Listen outgoing SMS or sent box in Android
I am developing an application which will store all the incoming and outgoing sms in a text file in SD card.
I am able to listen incoming messages using broadcast receiver.开发者_运维知识库 I am finding it very difficult to listen to outgoing SMS.
I know to some extent that a content observer on the sent box or outbox needs to be set, but I don't know how to do it.
How can this be done?
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 :)
This one is my approach for solving this
- Create a service that called from other activity
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; }
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 } } }
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.
This is my version, which has been verified in Android 6.0+
class smsObserver extends ContentObserver {
private String lastSmsId;
public smsObserver(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 id = cur.getString(cur.getColumnIndex("_id"));
if (smsChecker(id)) {
String address = cur.getString(cur.getColumnIndex("address"));
// Optional: Check for a specific sender
if (address.equals(phoneNumber)) {
String message = cur.getString(cur.getColumnIndex("body"));
// Use message content for desired functionality
}
}
}
// Prevent duplicate results without overlooking legitimate duplicates
public boolean smsChecker(String smsId) {
boolean flagSMS = true;
if (smsId.equals(lastSmsId)) {
flagSMS = false;
}
else {
lastSmsId = smsId;
}
return flagSMS;
}
}
Place this code where the observer should be enabled
ContentResolver contentResolver = getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms"), true, new smsObserver(new Handler()));
This assumes you are using an activity. Remember that you will need a Context reference to call getContentResolver()
from within a service or receiver.
I saw what goes wrong. its on the line:
contentResolver.registerContentObserver(Uri.parse("content://sms/sent"), true, _myObserver);
you must remove '/sent' and just write 'content://sms' its is already specified in the ContentObserver to look into sent sms.
精彩评论