3

Let me start by admitting that I am learning (or struggling to learn) Android, while also doing something that appears to be somewhat challenging.

While I think I have understood the basic usage of BroadcastReceivers and I can use one to receive SMS's and do some processing, I would like for this processing to happen even when device goes to sleep. Reading around, and asking a question (this one), I understand that I need to acquire a PARTIAL wake lock (to keep the CPU active, while screen+keyboard are asleep), to process the incoming SMS requests, much in the way the main Messaging application (or say Hangout or other general messaging apps) that can receive the incoming SMS and flash the notification LED and vibrate (if configured to do so).

However, what I am confused about is the following:

  • Wake lock has to be acquired when work is to be done, and released when there is no work to be done. If wake lock is acquired and never released, you drain battery much faster.
  • If the above is true, then how is a SMS reading application is expected to be immediately notified (perhaps using a BroadcastReceiver) of the incoming message, while not having to acquire the wake-lock permanently ?
  • One way that comes to my mind is, to use a Service that mostly sleeps, and only periodically wakes up, to check if there are any SMSs. However, this is contrary to the logic that the incoming SMS and it's corresponding Broadcast Intent could happen any time, clearly with ample opportunity for the application to miss the broadcast.

So, how can one develop an application that:

  • Never misses, any incoming SMS, and hopefully is notified as soon as it arrives (even when device is otherwise sleeping)
  • Consumes minimum battery, especially since the processing of the SMS Broadcast Intent is very small and simple... computationally minimal.

Edit (12-Sept-2014)

While I've accepted the answer, I wanted to add what I understood, although I am still not 100% sure that my understanding is correct.

What I understood is that, at a low level (operating system, firmware and device HW), in an Android device, when the device goes to sleep, there are multiple events that can cause it to 'wake up'. Network events, keyboard events, some (if not all) sensor events, timer events etc. will cause the device to wake up, and quickly process the event, and try it's best to go back to sleep ASAP. As I understand, the last bit is the key. This means, that events like incoming-call, incoming SMS, keypress or other causes that result in a Broadcast Intent, always lead to an Intent to be generated and delivered to all registered BroadcastReceivers. This part is ensured. However, what is not ensured is that all BroadcastReceivers would get enough time, to spend as much time as they need to process the Intent. Instead, they need to acquire a Wake lock (of the appropriate kind) and ensure that the device doesn't go back to sleep until the Wake lock is released. Now, as I realize, there are multiple ways of acquiring the Wake lock. It could be done directly in the BroadcastReceiver, but apparently not always intuitive as to what is the best and most efficient way to manage it, s.t. it is held for the least amount of time and released as soon as it is not required. For this the SDK provides the 'WakefulBroadcastReceiver' mechanism, making the task of writing software that handled BroadcastIntent simpler when holding a wake-lock is necessary. Then there is the alternative called WakefulIntentService, developed by CommonsWare (unless I am not mistaken, it is not from the SDK, but 3rd party).

I hope I am right :)

Edit (13-Sept-2014)

More information available in this SO Q&A

Community
  • 1
  • 1
bdutta74
  • 2,798
  • 3
  • 31
  • 54

1 Answers1

2

There is a Broadcast for incoming sms (quick google search gave android.provider.Telephony.SMS_RECEIVED). So you set up a receiver for this (quick google). In the receiver you start a WakefulIntentService (this manages your wakelocks). That's all.

WIS is the answer to your other question too.

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
  • Thanks Mr_and_Mrs_D. While I am aware of the broadcast intent, I wasn't sure if it is possible that certain Intents are not delivered when phone is sleeping. However, since last night, based on what I've read, while no one says so explicitly, but I believe an Intent s.a. this one, is **always** delivered, although the receiving Receiver may not get enough time to process the intent, unless they acquire a Partial wake lock. – bdutta74 Sep 10 '14 at 12:16
  • @icarus74: if the processing is to take any time you _must_ delegate to an intent service - and namely a wakeful intent service - this holds a wakelock that covers the gap between onReceive() and the start of the service processing – Mr_and_Mrs_D Sep 10 '14 at 19:52
  • @icarus74: did you use the WakefulIntentService ? – Mr_and_Mrs_D Sep 13 '14 at 00:38
  • Admittedly, not yet! I was trying to compare WakefulIntentService and WakefulBroadcastReceiver mechanisms. Since the WakefulBroadcastReceiver seems to be the officially sanctioned way, I was tilting slightly towards it. In either case however, being a newbie, the concept of an Android service is a bit advanced for me, so proceeding with caution. I will explore both for sure. – bdutta74 Sep 13 '14 at 07:09
  • If you have some words of advise against WakefulBroadcastReceiver, would like to know about it. – bdutta74 Sep 13 '14 at 07:12
  • 1
    @icarus74: I had used WIS with no problem: https://github.com/Utumno/AndroidMonitoring/tree/master/src/gr/uoa/di/monitoring/android/services - but I am woken up from the AlarmService which _does hold a Wakelock for its receiver_ - so I just needed a lock for the service - and bridge the gap from BR. Only later I had discovered WakefulBroadcastReceiver. I know that broadcast receiver's onRreceive runs on the UI thread (http://stackoverflow.com/a/20832375/281545) - so if you want to do anything that requires time you will need a service anyway. Actually comparing WIS and WBR is a good question. – Mr_and_Mrs_D Sep 13 '14 at 12:28