How to receive broadcast when a user sends SMS from his Android phone? I am creating an application which is taking track of sent SMS and calls. I am done with the calls part, please help me with the SMS. Note that sms are sent by the phone not any application.
----------//solution-----------
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(VIEW_RESOURCE_ID);
SendSmsObserver smsObeserver = (new SendSmsObserver(new Handler()));
ContentResolver contentResolver = this.getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms"),true, smsObeserver);
}
public class SendSmsObserver extends ContentObserver {
public SendSmsObserver(Handler handler) {
super(handler);
}
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
// save the message to the SD card here
Log.d("sent sms", "one text send");
}
}
I found the answer
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(VIEW_RESOURCE_ID);
SendSmsObserver smsObeserver = (new SendSmsObserver(new Handler()));
ContentResolver contentResolver = this.getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms"),true, smsObeserver);
}
public class SendSmsObserver extends ContentObserver {
public SendSmsObserver(Handler handler) {
super(handler);
}
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
// save the message to the SD card here
Log.d("sent sms", "one text send");
}
}
You could build on CallLog. The CallLog provider contains information about placed and received calls.
The Following code can work
Cursor c = null; try {
c = getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, null);
if (c != null && c.moveToFirst()) {
do {
int duration = c.getInt(c.getColumnIndex(CallLog.Calls.DURATION));
// do something with duration
} while (c.moveToNext());
} } finally {
if (c != null) {
c.close();
} }
--------------------------ADDED NEW SOLUTION------------------------
Have a look at:
http://groups.google.com/group/android-developers/browse_thread/thread/9bc7d7ba0229a1d2
and :
http://code.google.com/p/android/issues/detail?id=914
Basically, you can do it by registering a content observer on the SMS
message store.Try
this:
ContentResolver contentResolver = this.getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms"),true, smsObeserver);
Related
I want to read the sent message content from the mobile messages. I am not developing an sent sms reading application, but instead I want to read the recent last sent sms content form the mobile inbuilt sms app.
I want to read the sent sms from sent items and send some notification based on the keyword in the message.
I know we have to extend ContentObserver class and use ContentResolver.
Any idea is appreciated. Thank you!
This is my Observer class SMSObserver.java,
public class SMSObserver extends ContentObserver {
private String lastSmsId;
private Context c;
private String phoneNumber;
int type;
String lastID;
public SMSObserver(Handler handler) {
super(handler);
}
#Override
public void onChange(boolean selfChange,Uri uri) {
super.onChange(selfChange);
Uri uriSMSURI = Uri.parse("content://sms/out");
Cursor cur = c.getContentResolver().query(uriSMSURI, null, null, null, "date DESC LIMIT 1");
cur.moveToNext();
//String id = cur.getString(cur.getColumnIndex("_id"));
if( (type == 2 || type == 1) && (!lastID.contentEquals(cur.getString(cur.getColumnIndex("_id")))) ) {
String protocol = cur.getString(cur.getColumnIndex("protocol"));
lastID = cur.getString(cur.getColumnIndex("_id"));
// Message sent
if (protocol == null) {
Log.i("SMSStatus", "SMS Sent");
}
// Message receive
else {
Log.i("SMSStatus", "SMS received");
}
if (smsChecker(lastID)) {
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
if(message.contains("Dinner")){
Toast.makeText(c,"Dinner offer for 2!!",Toast.LENGTH_LONG).show();
}
}
}
}
}
// Prevent duplicate results without overlooking legitimate duplicates
public boolean smsChecker(String smsId) {
boolean flagSMS = true;
if (smsId.equals(lastSmsId)) {
flagSMS = false;
}
else {
lastSmsId = smsId;
}
Log.d(lastSmsId ,"LastSmsId");
return flagSMS;
}
}
I'm registering the contentObserver in a class SentSMSTrackerService.java
public class SentSMSTrackerService extends Service {
#Override
public int onStartCommand(Intent intent, int flag, int startId) {
SMSObserver smsObserver = new SMSObserver(new Handler());
ContentResolver contentResolver = getApplicationContext().getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms/out"), true, smsObserver);
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
I'm also giving the permission in AndroidManifest.xml
But,still i am not able to read the outgoing sms.
i am using broadcast receiver to read new incoming sms. my problem is when new sms from a contact recieves, my codes can not returns the last message of my contact, it returns the message before last one.
please help me to correct my codes. i am really confused.
public static class SmsReceiver extends BroadcastReceiver {
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(SMS_RECEIVED)) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
readVerificationCodeFromInbox();
}
}
}
}
public static void readVerificationCodeFromInbox() {
long currentTime = System.currentTimeMillis();
Uri message = Uri.parse("content://sms/");
ContentResolver cr = context.getContentResolver();
Cursor c = cr.query(message, null, null, null, null);
try {
if (c.moveToFirst()) {
do {
if (c.getString(c.getColumnIndexOrThrow("address")) == null) {
c.moveToNext();
continue;
}
if (c.getString(c.getColumnIndexOrThrow("address")).equalsIgnoreCase("9101620")){
long date = c.getLong(c.getColumnIndexOrThrow("date"));
Log.d("date-->", "" + date);
String Body =c.getString(c.getColumnIndexOrThrow("body")).toString();
String numberOnly= Body.replaceAll("[^0-9]", "");
Log.d("Body-->", "" + numberOnly);
if (currentTime-date<0.25*3600*1000) {
confirm_number.setText(numberOnly);
// EnterVerificationCode(numberOnly);
}else{
Toast.makeText(context, R.string.retry_get_verificationCode_time, Toast.LENGTH_LONG).show();
dialog.dismiss();
}
break;
}
} while (c.moveToNext());
}
c.close();
context.unregisterReceiver(receiver);
} catch (Exception e) {
e.printStackTrace();
}
}
What is the priority of your receiver in AndroidManifest.xml? I faced the same issue because I chose a positive priority where my receiver had more priority than the default Android SMS receiver. So what actually happened was, I tried to read the message before the android SMS receiver and put it into the default SMS database which we are accessing over content resolver.
Try choosing priority to be a negative value and it should work.
PS: This should be a comment but could not post it as I dont have enough reputation.
I am developing an Android application which has one of it's features as to detect any messages (SMS) sent by an app to any number. For this I want to keep track of sent messages. I want to check the message as and when it is sent. I know there is a Broadcast Receiver for SMS Recieved which will automatically call the function when a message is received. Is there any method to do that for SMS Sent? I just need a technique to do that.
Create a ContentObserver
public class InboxContentObserver extends ContentObserver {
ContentResolver cr;
Context ctxt;
public InboxContentObserver(Handler handler, Context ctxt) {
super(handler);
this.cr = ctxt.getContentResolver();
this.ctxt = ctxt;
}
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Log.i(TAG, "Starting sms sync.");
new Thread(new Runnable() {
#Override
public void run() {
Cursor sms_sent_cursor = cr.query(Uri
.parse("content://sms"), null, "date > ?",
new String[]{LAST_SYNC_TIME}, "_id asc");
//....write your code here
}
}).start();
}
}
Replace LAST_SYNC_TIME with the time.
Register the ContentObserver
new InboxContentObserver(new Handler(), getApplicationContext());
getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, inboxContentObserver);
I am developing an app that notify the user when any SMS marked as read even if the app isn't running
I simply created a contentobserver and I registered it in a service
the problem is that the contentobserver runs if the new SMS inserted or deleted but when the SMS marked as read ( Update operation) it doesn't work
here is my service code
public class Smssendservice extends Service {
private static Timer timer = new Timer();
private Context ctx;
public IBinder onBind(Intent arg0)
{
return null;
}
public void onCreate()
{
super.onCreate();
ctx = this;
startService();
}
private void startService()
{
//timer.scheduleAtFixedRate(new mainTask(), 0, 5000);
Toast.makeText(getApplicationContext(), "Before Register", Toast.LENGTH_SHORT).show();
final Uri SMS_STATUS_URI = Uri.parse("content://sms");
SMSLogger sl= new SMSLogger();
SMSObserver smsSentObserver = new SMSObserver(sl, ctx);
getContentResolver().registerContentObserver(SMS_STATUS_URI, true, smsSentObserver);
Toast.makeText(getApplicationContext(), "After Register", Toast.LENGTH_SHORT).show();
}
}
I am registering my content observer in the service
here is the content observer code
public class SMSObserver extends ContentObserver
{
SMSLogger smsLogger;
Context context;
public SMSObserver(SMSLogger smsLogger, Context context) {
super(new Handler());
this.context=context;
this.smsLogger = smsLogger;
}
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
smsLogger.querySMS(context);
}
}
eventually here is the SMS logger that I show the TOAST if the SMS data changed
public class SMSLogger {
protected void querySMS(Context context) {
Uri uriSMS = Uri.parse("content://sms/");
Cursor cur = context.getContentResolver().query(uriSMS, null, null, null, null);
/* cur.moveToNext(); // this will make it point to the first record, which is the last SMS sent
String body = cur.getString(cur.getColumnIndex("body")); //content of sms
String add = cur.getString(cur.getColumnIndex("address")); //phone num
String time = cur.getString(cur.getColumnIndex("date")); //date
String protocol = cur.getString(cur.getColumnIndex("protocol")); //protocol*/
Toast.makeText(context, "Data Changed CHECK SMS" , Toast.LENGTH_SHORT).show();
/*logging action HERE...*/
}
}
it showed this message "Data Changed CHECK SMS" if new SMS inserted or SMS deleted but in case of update the toast doesnt appear. any clue ?
In your update method, check if the number of entries updated is more than 0.
If it is, do getContext().getContentResolver().notifyChange(uri, null); before you return the number of entries updated.
What I want to do is to have a Service with more than one ContentObserver registered and check which ContentObserver triggers onChange() to do specific reactions. I dont know if I just have to include a if/else inside the onchange(), or Overwrite it to each ContentObserver, in either cases I wouldnt know exactly how to do it. Thanks in advance for any help.
public class SmsObserverService extends Service {
private String BABAS = "babas";
#Override
public void onCreate() {
Handler handler = new Handler();
this.getContentResolver().registerContentObserver(Uri.parse("content://sms/"), true, new SmsObserver(handler));
//Second observer
this.getContentResolver().registerContentObserver(Uri.parse("CallLog.Calls.CONTENT_URI"), true, new SmsObserver(handler));
}
#Override
public IBinder onBind(Intent intent) {
// TODO Put your code here
return null;
}
public class SmsObserver extends ContentObserver{
public SmsObserver(Handler handler) {
super(handler);
}
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
//Where I should check somehow which ContentObserver triggers the onChange
//This code to the sms log stuff, the call log part will be included
//when I find out how to check whic observer trigerred the onChange
Uri uri = Uri.parse("content://sms/");
Cursor cursor = getApplicationContext().getContentResolver().query( uri, null, null, null, null);
cursor.moveToNext();
String body = cursor.getString(cursor.getColumnIndex("body"));
String add = cursor.getString(cursor.getColumnIndex("address"));
String time = cursor.getString(cursor.getColumnIndex("date"));
String protocol = cursor.getString(cursor.getColumnIndex("protocol"));
if(protocol == null){
Toast.makeText(getApplicationContext(), "Enviada para: " +add + ", Hora: "+time +" - "+body, Toast.LENGTH_SHORT).show();
Log.i(BABAS, "Enviada para: "+add +" " +"Time: "+time +" - "+body);
}else{
Toast.makeText(getApplicationContext(), "Recebida de: "+add + ", Hora: "+time +" - "+body, Toast.LENGTH_SHORT).show();
Log.i(BABAS, "Recebida de: "+add +" " +"Time: "+time +" - "+body);
}
}
}
}
I'd simply extend ContentObserver and add whatever I am missing there.
mObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
#Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
}
}
};
You can check uri with above method