Showing posts with label SMS. Show all posts
Showing posts with label SMS. Show all posts

Wednesday, 16 April 2014

Hidden Android APIs: hiding SMS messages to the default SMS receiver

In a previous tutorial we saw how to take advantage of the hidden Android APIs to listen to incoming SMS messages.
Now suppose that we want to listen to specific SMS messages (messages coming from a particular number or containing specific strings) and to hide them to the default SMS receiver (like Google Hangout or other client).

This is a private message!

As in the previous tutorial we have to declare a BroadcastReceiver in the AndroidManifest.xml file. However, in order to take priority over the default SMS receiver, we also have to set a high priority for our SMS BroadcastReceiver:
<receiver android:name="com.androidthetechinalblog.SMSReceiver">
   <intent-filter android:priority="9999">
      <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
   </intent-filter>
</receiver>

Now we just have to make some minor changes to the SMSReceiver class:
public class SMSReceiver extends BroadcastReceiver {
 
 public void onReceive(Context context, Intent intent) {
  String action = intent.getAction();
 
  if(action.equals(“android.provider.Telephony.SMS_RECEIVED”)) {
   Object incomingSMSs[] = (Object[]) intent.getSerializableExtra(“pdus”);
    
   for(Object tmp : incomingSMSs) {
    byte message[] = (byte[]) tmp;
    SmsMessage smsMessage = SmsMessage.createFromPdu(message);

    String phoneNumber = smsMessage.getOriginatingAddress();
    String messageBody = smsMessage.getMessageBody();

    if(phoneNumber.equals("3457148596") || messageBody.contains("test")) {
       //we have found our SMS! here you can perform some actions
       abortBroadcast();
       setResultData(null);
    }
   }
  }
 }
}

As you can see, by calling abortBroadcast() and setResultData(null) (methods working only for "ordered broadcasts", like in our example) we make sure that our SMS won't be propagated to any other receiver.

Wednesday, 26 March 2014

Hidden Android APIs: listening to incoming SMS messages

In the Android platform there are two classes, SmsManager and SmsMessage, for sending SMS messages; hower there is no official class for receiving them. To be able to receive SMS messages we have to use a hidden API, present in the Android platform but not generally available for developers.
Hidden Android APIs contain several constants, methods, interfaces, etc. that can come in handy in a variety of situations.



To discover hidden Android APIs you can use the following resource:
  • AndroidXRef (http://androidxref.com): this site has indexed all the Android source code and offers a useful search box; however you have to know exactly what you are looking for.

Searching class Telephony from AndroidXRef


In order to make use of the Android hidden APIs, there are two possible scenarios:
  • constants: if you just need to use a hidden constant (for example for broacast actions), you can simply copy them from the Android source code into your app. In this tutorial we will use this technique;
  • methods, classes, interfaces, etc.: hidden methods, classes and interfaces must be compiled, before beeing able to use them. To do this you can either modify the SDK jar file used to compile your app, or make use of the java reflection method, each of which has its pros and cons.

To be able to receive incoming SMS messages we will use the following hidden constants contained in the class telephony-common (you can find them using the utilities listed above):
  • android.provider.Telephony.SMS_RECEIVED”: Intent action used in our BroadcastReceiver to listen to incoming SMS messages;
  • pdus”: constant used to retrieve SMS data from the Intent.

Extract from the class Telephony of the Android source code


Extract from the class Telephony of the Android source code


So here is the code:
  1. declare the use of the RECEIVE_SMS permission in the AndroidManifest.xml file;
  2. declare a BroadcastReceiver in the AndroidManifest.xml file with the intent-filter “android.provider.Telephony.SMS_RECEIVED”;
  3. implement the BroadcastReceiver as follows:


public class SMSReceiver extends BroadcastReceiver {

 public void onReceive(Context context, Intent intent) {
  String action = intent.getAction();

  if(action.equals(“android.provider.Telephony.SMS_RECEIVED”)) {
   Object incomingSMSs[] = (Object[]) intent.getSerializableExtra(“pdus”);
   
   for(Object tmp : incomingSMSs) {
    byte message[] = (byte[]) tmp;
    SmsMessage smsMessage = SmsMessage.createFromPdu(message);
   }
  }
 }
}

Once you have a SmsMessage object, you can use one ot its several methods to retrieve useful info about the SMS received:
smsMessage.getOriginatingAddress();
smsMessage.getMessageBody();
etc.