Using SMS Android

SMS usage has become ubiquitous in the last several years. Integrating messaging services, even if only outbound, to an application can provide familiar social functionality to the user. SMS functionality is provided to applications through the android.telephony package.

Screen showing formatting results after entering only digits.

Screen showing formatting results after entering only digits

Gaining Permission to Send and Receive SMS Messages

SMS functionality requires two different permissions, depending on if the application sends or receives messages. The following XML, to be placed with Android Manifest .xml, shows the permissions needed for both actions:

<uses-permission
android:name=”android.permission.SEND_SMS” />
<uses-permission
android:name=”android.permission.RECEIVE_SMS” />

Sending an SMS

To send an SMS, an application first needs to get an instance of the SmsManager. Unlike other system services, this is achieved by calling the static method get Default() of SmsManager:

final SmsManager sms = SmsManager.getDefault();

Now that the application has the SmsManager, sending SMS is as simple as a single call:

sms.sendTextMessage(
“9995551212”, null, “Hello!”, null, null);

The application does not know if the actual sending of the SMS was successful without providing a PendingIntent to receive the broadcast of this information. The following code demonstrates configuring a PendingIntent to listen for the status of the SMS:

Intent msgSent = new Intent(“ACTION_MSG_SENT”);
final PendingIntent pendingMsgSent =
PendingIntent.getBroadcast(this, 0, msgSent, 0);
registerReceiver(new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
int result = getResultCode();
if (result != Activity.RESULT_OK) {
Log.e(“telephony”,
“SMS send failed code = “ + result);
pendingMsgReceipt.cancel();
} else {
messageEntry.setText(““);
}
}
}, new IntentFilter(“ACTION_MSG_SENT”));

The PendingIntent pendingMsgSent can be used with the call to the sendText Message(). The code for the message-received receipt is similar but is called when the sending handset receives acknowledgment from the network that the destination handset received the message.

If we put all this together with the preceding phone number formatting EditText, a new entry field for the message, and a button, we can create a simple form for sending an SMS message. The code for the button handling looks like the following:

Button sendSMS = (Button) findViewById(R.id.send_sms);
sendSMS.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String destination =
numberEntry.getText().toString();
String message =
messageEntry.getText().toString();
sms.sendTextMessage(destination, null, message,
pendingMsgSent, pendingMsgReceipt);
registerReceiver(...);
}
}

After this code is hooked in, the result should look something like Figure.Within this application, we used the emulator “phone number” trick (its port number).This is a great way to test sending SMS messages without using hardware or without incurring charges by the handset operator.

Two emulators, one sending an SMS from an application and one receiving an SMS.

Two emulators, one sending an SMS from an application and one receiving an SMS

A great way to extend this would be to set the sent receiver to modify a graphic on the screen until the sent notification is received. Further, you could use another graphic to indicate when the recipient has received the message. Alternatively, you could use ProgressBar widgets track the progress to the user.

Receiving an SMS

Applications can also receive SMS messages. To do so, your application must register a BroadcastReceiver to listen for the Intent action associated with receiving an SMS. An application listening to SMS in this way doesn’t prevent the message from getting to other applications.

Expanding on the previous example, the following code shows how any incoming text message can be placed within a TextView on the screen:

final TextView receivedMessage = (TextView)findViewById(
R.id.received_message);
rcvIncoming = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
Log.i(“telephony”, “SMS received”);
Bundle data = intent.getExtras();
if (data != null) {
Object pdus[] =
(Object[]) data.get(“pdus”);
String message = “New message: ”;
String sender = null;
for (Object pdu : pdus) {
SmsMessage part = SmsMessage.
createFromPdu((byte[])pdu);
message += part.
getDisplayMessageBody();
(sender == null) {
sender = part.
getDisplayOriginatingAddress();
} }
receivedMessage.setText(
message + “ From: “+sender);
numberEntry.setText(sender);
}
}
};
registerReceiver(rcvIncoming, new IntentFilter(
“android.provider.Telephony.SMS_RECEIVED”));

This block of code is placed within the onCreate() method of the Activity. First, the message Bundle is retrieved. In it, an array of Objects holds several byte arrays that contain PDU data—the data format that is customarily used by wireless messaging protocols. Luckily, the Android SDK can decode these with a call to the static SmsMessage.createFromPdu() utility method. From here, we can retrieve the body of the SMS message by calling getDisplayMessageBody().

The message that comes in might be longer than the limitations for an SMS. If it is, it will have been broken up in to a multipart message on the sending side. To handle this, we loop through each of the received Object parts and take the corresponding body from each, while only taking the sender address from the first.

Next, the code updates the text string in the TextView to show the user the received message. The sender address is also updated so that the recipient can respond with less typing. Finally, we register the BroadcastReceiver with the system. The IntentFilter used here, android.provider.Telephony.SMS_RECEIVED, is a well-known but undocumented IntentFilter used for this. As such, we have to use the string literal for it.


All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

Android Topics