Working with messaging SMS

SMS is a hugely popular and important means of communication for mobile devices. SMS is used to send simple text messages and small amounts of data. Android includes a built-in SMS application that allows users to view received SMS messages and send messages (including replying to received messages). Along with the built-in user-facing support and the related ContentProvider for interacting with the built-in system, the SDK provides APIs for developers to be able to send and receive messages programmatically.

To explore this support we are going to look at both sides of the coin, sending and receiving. The unadorned screen in figure 7.4 shows the SMS-related Activity we will build in the Tele-phonyExplorer application.

To get started working with SMS, we will send SMS messages using the support provided by the SmsManager.

7.4.1 Sending SMS messages

The android.telephony.gsm subpackage contains the SmsManager and SmsMessage classes. These are our SMS friends. The SmsManager is used to define many important SMS-related constants, and it contains the sendDataMessage, sendMultipartTextMessage, and sendTextMessage methods.

In listing 7.7 we have an example from our TelephonyExplorer application of using the SMS manager to send a simple text message.



Enter de small or number:

Enter de small or number:

SMS RECEIVED body - wootl

Figure 7.4 An Activity that sends SMS messages and an example of an alert based on a received SMS message

Listing 7.7 Using the SmsManager to send SMS messages

// . . . start of class omitted for brevity private Button smsSend; private SmsManager smsManager;

@Override public void onCreate(Bundle icicle) { super.onCreate(icicle);


// . . . other onCreate view item inflation omitted for brevity this.smsSend = (Button) findViewByld(; this . smsManager = SmsManager. getDefault () ; ^-1 get SmsManager final PendingIntent sentlntent = PendingIntent.getActivity( this, 0, new Intent (this, SmsSendCheck.class), 0);

C Create PendingIntent handle for post action this . smsSend.setOnClickListener(new OnClickListener() { public void onClick(View v) {

String dest = smslnputDest.getText().toString(); i f (PhoneNumbe rUt ils.

isWellFormedSmsAddress(dest) ) { - | Check destination smsManager.sendTextMessage( smslnputDest.getText().toString, null, smslnputText.getText().toString(),

I Check destinatio D is valid sentIntent, null); <—© Send message

Toast.makeText(SmsExample.this, "SMS message sent", Toast. LENGTH_LONG).show(); } else {

Toast.makeText(SmsExample.this, "SMS destination invalid - try again", Toast. LENGTH_LONG).show();

The first thing we need to do in regard to working with SMS messages is obtain an instance of the SmsManager, which is done with the static getDefault method O. The manager will be used later to send the message. Before we can do that, though, we need to create a PendingIntent (which will be used as a parameter in the send method coming up).

What is a PendingIntent?

A PendingIntent is a specification of a future intent. It is basically a way for you to pass a future Intent to another application and allow that application to execute that Intent as if it had the same permissions as your application, whether or not your application is still around when the Intent is eventually invoked. Remember the Activity lifecycle and the separate process logic that the platform uses. A PendingIntent provides a means for applications to, in essence, work "beyond the grave" for a particular Intent. Even after an owning application that creates a PendingIntent has been killed, that Intent can still be run later.

A PendingIntent can specify an Activity, Broadcast, or Service that it requires. In our case we are using the getActivity method, which denotes an Activity, and then we are specifying the context, request code (which is unused), the Intent, and additional flags C. The flags indicate whether or not a new instance of the referenced Activity (or Broadcast or Service) should be created if one does not already exist.

Once we have a PendingIntent, we check that the destination address is valid for SMS (using another method from PhoneNumberUtils) ©, and we send the message using the manager's sendTextMessage method ©.

This send method takes in several parameters, one of which can be confusing. The signature of this method is as follows:

sendDataMessage(String destinationAddress, String scAddress, short destinationPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent)

The destinationAddress is simple; this is the phone number you want to send the message to. The scAddress is the tricky one. This is not meant to be the source address, but rather it indicates the internal service center address on the network; this should be left null in most cases (which uses the default). The destinationPort is also simple; it's the port. The data is the payload of the message. Finally, the sent-Intent and deliverylntent are separate PendingIntent instances that are fired when the message is successfully sent and received, respectively.

Much like the permissions we listed in table 7.1 in reference to phone permissions, SMS-related tasks also require manifest permissions. The SMS-related permissions are shown in table 7.2.

Table 7.2 SMS-related manifest permissions and their purpose

Phone-related permission


android.permission.RECEIVE_SMS android.permission.READ_SMS android.permission.SEND_SMS android.permission.WRITE_SMS

Allow application to monitor incoming SMS messages

Allow application to read SMS messages

Allow application to send SMS messages

Write SMS messages to the built-in SMS provider (not related to sending messages directly)

Along with sending text and data messages using this basic pattern, you can create an SMS-related BroadcastReceiver to receive incoming SMS messages.

7.4.2 Receiving SMS messages

Receiving an SMS message programmatically is done through receiving a broadcast on the Android platform. To demonstrate this with our TelephonyExplorer application, we are again going to implement a receiver, as shown in listing 7.8.

Listing 7.8 Creating an SMS-related BroadcastReceiver public class SmsReceiver extends BroadcastReceiver { <1-1

public static final String SMSRECEIVED = "SMSR"; O private static final String SMS_REC_ACTION = "android.provider.Telephony.SMS_RECEIVED";

@Override public void onReceive(fContext context, Intent intent) {



Define constant SMS_RECEIVED action if (intent.getAction().

StringBuilder sb = new StringBuilder(); ©

Filter for action in receiver

Bundle bundle = intent.getExtras(); if (bundle != null) {

Object [] pdus = (Object []) bundle .get ("pdus") ; for (Object pdu : pdus) { SmsMessage smsMessage =

SmsMessage.createFromPdu((byte[]) pdu) ; sb.append("body - "

+ smsMessage.getDisplayMessageBody());

Get pdus from Intent Bundle

F Create SmsMessage <,J from pdus

I Get message G body for display

Toast.makeText(context, "SMS RECEIVED - " + sb.toString(), Toast.LENGTH_LONG).show();

To react to an incoming SMS message we once again are creating a BroadcastReceiver by extending that class O. Our receiver defines a local constant for the Intent action it wants to catch, in this case android.provider.Telephony.SMS_RECEIVED C.

Once the class setup is ready, we filter for the action we want in the onReceive method ©, and we get the SMS data from the Intent "extras" Bundle using the key pdus ©. PDU, or Protocol Data Unit, is the term that describes the data packet in SMS messages. In this case the platform is using the String key pdus (we discovered this by trial and error, by getting the key Set from the Bundle and iterating it). For every pdu Object we then construct an SmsMessage by casting the data to a byte array ©. Once this is in SmsMessage form, we can work with the methods on that class, such as get-DisplayMessageBody ©.

Sending and receiving messages in SMS form completes our exploration of the telephony APIs.

0 0


  • bobbi
    What is the destination port ib android sendDataMessage and qhat ia the phone number entered?
    2 years ago

Post a comment