Home | History | Annotate | Download | only in smssample
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.smssample;
     18 
     19 import android.content.Context;
     20 import android.content.Intent;
     21 import android.database.Cursor;
     22 import android.net.Uri;
     23 import android.os.Bundle;
     24 import android.provider.Telephony.Sms.Inbox;
     25 import android.support.v4.app.FragmentActivity;
     26 import android.support.v4.app.LoaderManager.LoaderCallbacks;
     27 import android.support.v4.content.CursorLoader;
     28 import android.support.v4.content.Loader;
     29 import android.support.v4.widget.SimpleCursorAdapter;
     30 import android.telephony.TelephonyManager;
     31 import android.text.TextUtils;
     32 import android.view.Menu;
     33 import android.view.View;
     34 import android.view.View.OnClickListener;
     35 import android.widget.Button;
     36 import android.widget.EditText;
     37 import android.widget.ListView;
     38 import android.widget.RelativeLayout;
     39 import android.widget.Toast;
     40 
     41 /**
     42  * The main Activity that provides a sample of a few things:
     43  *   -detecting if this app is the default SMS app and then showing/hiding UI and enabling/disabling
     44  *    functionality. the UI that is shown has a button to prompt the user to set this app as the
     45  *    default.
     46  *   -a simple query to the SMS content provider to show a list of SMS messages in the inbox. even
     47  *    though the query uses KitKat APIs this query should still work on earlier versions of Android
     48  *    as the contract class and ContentProvider were still around (with essentially the same
     49  *    structure) but were private.
     50  *   -being triggered from another application when creating a new SMS. a good example is creating
     51  *    a new SMS from the system People application. although nothing is done with the incoming
     52  *    Intent in this case (just a Toast is displayed)
     53  *
     54  *  Obviously this is far from a full implementation and should just be used as a sample of how
     55  *  an app could be set up to correctly integrate with the new Android 4.4 KitKat APIs while
     56  *  running normally on earlier Android versions.
     57  */
     58 public class MainActivity extends FragmentActivity implements LoaderCallbacks<Cursor> {
     59     private RelativeLayout mSetDefaultSmsLayout;
     60     private Button mSendSmsButton;
     61     private EditText mSendSmsEditText;
     62     private SimpleCursorAdapter mAdapter;
     63 
     64     @Override
     65     protected void onCreate(Bundle savedInstanceState) {
     66         super.onCreate(savedInstanceState);
     67         setContentView(R.layout.activity_main);
     68 
     69         // Find some views
     70         mSetDefaultSmsLayout = (RelativeLayout) findViewById(R.id.set_default_sms_layout);
     71         mSendSmsEditText = (EditText) findViewById(R.id.send_sms_edittext);
     72         ListView listView = (ListView) findViewById(android.R.id.list);
     73         listView.setEmptyView(findViewById(android.R.id.empty));
     74         mSendSmsButton = (Button) findViewById(R.id.send_sms_button);
     75         mSendSmsButton.setOnClickListener(new OnClickListener() {
     76             @Override
     77             public void onClick(View view) {
     78                 sendSms(mSendSmsEditText.getText().toString());
     79             }
     80         });
     81 
     82         // Create adapter and set it to our ListView
     83         final String[] fromFields = new String[] {
     84                 SmsQuery.PROJECTION[SmsQuery.ADDRESS], SmsQuery.PROJECTION[SmsQuery.BODY] };
     85         final int[] toViews = new int[] { android.R.id.text1, android.R.id.text2 };
     86         mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, null,
     87                 fromFields, toViews, 0);
     88         listView.setAdapter(mAdapter);
     89 
     90         // Placeholder to process incoming SEND/SENDTO intents
     91         String intentAction = getIntent() == null ? null : getIntent().getAction();
     92         if (!TextUtils.isEmpty(intentAction) && (Intent.ACTION_SENDTO.equals(intentAction)
     93                 || Intent.ACTION_SEND.equals(intentAction))) {
     94             // TODO: Handle incoming SEND and SENDTO intents by pre-populating UI components
     95             Toast.makeText(this, "Handle SEND and SENDTO intents: " + getIntent().getDataString(),
     96                     Toast.LENGTH_SHORT).show();
     97         }
     98 
     99         // Simple query to show the most recent SMS messages in the inbox
    100         getSupportLoaderManager().initLoader(SmsQuery.TOKEN, null, this);
    101     }
    102 
    103     /**
    104      * Dummy sendSms method, would need the "to" address to actually send a message :)
    105      */
    106     private void sendSms(String smsText) {
    107         if (!TextUtils.isEmpty(smsText)) {
    108             if (Utils.isDefaultSmsApp(this)) {
    109                 // TODO: Use SmsManager to send SMS and then record the message in the system SMS
    110                 // ContentProvider
    111                 Toast.makeText(this, "Sending text message: " + smsText, Toast.LENGTH_SHORT).show();
    112             } else {
    113                 // TODO: Notify the user the app is not default and provide a way to trigger
    114                 // Utils.setDefaultSmsApp() so they can set it.
    115                 Toast.makeText(this, "Not default", Toast.LENGTH_SHORT).show();
    116             }
    117         }
    118     }
    119 
    120     @Override
    121     protected void onResume() {
    122         super.onResume();
    123 
    124         // Only do these checks/changes on KitKat+, the "mSetDefaultSmsLayout" has its visibility
    125         // set to "gone" in the xml layout so it won't show at all on earlier Android versions.
    126         if (Utils.hasKitKat()) {
    127             if (Utils.isDefaultSmsApp(this)) {
    128                 // This app is the default, remove the "make this app the default" layout and
    129                 // enable message sending components.
    130                 mSetDefaultSmsLayout.setVisibility(View.GONE);
    131                 mSendSmsEditText.setHint(R.string.sms_send_new_hint);
    132                 mSendSmsEditText.setEnabled(true);
    133                 mSendSmsButton.setEnabled(true);
    134             } else {
    135                 // Not the default, show the "make this app the default" layout and disable
    136                 // message sending components.
    137                 mSetDefaultSmsLayout.setVisibility(View.VISIBLE);
    138                 mSendSmsEditText.setText("");
    139                 mSendSmsEditText.setHint(R.string.sms_send_disabled);
    140                 mSendSmsEditText.setEnabled(false);
    141                 mSendSmsButton.setEnabled(false);
    142 
    143                 Button button = (Button) findViewById(R.id.set_default_sms_button);
    144                 button.setOnClickListener(new OnClickListener() {
    145                     @Override
    146                     public void onClick(View view) {
    147                         Utils.setDefaultSmsApp(MainActivity.this);
    148                     }
    149                 });
    150             }
    151         }
    152         String phoneNumberToast = "Unable to obtain phone number (not default SMS app?)";
    153         final TelephonyManager telephony =
    154                 (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
    155         try {
    156             phoneNumberToast = "Phone number: " + telephony.getLine1Number();
    157         } catch (SecurityException e) {
    158         }
    159         Toast.makeText(this, phoneNumberToast, Toast.LENGTH_SHORT).show();
    160     }
    161 
    162     @Override
    163     public boolean onCreateOptionsMenu(Menu menu) {
    164         // Inflate the menu; this adds items to the action bar if it is present.
    165         getMenuInflater().inflate(R.menu.main, menu);
    166         return true;
    167     }
    168 
    169     @Override
    170     public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
    171         if (i == SmsQuery.TOKEN) {
    172             // This will fetch all SMS messages in the inbox, ordered by date desc
    173             return new CursorLoader(this, SmsQuery.CONTENT_URI, SmsQuery.PROJECTION, null, null,
    174                     SmsQuery.SORT_ORDER);
    175         }
    176         return null;
    177     }
    178 
    179     @Override
    180     public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
    181         if (cursorLoader.getId() == SmsQuery.TOKEN && cursor != null) {
    182             // Standard swap cursor in when load is done
    183             mAdapter.swapCursor(cursor);
    184         }
    185     }
    186 
    187     @Override
    188     public void onLoaderReset(Loader<Cursor> cursorLoader) {
    189         // Standard swap cursor to null when loader is reset
    190         mAdapter.swapCursor(null);
    191     }
    192 
    193     /**
    194      * A basic SmsQuery on android.provider.Telephony.Sms.Inbox
    195      */
    196     private interface SmsQuery {
    197         int TOKEN = 1;
    198 
    199         static final Uri CONTENT_URI = Inbox.CONTENT_URI;
    200 
    201         static final String[] PROJECTION = {
    202                 Inbox._ID,
    203                 Inbox.ADDRESS,
    204                 Inbox.BODY,
    205         };
    206 
    207         static final String SORT_ORDER = Inbox.DEFAULT_SORT_ORDER;
    208 
    209         int ID = 0;
    210         int ADDRESS = 1;
    211         int BODY = 2;
    212     }
    213 }
    214