📜 ⬆️ ⬇️

Monitoring messages and calls to Android

On the Android project I am developing, it became necessary to monitor incoming and outgoing calls and messages. It is useful to read the documentation and books at hand, and unfortunately I realized that the task is not entirely trivial, since each part of one problem requires a different approach to implementation. In general, I noticed that many books or articles are always trying to give lighter examples, such as processing an incoming message, but about the outgoing word, if the implementation is more complicated. Perhaps this is my prejudice, but not the first time I pay attention to this
I decided to put it all together and share it with those who might fill the edge with themselves trying to find a solution to this problem. I do not pretend to optimality, as I study myself


Monitoring incoming messages



Probably the implementation of this part of the most simple and easy. In the application manifest, we give permission to process the receipt of a message.
')
<uses-permission android:name="android.permission.RECEIVE_SMS"/> 


And register the Receiver, which will be triggered by the event of the incoming message

 <receiver android:name="MessageReceiver" android:enabled="true"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver> 


As can be seen from the example code, upon receipt of a message, control will be transferred to Receiver-from MessageReceiver.

Sample implementation:

 public class MessageReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); if (bundle != null) { Object[] pdus = (Object[]) bundle.get("pdus"); SmsMessage[] msgs = new SmsMessage[pdus.length]; ArrayList<String> numbers = new ArrayList<String>(); ArrayList<String> messages = new ArrayList<String>(); for (int i=0; i<msgs.length; i++){ //     msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]); numbers.add(msgs[i].getOriginatingAddress()); //   messages.add(msgs[i].getMessageBody().toString());//   } if (messages.size() > 0){ // -   } } } } 


Outgoing message monitoring



Unfortunately, outgoing messages are not as easy as incoming ones. The Telephony API does not provide a separate outbound message event. To me, this looks quite strange in a rather polished product, which is Android. Nevertheless, the solution is still there.

In the application manifest, we give permission to read messages

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


And then you should create and register a message base change handler. In the workplace, you can combine the processing of incoming and outgoing messages, but somehow with the incoming messages, everything is much simpler. When processing outgoing messages, you should consider the fact that the handler can be called several times when sending the same message. It is recommended to create a hash table of all messages to check if there is no processed message in the database. The code below shows a primitive check by message id

 private static final String CONTENT_SMS = "content://sms/"; private static long id = 0; //     ContentResolver contentResolver = getBaseContext().getContentResolver(); contentResolver.registerContentObserver(Uri.parse(CONTENT_SMS),true, new OutgoingSmsObserver(new Handler())); private class OutgoingSmsObserver extends ContentObserver { @Override public void onChange(boolean selfChange) { super.onChange(selfChange); Uri uriSMSURI = Uri.parse(CONTENT_SMS); Cursor cur = getContentResolver().query(uriSMSURI, null, null,null, null); cur.moveToNext(); String protocol = cur.getString(cur.getColumnIndex("protocol")); if(protocol == null){ long messageId = cur.getLong(cur.getColumnIndex("_id")); //       - if (messageId != id){ id = messageId; int threadId = cur.getInt(cur.getColumnIndex("thread_id")); Cursor c = getContentResolver().query(Uri.parse("content://sms/outbox/" + threadId), null, null, null, null); c.moveToNext(); //   String address = cur.getString(cur.getColumnIndex("address")); //   String body= cur.getString(cur.getColumnIndex("body")); // -   } } } } 


Call monitoring



Android provides the ability to monitor the status of the phone through the action android.intent.action.PHONE_STATE, but again I still have the problem of getting the subscriber number on an outgoing call, so I had to register the receiver for two actions.

In the application manifest, we give permission to read the state of the phone and handle outgoing calls.

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


And register the Receiver, which will be triggered by the event of the incoming message

 <receiver android:name="CallReceiver"> <intent-filter> <action android:name="android.intent.action.PHONE_STATE"/> <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> </intent-filter> </receiver> 


Sample implementation:

 String phoneNumber = ""; public class CallReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) { //   phoneNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER"); } else if (intent.getAction().equals("android.intent.action.PHONE_STATE")){ String phone_state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); if (phone_state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { // ,    phoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER); } else if (phone_state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){ //     (  / ) } else if (phone_state.equals(TelephonyManager.EXTRA_STATE_IDLE)){ //    .      ,         } } } } 


Summarizing the problems that I described at the very beginning, I’ll say again that I didn’t have a feeling of some undifferentiated Android API. The incoming message is quite easily intercepted, which cannot be said about outgoing. The same goes for calls. Of course, you can use one solution for messages, but if it's so easy for incoming, then why is there no such simplicity for outgoing?

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


All Articles