Add SMS manager demo
diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml
index 6615d71..1e3f66b 100644
--- a/samples/ApiDemos/AndroidManifest.xml
+++ b/samples/ApiDemos/AndroidManifest.xml
@@ -29,6 +29,8 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_SMS" />
<!-- We will request access to the camera, saying we require a camera
of some sort but not one with autofocus capability. -->
@@ -651,6 +653,23 @@
</intent-filter>
</activity>
+ <activity android:name=".os.SmsMessagingDemo" android:label="OS/SMS Messaging">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".os.SmsReceivedDialog"
+ android:theme="@android:style/Theme.Translucent.NoTitleBar"
+ android:launchMode="singleInstance" />
+
+ <receiver android:name=".os.SmsMessageReceiver" android:enabled="false">
+ <intent-filter>
+ <action android:name="android.provider.Telephony.SMS_RECEIVED" />
+ </intent-filter>
+ </receiver>
+
<!-- ************************************* -->
<!-- ANIMATION PACKAGE SAMPLES -->
<!-- ************************************* -->
diff --git a/samples/ApiDemos/res/layout/sms_demo.xml b/samples/ApiDemos/res/layout/sms_demo.xml
new file mode 100644
index 0000000..1074f52
--- /dev/null
+++ b/samples/ApiDemos/res/layout/sms_demo.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Demonstrates sending and receiving SMS messages.
+ See corresponding Java code SmsMessagingDemo.java
+-->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="6dip">
+ <TextView
+ android:textColor="#ff0000"
+ android:textStyle="bold"
+ android:text="@string/sms_warning"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ <CheckBox
+ android:id="@+id/sms_enable_receiver"
+ android:text="@string/sms_enable_receiver"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ <TableLayout
+ android:padding="6dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:stretchColumns="1">
+ <TableRow android:layout_width="match_parent">
+ <TextView android:text="@string/sms_recipient_label" />
+ <EditText android:id="@+id/sms_recipient" />
+ </TableRow>
+ <TableRow>
+ <TextView android:text="@string/sms_content_label" />
+ <EditText android:id="@+id/sms_content" />
+ </TableRow>
+ <TableRow>
+ <Button
+ android:id="@+id/sms_send_message"
+ android:text="@string/sms_send_message"
+ android:layout_column="1" />
+ </TableRow>
+ <TableRow>
+ <TextView
+ android:id="@+id/sms_status"
+ android:layout_column="1" />
+ </TableRow>
+ </TableLayout>
+ </LinearLayout>
+</ScrollView>
diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml
index c7bb84e..799d67f 100644
--- a/samples/ApiDemos/res/values/strings.xml
+++ b/samples/ApiDemos/res/values/strings.xml
@@ -879,5 +879,21 @@
<string name="appwidget_configure_instructions">This text will be shown before the date in our example widget.</string>
<string name="appwidget_prefix_default">Oh hai</string>
<string name="appwidget_text_format"><xliff:g id="prefix">%1$s</xliff:g>: <xliff:g id="time">%2$s</xliff:g></string>
+
+ <!-- ============================ -->
+ <!-- SMS Messaging examples strings -->
+ <!-- ============================ -->
+
+ <string name="sms_warning">
+ WARNING: this demo can send actual text messages (one at a time), so be sure to
+ test with the Android emulator or have a text messaging plan with your carrier.
+ </string>
+ <string name="sms_enable_receiver">Enable SMS broadcast receiver</string>
+ <string name="sms_recipient_label">Recipient #</string>
+ <string name="sms_content_label">Message Body</string>
+ <string name="sms_send_message">Send</string>
+ <string name="sms_speak_string_format">Message from "%1$s": %2$s</string>
+ <string name="reply">Reply</string>
+ <string name="dismiss">Dismiss</string>
</resources>
diff --git a/samples/ApiDemos/src/com/example/android/apis/os/SmsMessageReceiver.java b/samples/ApiDemos/src/com/example/android/apis/os/SmsMessageReceiver.java
new file mode 100644
index 0000000..ec80955
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/os/SmsMessageReceiver.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.os;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.ContactsContract;
+import android.telephony.SmsMessage;
+
+public class SmsMessageReceiver extends BroadcastReceiver {
+ /** Tag string for our debug logs */
+ private static final String TAG = "SmsMessageReceiver";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Bundle extras = intent.getExtras();
+ if (extras == null)
+ return;
+
+ Object[] pdus = (Object[]) extras.get("pdus");
+
+ for (int i = 0; i < pdus.length; i++) {
+ SmsMessage message = SmsMessage.createFromPdu((byte[]) pdus[i]);
+ String fromAddress = message.getOriginatingAddress();
+ String fromDisplayName = fromAddress;
+
+ Uri uri;
+ String[] projection;
+
+ // If targeting Donut or below, use
+ // Contacts.Phones.CONTENT_FILTER_URL and
+ // Contacts.Phones.DISPLAY_NAME
+ uri = Uri.withAppendedPath(
+ ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
+ Uri.encode(fromAddress));
+ projection = new String[] { ContactsContract.PhoneLookup.DISPLAY_NAME };
+
+ // Query the filter URI
+ Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);
+ if (cursor != null) {
+ if (cursor.moveToFirst())
+ fromDisplayName = cursor.getString(0);
+
+ cursor.close();
+ }
+
+ // Trigger the main activity to fire up a dialog that shows/reads the received messages
+ Intent di = new Intent();
+ di.setClass(context, SmsReceivedDialog.class);
+ di.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ di.putExtra(SmsReceivedDialog.SMS_FROM_ADDRESS_EXTRA, fromAddress);
+ di.putExtra(SmsReceivedDialog.SMS_FROM_DISPLAY_NAME_EXTRA, fromDisplayName);
+ di.putExtra(SmsReceivedDialog.SMS_MESSAGE_EXTRA, message.getMessageBody().toString());
+ context.startActivity(di);
+
+ // For the purposes of this demo, we'll only handle the first received message.
+ break;
+ }
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/os/SmsMessagingDemo.java b/samples/ApiDemos/src/com/example/android/apis/os/SmsMessagingDemo.java
new file mode 100644
index 0000000..94f4e5a
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/os/SmsMessagingDemo.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.os;
+
+import java.util.List;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.telephony.SmsManager;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+
+import com.example.android.apis.R;
+
+public class SmsMessagingDemo extends Activity {
+ /** Tag string for our debug logs */
+ private static final String TAG = "SmsMessagingDemo";
+
+ public static final String SMS_RECIPIENT_EXTRA = "com.example.android.apis.os.SMS_RECIPIENT";
+
+ public static final String ACTION_SMS_SENT = "com.example.android.apis.os.SMS_SENT_ACTION";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.sms_demo);
+
+ if (getIntent().hasExtra(SMS_RECIPIENT_EXTRA)) {
+ ((TextView) findViewById(R.id.sms_recipient)).setText(getIntent().getExtras()
+ .getString(SMS_RECIPIENT_EXTRA));
+ ((TextView) findViewById(R.id.sms_content)).requestFocus();
+ }
+
+ // Enable or disable the broadcast receiver depending on the checked
+ // state of the checkbox.
+ CheckBox enableCheckBox = (CheckBox) findViewById(R.id.sms_enable_receiver);
+
+ final PackageManager pm = this.getPackageManager();
+ final ComponentName componentName = new ComponentName("com.example.android.apis",
+ "com.example.android.apis.os.SmsMessageReceiver");
+
+ enableCheckBox.setChecked(pm.getComponentEnabledSetting(componentName) ==
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+
+ enableCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ Log.d(TAG, (isChecked ? "Enabling" : "Disabling") + " SMS receiver");
+
+ pm.setComponentEnabledSetting(componentName,
+ isChecked ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
+ }
+ });
+
+ final EditText recipientTextEdit = (EditText) SmsMessagingDemo.this
+ .findViewById(R.id.sms_recipient);
+ final EditText contentTextEdit = (EditText) SmsMessagingDemo.this
+ .findViewById(R.id.sms_content);
+ final TextView statusView = (TextView) SmsMessagingDemo.this.findViewById(R.id.sms_status);
+
+ // Watch for send button clicks and send text messages.
+ Button sendButton = (Button) findViewById(R.id.sms_send_message);
+ sendButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ if (TextUtils.isEmpty(recipientTextEdit.getText())) {
+ Toast.makeText(SmsMessagingDemo.this, "Please enter a message recipient.",
+ Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ if (TextUtils.isEmpty(contentTextEdit.getText())) {
+ Toast.makeText(SmsMessagingDemo.this, "Please enter a message body.",
+ Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ recipientTextEdit.setEnabled(false);
+ contentTextEdit.setEnabled(false);
+
+ SmsManager sms = SmsManager.getDefault();
+
+ List<String> messages = sms.divideMessage(contentTextEdit.getText().toString());
+
+ String recipient = recipientTextEdit.getText().toString();
+ for (String message : messages) {
+ sms.sendTextMessage(recipient, null, message, PendingIntent.getBroadcast(
+ SmsMessagingDemo.this, 0, new Intent(ACTION_SMS_SENT), 0), null);
+ }
+ }
+ });
+
+ // Register broadcast receivers for SMS sent and delivered intents
+ registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String message = null;
+ boolean error = true;
+ switch (getResultCode()) {
+ case Activity.RESULT_OK:
+ message = "Message sent!";
+ error = false;
+ break;
+ case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
+ message = "Error.";
+ break;
+ case SmsManager.RESULT_ERROR_NO_SERVICE:
+ message = "Error: No service.";
+ break;
+ case SmsManager.RESULT_ERROR_NULL_PDU:
+ message = "Error: Null PDU.";
+ break;
+ case SmsManager.RESULT_ERROR_RADIO_OFF:
+ message = "Error: Radio off.";
+ break;
+ }
+
+ recipientTextEdit.setEnabled(true);
+ contentTextEdit.setEnabled(true);
+ contentTextEdit.setText("");
+
+ statusView.setText(message);
+ statusView.setTextColor(error ? Color.RED : Color.GREEN);
+ }
+ }, new IntentFilter(ACTION_SMS_SENT));
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/os/SmsReceivedDialog.java b/samples/ApiDemos/src/com/example/android/apis/os/SmsReceivedDialog.java
new file mode 100644
index 0000000..0df93a7
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/os/SmsReceivedDialog.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.os;
+
+import java.util.Locale;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.TextToSpeech.OnInitListener;
+import android.util.Log;
+
+import com.example.android.apis.R;
+
+public class SmsReceivedDialog extends Activity implements OnInitListener {
+ private static final String TAG = "SmsReceivedDialog";
+
+ private static final int DIALOG_SHOW_MESSAGE = 1;
+
+ public static final String SMS_FROM_ADDRESS_EXTRA = "com.example.android.apis.os.SMS_FROM_ADDRESS";
+ public static final String SMS_FROM_DISPLAY_NAME_EXTRA = "com.example.android.apis.os.SMS_FROM_DISPLAY_NAME";
+ public static final String SMS_MESSAGE_EXTRA = "com.example.android.apis.os.SMS_MESSAGE";
+
+ private TextToSpeech mTts;
+
+ private String mFromDisplayName;
+ private String mFromAddress;
+ private String mMessage;
+ private String mFullBodyString;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mFromAddress = getIntent().getExtras().getString(SMS_FROM_ADDRESS_EXTRA);
+ mFromDisplayName = getIntent().getExtras().getString(SMS_FROM_DISPLAY_NAME_EXTRA);
+ mMessage = getIntent().getExtras().getString(SMS_MESSAGE_EXTRA);
+
+ mFullBodyString = String.format(
+ getResources().getString(R.string.sms_speak_string_format),
+ mFromDisplayName,
+ mMessage);
+
+ showDialog(DIALOG_SHOW_MESSAGE);
+ mTts = new TextToSpeech(this, this);
+ }
+
+ public void onInit(int status) {
+ if (status == TextToSpeech.SUCCESS) {
+ int result = mTts.setLanguage(Locale.US);
+ if (result == TextToSpeech.LANG_MISSING_DATA
+ || result == TextToSpeech.LANG_NOT_SUPPORTED) {
+ Log.e(TAG, "TTS language is not available.");
+ } else {
+ mTts.speak(mFullBodyString, TextToSpeech.QUEUE_ADD, null);
+ }
+ } else {
+ // Initialization failed.
+ Log.e(TAG, "Could not initialize TTS.");
+ }
+ }
+
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ switch (id) {
+ case DIALOG_SHOW_MESSAGE:
+ return new AlertDialog.Builder(this)
+ .setIcon(android.R.drawable.ic_dialog_email)
+ .setTitle("Message Received")
+ .setMessage(mFullBodyString)
+ .setPositiveButton(R.string.reply, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+ // Begin creating the reply with the SmsMessagingDemo activity
+ Intent i = new Intent();
+ i.setClass(SmsReceivedDialog.this, SmsMessagingDemo.class);
+ i.putExtra(SmsMessagingDemo.SMS_RECIPIENT_EXTRA, mFromAddress);
+ startActivity(i);
+
+ dialog.dismiss();
+ finish();
+ }
+ })
+ .setNegativeButton(R.string.dismiss, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+ dialog.dismiss();
+ finish();
+ }
+ })
+ .setOnCancelListener(new DialogInterface.OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ finish();
+ }
+ }).create();
+ }
+ return null;
+ }
+}