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