9

I am interested in how I can figure out if SMS has been sent from the device.

In order to get notification when SMS is recieved, we use a broadcaster with:

android.provider.Telephony.SMS_RECEIVED

Important to mention that I do not send SMS from my app, I just should listen when SMS is sent from the device.

May be I should listen to some Content provider (which somehow related with SMS) and react for that change. Any ideas how I can achieve that?

Bali C
  • 29,317
  • 35
  • 118
  • 150
Jviaches
  • 835
  • 3
  • 14
  • 30

3 Answers3

16

Yes, It is possible to listen SMS ContentProvider by using ContentObserver

Here is my example for Outgoing SMS:

First register a ContetObserver with content://sms/

   public class Smssendservice extends Service{

       @Override  
       public void onCreate() {
            SmsContent content = new SmsContent(new Handler());  
            // REGISTER ContetObserver 
            this.getContentResolver().
                registerContentObserver(Uri.parse("content://sms/"), true, SMSObserver);  
       } 

       @Override
       public IBinder onBind(Intent arg0) {
            // TODO Auto-generated method stub

            return null;
       }

SMSObserver.class

       public class SMSObserver extends ContentObserver {
            private Handler m_handler = null;

            public SMSObserver(SMSLogger handler){
                 super(handler);
                 m_handler = handler;
            }

            @Override
            public void onChange(boolean selfChange) {
            super.onChange(bSelfChange);
            Uri uriSMSURI = Uri.parse("content://sms");

            Cursor cur = this.getContentResolver().query(uriSMSURI, null, null,
                 null, null);
            cur.moveToNext();

            String protocol = cur.getString(cur.getColumnIndex("protocol"));

            if(protocol == null) {
         //the message is sent out just now     
            }               
            else {
                 //the message is received just now   
            }
      }
  }

}
Aexyn
  • 1,204
  • 2
  • 13
  • 30
ρяσѕρєя K
  • 130,641
  • 51
  • 193
  • 212
  • Would this trigger if a SMS was removed as well? – tidbeck Mar 13 '12 at 10:39
  • @tidbeck :no,not trigger when SMS was removed from ContentProvider – ρяσѕρєя K Mar 13 '12 at 14:58
  • 2
    Inside SMSObserver.class there is is `Cursor cur = this.getContentResolver().....`. To what related `getContentResolver()` ? Because eclipse show this one as error. – Jviaches Mar 13 '12 at 18:01
  • @Jviaches: please see my updated edit.i have implement full code in a service. – ρяσѕρєя K Mar 13 '12 at 18:18
  • While this is working perfectly, may I ask if the user sends a multi-part message, will it be counted as 1 or is there any way to check this scenario? – midhunhk Feb 21 '14 at 04:45
  • @ρяσѕρєяK can u tell me i dont need to use service i just want when user come inside my app i will show simply count of sent messages to the user ? how will i do ? – Erum Feb 11 '15 at 06:24
  • @ρяσѕρєяK How do you position the cursor on the last sent/reveived message? I see `cur.moveToNext()`, but can it be just any message? – 18446744073709551615 Mar 02 '15 at 12:27
  • @18446744073709551615, `getContentResolver().query` returns a cursor that points to the last entry in the URI – midhunhk Jul 28 '15 at 11:54
  • @midhunhk yeah, it is just on some phones that you need to specify the default order explicitly and null does not work. – 18446744073709551615 Jul 28 '15 at 12:46
  • @18446744073709551615, ok. I am not aware of that. Can yopu give some examples of such devices? – midhunhk Jul 28 '15 at 17:23
  • 1
    midhunhk IIRC something from LG. I cannot be more specific now, months have passed since then. But I could find the lines of code like: `cur = context.getContentResolver().query(uri, cursorProjection, null, null, CallLog.Calls.DEFAULT_SORT_ORDER);` I remember that one `DEFAULT_SORT_ORDER` has fixed a bug, and was copied to other `query()` calls just in case. – 18446744073709551615 Jul 29 '15 at 10:55
  • @ρяσѕρєяK Thanks for help. But in my case, protocol is never `null` (it is "0" in either cases). Is there any preference for using `Telephony.Sms.PROTOCOL` over using `Telephony.Sms.TYPE` and checking if it is `MESSAGE_TYPE_INBOX` or not? – AliLotfi Oct 20 '15 at 12:55
  • 3
    On Android API 16 I've tested this piece of code, and the observer is not notified of a change on content://sms, then the code is not called at all. I checked the logcat console, and it write that the content://sms and content://sms/queued are really updated when I send a SMS.. any idea ? – Alex Aug 02 '16 at 16:51
  • 1
    what is SmsContent? shouldn't it be SMSObserver (the class defined right after) instead? – Yoav Feuerstein Jun 19 '18 at 13:36
7

use the following method to send sms as well as check whether the sms get delivered or not.

send.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                String phoneNo = "Phone number to sent";
                String message = "Your message";
                if (phoneNo.length() > 0 && message.length() > 0) {
                    TelephonyManager telMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
                    int simState = telMgr.getSimState();
                    switch (simState) {
                    case TelephonyManager.SIM_STATE_ABSENT:
                        displayAlert();
                        break;
                    case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
                        // do something
                        break;
                    case TelephonyManager.SIM_STATE_PIN_REQUIRED:
                        // do something
                        break;
                    case TelephonyManager.SIM_STATE_PUK_REQUIRED:
                        // do something
                        break;
                    case TelephonyManager.SIM_STATE_READY:
                        // do something
                        sendSMS(phoneNo, message); // method to send message
                        break;
                    case TelephonyManager.SIM_STATE_UNKNOWN:
                        // do something
                        break;
                    }

                } else {
                    Toast.makeText(getBaseContext(),
                            "Please enter both phone number and message.",
                            Toast.LENGTH_SHORT).show();
                }

            }

            private void displayAlert() {
                // TODO Auto-generated method stub

                new AlertDialog.Builder(YourActivity.this)
                        .setMessage("Sim card not available")
                        .setCancelable(false)
                        // .setIcon(R.drawable.alert)
                        .setPositiveButton("ok",
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog,
                                            int id) {
                                        Log.d("I am inside ok", "ok");
                                        dialog.cancel();
                                    }
                                })

                        .show();

            }

        });




            private void sendSMS(String phoneNumber, String message) {
        String SENT = "SMS_SENT";
        String DELIVERED = "SMS_DELIVERED";

        PendingIntent sentPI = PendingIntent.getBroadcast(YourActivity.this, 0,
                new Intent(SENT), 0);

        PendingIntent deliveredPI = PendingIntent.getBroadcast(YourActivity.this,
                0, new Intent(DELIVERED), 0);

        // ---when the SMS has been sent---
        final String string = "deprecation";
        registerReceiver(new BroadcastReceiver() {

            @Override
            public void onReceive(Context arg0, Intent arg1) {
                switch (getResultCode()) {
                case Activity.RESULT_OK:
                    Toast.makeText(YourActivity.this, "SMS sent",
                            Toast.LENGTH_SHORT).show();
                    break;
                case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                    Toast.makeText(YourActivity.this, "Generic failure",
                            Toast.LENGTH_SHORT).show();
                    break;
                case SmsManager.RESULT_ERROR_NO_SERVICE:
                    Toast.makeText(YourActivity.this, "No service",
                            Toast.LENGTH_SHORT).show();
                    break;
                case SmsManager.RESULT_ERROR_NULL_PDU:
                    Toast.makeText(YourActivity.this, "Null PDU",
                            Toast.LENGTH_SHORT).show();
                    break;
                case SmsManager.RESULT_ERROR_RADIO_OFF:
                    Toast.makeText(getBaseContext(), "Radio off",
                            Toast.LENGTH_SHORT).show();
                    break;

                }
            }
        }, new IntentFilter(SENT));

        // ---when the SMS has been delivered---
        registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context arg0, Intent arg1) {
                switch (getResultCode()) {
                case Activity.RESULT_OK:
                    Toast.makeText(YourActivity.this, "SMS delivered",
                            Toast.LENGTH_SHORT).show();
                    break;
                case Activity.RESULT_CANCELED:
                    Toast.makeText(YourActivity.this, "SMS not delivered",
                            Toast.LENGTH_SHORT).show();
                    break;
                }
            }
        }, new IntentFilter(DELIVERED));

        SmsManager sms = SmsManager.getDefault();
        sms.sendTextMessage(phoneNumber, null, message, sentPI, deliveredPI);

    }
Manikandan
  • 2,463
  • 5
  • 51
  • 91
0

One thing that comes to mind is using the logcat log. Every time a SMS is sent/received there is a specific entry. Just hook up your phone in debug and test and you will observe the specific entry.

I should mention this method is done from your app, so you can work it into your code.

Take a pull of this. There may be other methods but that seems fairly easy and do-able.

KDEx
  • 3,425
  • 3
  • 29
  • 39