📜 ⬆️ ⬇️

Android: SMS Processing

0. Instead of entry


Periodically (when I have a free evening, and our “club” organizes the game) I play rugball. The “Club” is organized in such a way that on the day of the game all participants receive an SMS of the following type:

! 19-30. №30: . , 20. . . 8 (951) ***-**-**.

And so I thought - why not write a small application that will catch these messages, and fill them in the Google calendar. What for? Yes, basically, just for fun, because I’m not so busy a person that I need automatic secretaries.

So, the application will be able to do the following:

As part of this article, I believe that the reader has a basic knowledge of how to create a project, what a Manifest file is, and where to start development for android in general - there are a lot of different tutorials on this subject, and we will not dwell on this here. At the same time, the article is not intended for advanced android developers, it will deal with fairly basic things, such as monitoring and processing SMS, working with a database, connecting via HTTP.

So let's get started. By the way, the SDK version used is 14 (Android 4.0).
')

1. We intercept SMS


To monitor incoming SMS, we first need to request permission to receive them. To do this, you need to add an entry to the AndroidManifest.xml file:

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


The next step is to implement the monitor to listen for incoming messages. To do this, register the receiver in the manifest file:

 <receiver android:name="SMSMonitor"> <intent-filter android:priority="100"> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver> 


Here we set the priority to 100, so that our application can access the incoming SMS before the standard SMS handler, which has zero priority. After our application processes the message, it makes no sense to give it to the system, and put it in the Inbox.

Now create a class that extends BroadcastReceiver :

 public class SMSMonitor extends BroadcastReceiver { private static final String ACTION = "android.provider.Telephony.SMS_RECEIVED"; @Override public void onReceive(Context context, Intent intent) { } } 


This class implements the abstract onReceive() method, which is called by the system each time a message is received. In the method we write:

 if (intent != null && intent.getAction() != null && ACTION.compareToIgnoreCase(intent.getAction()) == 0) { Object[] pduArray = (Object[]) intent.getExtras().get("pdus"); SmsMessage[] messages = new SmsMessage[pduArray.length]; for (int i = 0; i < pduArray.length; i++) { messages[i] = SmsMessage.createFromPdu((byte[]) pduArray[i]); } } 


Here we get a message using the intent.getExtras().get("pdus") , which returns an array of objects in the PDU format — we then SmsMessage these objects to the SmsMessage type using the createFromPdu() method.

Now attention. What we do after receiving the message must be executed quickly . Broadcast receiver receives a high priority in the system, but it runs in the background and must be executed in a short time, so our capabilities are limited. For example, we can generate a notification or start a service to continue processing in it. Therefore, we will check the sender of the message, and if this is a notification about the game, we will pull out the text of the message and start the service, in which we will already process this message.

We add in the onReceive() method:

 String sms_from = messages[0].getDisplayOriginatingAddress(); if (sms_from.equalsIgnoreCase("RM FIGHT")) { StringBuilder bodyText = new StringBuilder(); for (int i = 0; i < messages.length; i++) { bodyText.append(messages[i].getMessageBody()); } String body = bodyText.toString(); Intent mIntent = new Intent(context, SmsService.class); mIntent.putExtra("sms_body", body); context.startService(mIntent); abortBroadcast(); } 


Here we compose the message text (in the case when the message was long and came in several SMS messages[i] , each separate part is stored in messages[i] ) and call the abortBroadcast() method to prevent further processing of the message by other applications.

2. We process SMS


In the previous paragraph, we stopped at the fact that we start the service for processing SMS using the startService() method. Actually, what services are and what they are eaten with is well described on the official site , therefore we will not dwell on this here.

Create the SmsService class that extends the Service class:

 public class SmsService extends Service { @Override public IBinder onBind(Intent intent) { return null; } } 


Since we have a local service, the onBind () method returns null.

To display notifications, we need the showNotification () helper method:

 private void showNotification(String text) { PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0); Context context = getApplicationContext(); Notification.Builder builder = new Notification.Builder(context) .setContentTitle("Rugball") .setContentText(text) .setContentIntent(contentIntent) .setSmallIcon(R.drawable.ic_launcher) .setAutoCancel(true); NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); Notification notification = builder.getNotification(); notificationManager.notify(R.drawable.ic_launcher, notification); } 


In the onStartCommand() method onStartCommand() write:

 @Override public int onStartCommand(Intent intent, int flags, int startId) { String sms_body = intent.getExtras().getString("sms_body"); showNotification(sms_body); return START_STICKY; } 


It remains, in fact, to implement the smsProcess() method, which will add SMS to the database and form an event in the Google calendar. We will deal with this in the next part of the article.

UPDATE: posted the code on github . I don’t have time with the second part of the article, I’m too busy at work. I hope to deal with this issue in the near future.

Source: https://habr.com/ru/post/149555/


All Articles