1

I've been studying WakefulBroadcastReceiver from this link : https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html

I have few confusions regarding this:

  1. Does this receiver ensures that you'll receive the broadcast even when the device is in sleep mode? (I think no, it just keeps the device awake after receiving the broadcast until a call to completeWakefulIntent() is made.)
  2. The documentation illustrates the use of intent service within the receiver and after the completion of work, a call to completeWakefulIntent is made.

CODE :

import android.app.IntentService;
import android.content.Intent;
import android.os.SystemClock;
import android.util.Log;

public class SimpleWakefulService extends IntentService {
    public SimpleWakefulService() {
        super("SimpleWakefulService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        // At this point SimpleWakefulReceiver is still holding a wake lock
        // for us.  We can do whatever we need to here and then tell it that
        // it can release the wakelock.  This sample just does some slow work,
        // but more complicated implementations could take their own wake
        // lock here before releasing the receiver's.
        //
        // Note that when using this approach you should be aware that if your
        // service gets killed and restarted while in the middle of such work
        // (so the Intent gets re-delivered to perform the work again), it will
        // at that point no longer be holding a wake lock since we are depending
        // on SimpleWakefulReceiver to that for us.  If this is a concern, you can
        // acquire a separate wake lock here.
        for (int i=0; i<5; i++) {
            Log.i("SimpleWakefulReceiver", "Running service " + (i+1)
                    + "/5 @ " + SystemClock.elapsedRealtime());
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
            }
        }
        Log.i("SimpleWakefulReceiver", "Completed service @ " + SystemClock.elapsedRealtime());
        SimpleWakefulReceiver.completeWakefulIntent(intent);
    }
}

Now, as the docs say that this receiver holds a wake lock, I highly doubt that it's a good practice to start something like an intent service from the receiver. This would prevent the receiver from releasing the wake lock and drain a lot of battery as services are generally used for long operations.

Even as the code snippet above highlights, there's a delay of 25 seconds before releasing the lock. Is this the right way to use this receiver or should it be used only for short operations? Any help is appreciated.

gaurav jain
  • 3,119
  • 3
  • 31
  • 48
  • I am not a Perfect one to say its a good or bad practice, but it works perfect – Syed Nazar Muhammad Sep 07 '15 at 11:25
  • 1
    basically there is no references to the reciver itself ... it just start to hold the lock for the intent ... and **static** method release the lock ... – Selvin Sep 07 '15 at 11:26
  • @Selvin Even if there's no reference (I mean static method as you suggested), there's still a wake lock being held, which would anyway drain battery? – gaurav jain Sep 07 '15 at 11:26
  • 1
    *Can you elaborate more, couldn't get your poin* ... what for ... the source of WakefulBroadcastReceiver is extremely simple ... *there's still a wake lock being held, which would anyway drain battery?* ... that's why there is completeWakefulIntent method – Selvin Sep 07 '15 at 11:27
  • @Selvin Indirectly my question is : Is it a practical scenario where in a long running service requires a wake lock, if it is wouldn't it drain battery? You can ignore the receiver as per this comment in code : At this point SimpleWakefulReceiver is still holding a wake lock for us. We can do whatever we need to here and then tell it that it can release the wakelock. This sample just does some slow work, but more complicated implementations could take their own wake lock here before releasing the receiver's. – gaurav jain Sep 07 '15 at 11:34
  • huh? it seems like you do not understand the basics ... BroadcastReceiver is called from system ... system holds lock while onReceive being called ... and release it right after is finished... starting service inside onReceive without holding own lock would make no sens as CPU will be "dissabled" right after onReceive finished (of course if there would be other application hold the lock it may run) ... so there is no need to use WakefulBroadcastReceiver if you are doing simple tasks like showing notification or some SharedPreferences modification ... – Selvin Sep 07 '15 at 11:39
  • @Selvin Well I guess I do, it's just a way of answering that differentiates the best answer from others (see below). Anyways, thanks for your time and effort. – gaurav jain Sep 07 '15 at 11:51

1 Answers1

10

Does this receiver ensures that you'll receive the broadcast even when the device is in sleep mode?

No.

(I think no, it just keeps the device awake after receiving the broadcast until a call to completeWakefulIntent() is made.)

Correct.

I highly doubt that it's a good practice to start something like an intent service from the receiver

Yes, it is a good practice. That's the entire point.

This would prevent the receiver from releasing the wake lock

The wake lock is held in a static data member, which is why a static method (completeWakefulWork()) is able to release it.

as services are generally used for long operations

The definition of "long" varies. I start using WakefulBroadcastReceiver (or my WakefulIntentService predecessor) for anything that is likely to exceed 10 seconds. However, an IntentService of any form is really only designed for transactional work (e.g., downloading a large file), and so it is not well-suited for cases where the service might need to run indefinitely (e.g., as long as the user wants to talk to a certain chat server).

You only use WakefulBroadcastReceiver when you want to ensure that the CPU will stay alive for the service to complete its work. Otherwise, you use the IntentService directly.

Is this the right way to use this receiver or should it be used only for short operations?

25 seconds is a perfectly reasonable time frame for using WakefulBroadcastReceiver and its associated IntentService.

but more complicated implementations could take their own wake lock here before releasing the receiver's

Sure, though it is unclear what this would gain you. A wake lock is a wake lock. A service-owned wake lock will have the exact same impact on battery as will a receiver-owned wake lock.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thanks! Clear and concise. I understand it a lot better now. – gaurav jain Sep 07 '15 at 11:52
  • Can you give some examples of when to use WakefulBroadcastReceiver ? Do alarm-manager apps use it ? – android developer Oct 26 '16 at 07:15
  • @androiddeveloper: "Can you give some examples of when to use WakefulBroadcastReceiver ?" -- any time your code is being woken up in the background, you need a `WakeLock`, unless specified otherwise, as you do not know how long you will be awake. `WakefulBroadcastReceiver` is specifically designed for use with `AlarmManager`, as `AlarmManager` guarantees to keep the device awake long enough for `onReceive()` to complete. – CommonsWare Oct 26 '16 at 11:10
  • @CommonsWare So unless the alarm clock app doesn't do a long task like loading something from the Internet, it doesn't need to use it , right? – android developer Oct 26 '16 at 13:43
  • @androiddeveloper: Since `onReceive()` of a `BroadcastReceiver` is called on the main application thread, you need to get off that thread ASAP, let you freeze your UI (if your UI happens to be in the foreground). So, if the receiver needs to do something very short (~1ms), it can do so directly in `onReceive()` and call it good. Otherwise, it should be delegating the work to a service, and that's where `WakefulBroadcastReceiver` plus an `IntentService` come into play. – CommonsWare Oct 26 '16 at 13:46
  • @CommonsWare Actually, BroadcastReceiver can run for up to about 10 seconds, by using goAsync : http://stackoverflow.com/q/22741202/878126 , https://developer.android.com/reference/android/content/BroadcastReceiver.html#goAsync() . What's the difference though between using WakefulBroadcastReceiver&IntentService , vs BroadcastReceiver&Service (with a new thread, or IntentService) that's using a wakeLock ? – android developer Oct 26 '16 at 18:08
  • @androiddeveloper: I have never trusted `goAsync()` due to limited documentation. "What's the difference..." -- programmers already debugged the `WakeLock` handling patterns in `WakefulBroadcastReceiver` (or even my older `WakefulIntentService`), versus something that you roll yourself. If you want to roll your own solution, go right ahead. – CommonsWare Oct 26 '16 at 18:11
  • @CommonsWare Ok, so it's about the same. Thank you. – android developer Oct 26 '16 at 18:40
  • Why wouldn't be "a good practice to start something like an intent service from the receiver" ? Why isn't this a good practice? I can start a new question if this is necessary. – Don Box Feb 10 '17 at 11:59
  • in the case when broadcast receiver runs in a separate process and it's sent by ActionBootCompleted, does `BroadcastReceiver` should start a `Service` if it has something longer to do or it can do the work in the `onReceive()`? Does the 10 seconds rule apply also when broadcast is sent by system? – Don Box Feb 10 '17 at 12:14
  • 1
    @DonBox: "Why isn't this a good practice?" -- since I am not the one who wrote that, I do not know why you are commenting here. That *is* a good practice, as is covered by my answer. – CommonsWare Feb 10 '17 at 13:29
  • @CommonsWare Oh thanks. I think I read your answer the wrong way. You said "Sure it is. That's the entire point.". I thought you agree with OP that it's not a good practice :) But I understand now you are actually contradicting his statement, not agreeing with it :) – Don Box Feb 10 '17 at 13:54
  • @DonBox: I edited the answer to try to be less colloquial there. I apologize for contributing to the confusion! – CommonsWare Feb 10 '17 at 13:55
  • @CommonsWare not a problem, thank you for responding! – Don Box Feb 10 '17 at 13:55