0

Here is how I am registering a ContentObserver to listen to sent sms:

SendSmsObserver smsObeserver = (new SendSmsObserver(new Handler(), context));
ContentResolver contentResolver = context.getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms"), true, smsObeserver);

This is the SendSmsObserver class:

class SendSmsObserver extends ContentObserver {

private Context context;

SendSmsObserver(Handler handler, Context context) {
    super(handler);
    this.context = context;
}

@Override
public void onChange(boolean selfChange) {
    super.onChange(selfChange);
    queryLastSentSMS();
}

Now the question is that where should I put the top three lines of code? Currently I am writing it in the Activity's OnCreate method. But by doing this I am calling it every time the app is launched. I don't know if it is bad practice or not.

My requirement is that I should listen for sent sms outside my Activity lifecycle. This is working as expected, but should I always register it in the OnCreate method? Also I want to put the same lines in the onReceive() of a BroadcastReceiver to ensure that I am listening after rebooting the device.

UPDATE: BroadcastReceiver is somehow not registering the ContentObserver. I also tried to use getApplicationContext() as a context in BroadcastReceiver but to no avail.

Usman
  • 2,331
  • 2
  • 21
  • 29
  • On Android 7.0+, you can use `JobScheduler` to monitor for content changes, akin to a `ContentObserver`. This is very useful, as what you want is not very practical on older devices. – CommonsWare Apr 26 '17 at 11:52
  • that would be great but right now I must target old devices. – Usman Apr 26 '17 at 12:01
  • UPDATE: BroadcastReceiver is somehow not registering the ContentObserver. I also tried to use getApplicationContext() as a context in BroadcastReceiver but to no avail – Usman Apr 26 '17 at 12:02
  • Then what you want is not going to be reliable, and what you want will cause users to want to shoot you. You would have to have a service running *forever*, where that service has the `ContentObserver`. But since you cannot have a service running forever, there will be gaps in your coverage. And I am not certain if your `ContentObserver` will be notified about SMS messages delivered while the device is in Doze mode or if your app is placed in app standby mode on Android 6.0+. – CommonsWare Apr 26 '17 at 12:11
  • The app is so far recording all the sms sent events even without service. Now if I use a service, won't it make the app more reliable, since the service will get restarted automatically even if it's destroyed by android? – Usman Apr 26 '17 at 13:52
  • It will be more reliable than *not* using a service. It will not be reliable compared to using `JobScheduler` on Android 7.0. Your service will not run forever, and you do not have control over how long the periods are between when it does run and when it does not run. Also, as I noted earlier, I would expect issues with Doze mode and app standby on Android 6.0+. Android O blocks you from having services like you are proposing, unless you make it a foreground service, which further annoys users. And so on. – CommonsWare Apr 26 '17 at 13:59
  • As I am looking for sent messages, I think doze will not be a problem when the user has just sent an SMS. Can you recommend a better approach, using which I can still target older devices? I'm currently targeting kitkat 4.4.4+ – Usman Apr 26 '17 at 19:01
  • "I think doze will not be a problem when the user has just sent an SMS" -- true. My apologies, I thought you were monitoring received as well as sent SMS messages. "Can you recommend a better approach" -- better than what? I have no idea why you need real-time access to sent SMS messages while also not being the user's chosen SMS client. There's no good way to do that, only a bad way (everlasting service) prior to 7.0. – CommonsWare Apr 26 '17 at 22:59
  • I need to log the incoming/outgoing sms to determine the most contacted contacts (and other purposes). I can listen to incoming SMS by using the official documentation but there is nothing official when it comes to sent sms. Another thing which may help me would be to read the sms database when I need to show data to the user, but that will be far less reliable because some users delete their messages as soon as they send it. – Usman Apr 27 '17 at 06:53

2 Answers2

2

You could create a service that runs indefinitely in the background (Start sticky). In this service you can add your content observer (first 3 lines). This way you ensure that the service is still working after the user closes the app.

You can start this service in the OnCreate of your application class, and also in the broadcast receiver to make sure that it runs after the phone is rebooted.

bogdanN
  • 183
  • 10
  • I'll try this and let you know – Usman Apr 26 '17 at 13:47
  • This answer should work correctly, but I have resorted to a different approach for reading sent SMS; That is: by querying the sent messages (if any) with a date larger than the last recorded date. Rather than keeping the database up to date every second, I am now updating it whenever I need it. So the end result is practically the same, save that the user might have deleted the text before I have queried it. – Usman Apr 27 '17 at 09:02
0

You should put those 3 lines of code in a foreground service.

Running a service in the background and keeping it "sticky" no longer works in newer version of Android for your scenario. The system will kill your background service eventually if your main app has been destroyed. The only way that has worked for me is to run a foreground service, which means there is a permanent notification. With this method, I was able to have my contentobserver run indefinitely as long as the foreground service was running.

I am still looking for a way to run a background service forever, and just fyi the following link does not work, Android will send a couple of broadcasts to restart service but eventually it will fail due to trying to start that service too many times.

https://fabcirablog.weebly.com/blog/creating-a-never-ending-background-service-in-android

Bqin1
  • 467
  • 1
  • 9
  • 19