Listen outgoing SMS or sent box in Android

Solution 1:

Basically, you have to register a content observer... something like this:

ContentResolver contentResolver = context.getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms/out"),true, yourObserver);

yourObserver is an object (new YourObserver(new Handler())) that could look like this:

class YourObserver extends ContentObserver {

    public YourObserver(Handler handler) {
        super(handler);
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        // save the message to the SD card here
    }
}

So, how exactly do you get the content of the SMS? You must use a Cursor:

// save the message to the SD card here
Uri uriSMSURI = Uri.parse("content://sms/out");
Cursor cur = this.getContentResolver().query(uriSMSURI, null, null, null, null);
 // this will make it point to the first record, which is the last SMS sent
cur.moveToNext();
String content = cur.getString(cur.getColumnIndex("body"));
// use cur.getColumnNames() to get a list of all available columns...
// each field that compounds a SMS is represented by a column (phone number, status, etc.)
// then just save all data you want to the SDcard :)

Solution 2:

This one is my approach for solving this

  1. Create a service that called from other activity
  2. Create a content observer inside it

     @Override
     public int onStartCommand(Intent intent, int flag, int startId) {
     MyObserver myObserver = new MyObserver(new Handler());
     ContentResolver contentResolver = this.getApplicationContext().getContentResolver();
     contentResolver.registerContentObserver(Uri.parse("content://sms/sent"), true, myObserver);
     return START_STICKY;
     }
    
  3. Create the observer class

    class MyObserver extends ContentObserver {
    
    public MyObserver(Handler handler) {
        super(handler);
    }
    
    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        Uri uriSMSURI = Uri.parse("content://sms/sent");
        Cursor cur = getContentResolver().query(uriSMSURI, null, null, null, null);
        cur.moveToNext();
        String content = cur.getString(cur.getColumnIndex("body"));
        String smsNumber = cur.getString(cur.getColumnIndex("address"));
        if (smsNumber == null || smsNumber.length() <= 0) {
            smsNumber = "Unknown";
        }
        cur.close();
    
        if(smsChecker( "OutgoingSMS to " + smsNumber + ": " + content)) {
            //save data into database/sd card here
        }
    }
    }
    
  4. I added a method smsChecker() to check if the new message is just same as the last message

    public boolean smsChecker(String sms) {
    boolean flagSMS = true;
    
    if (sms.equals(lastSMS)) {
        flagSMS = false;
    }
    else {
        lastSMS = sms;
    }
    //if flagSMS = true, those 2 messages are different
    return flagSMS;
    }
    

if i am not mistaken, we use "content://sms/sent" if we ONLY want to check all sent messages, "content://sms/out" if we ONLY want to check all messages inside outbox, and "content://sms" if we want to check ALL messages.