Why is it suggested generally to pass a pending intent for an Intent Service when using alarm manager? The same thing can be done in the onreceive() function of the broadcast receiver called by the alarmmanager. What is the advantage with using a service(Intent Service)?
If everything that you need done can be completed in onReceive of a BroadcastReceiver, then you should use that, not an IntentService.
If you want to do anything after the BroadcastReceiver, then you should use the IntentService. For example, if you want your BroadcastReceiver to start a Service, and you want the service to gain a WakeLock, then you should be using an IntentService instead.
The reason is that AlarmManager only guarantees that the onReceive of a BroadcastReceiver will be run, even if you use RTC_WAKEUP. So, it is slightly possible that if you use the BroadcastReceiver/Service combination, then the CPU will fall asleep before the Service can acquire the WakeLock - this is, unless you acquire a WakeLock in the BroadcastReceiver and you acquire one in the service, perhaps via a static WakeLock. But this is... messy, I suppose.
Btw, I have never implemented an IntentService. I just use the BroadcastReceiver and Service combo and have never had a problem reported. All the information I provided are things I read from other SO posts (primarily from CommonsWare)
EDIT:
The 50ms time frame I read from something CommonsWare posted on StackOverflow, and CommonsWare seems to be a rather reliable source of knowledge for Android.
I looked it up and, The docs do say:
(there is a timeout of 10 seconds that the system allows before
considering the receiver to be blocked and a candidate to be killed).
And they also say:
If this BroadcastReceiver was launched through a tag, then the object is no
longer alive after returning from this function.
You should not do anything that takes close to 10 seconds, just to be safe.
If you do anything that has to wait for a response, the BroadcastReceiver will die because the onReceive will likely finish running before you get the response back.
Though, I suppose the reason for the 50ms time frame is so you don't risk causing an ANR or any lag. Because if you use a Service, then you can start a new Thread, and it will not block. You would not be able to start a new Thread in a BroadcastReceiver because the code after the thread would continue to run, the BroadcastReceiver would die, and then the Thread would die, too.
Related
Is it correct that there's some overlap in the responsibilities of BroadcastReceiver and IntentService? By that, I mean that it would be redundant to set up a BroadcastReceiver that triggers an IntentService that performs some task that needs to be done. Since both respond to intents it's simpler to have just the IntentService respond directly to the intent without BroadcastReceiver serving as an intermediary.
Is this interpretation correct? Is it always correct? If not, please give an example of when it's incorrect.
Thanks much!
I mean that it would be redundant to set up a BroadcastReceiver that triggers an IntentService that performs some task that needs to be done
Not only is that not necessarily redundant, it is a very common pattern.
Is this interpretation correct?
No.
please give an examples of when it's incorrect.
Either an Intent is used with sendBroadcast() or with startService(). If an Intent is used with sendBroadcast(), it is not possible for a service to respond to it directly. Similarly, if an Intent is used with startService(), it is not possible for a receiver to respond to it directly. So, in cases where somebody else wrote the code to use the Intent, you have to match up with how they used it. You cannot unilaterally "change the channel" that the Intent is used on.
Beyond that, onReceive() of a BroadcastReceiver is always called on the main application thread. You do not want to take any meaningful amount of time here, as it will freeze your UI if your UI happens to be in the foreground. And, once onReceive() returns, a manifest-registered receiver's instance is discarded, and your process may be terminated shortly thereafter. Hence, it is not safe for a BroadcastReceiver to fork its own background thread, as Android will ignore that thread and terminate your process. A common pattern for responding to system-sent broadcasts is to use a BroadcastReceiver, then have it delegate the work to an IntentService. In one fell swoop, you solve both problems:
IntentService does its heavy lifting in onHandleIntent(), called on a background thread
because it is a Service, having it running while doing that work will signal to the OS to let your process live a little while longer
Now, if you are the one creating the Intent and you are the one dispatching that Intent and you are the one consuming that Intent, and you want to have your code use startService() directly to invoke an IntentService, that is perfectly fine.
I have an IntentService which is called from elsewhere (say from component X) in my app. I want its onHandleIntent to run with a wake lock. There seem to be two ways of doing this:
Acquire and release a wake lock in onHandleIntent.
Create a new WakefulBroadcastReceiver which starts this service. In component X, call this receiver instead of the service directly.
The second option seems to be recommended. But why? Does the added indirection and boilerplate offer any advantage over the first approach?
Back in 2010, we were told that the only guarantee with AlarmManager and _WAKEUP-style alarms was that if we used a broadcast PendingIntent, then Android would keep the device awake long enough for onReceive() to complete. Any other type of PendingIntent did not have that sort of guarantee.
However, onReceive() of a BroadcastReceiver is called on the main application thread, and we cannot safely spend much time there. Ideally, it's sub-millisecond, as for all you know, your UI happens to be in the foreground right now, and you do not want this receiver to cause jank.
So, the recipe became:
Have the alarm trigger a BroadcastReceiver
Have the receiver acquire a WakeLock
Have the receiver delegate the work to a Service, typically an IntentService
Have the service release the WakeLock when the work is completed
My WakefulIntentService was the first library to offer support for this recipe. WakefulBroadcastReceiver came along later. They both accomplish the same end, just with different semantics.
Note that "why don't we just acquire a WakeLock in the service?" fails because the device might fall asleep between the end of onReceive() and the first place where the service might get a chance to acquire the WakeLock.
Now, for other situations, not involving AlarmManager, having the service manage its own WakeLock is perfectly reasonable. In fact, that's one of the reasons I went with having a special IntentService (WakefulIntentService) rather than a special BroadcastReceiver (WakefulBroadcastReceiver).
I've a BroadcastReciever on a separate class, i register that receiver on one of the activities, and this broadcast receiver trigger when there is an Internet connectivity. Inside onReceive() of the receiver, i execute a method for getting token from the server.
But when i gone through the documentation i found that; "When it runs on the main thread you should never perform long-running operations in it (there is a timeout of 10 seconds that the system allows before considering the receiver to be blocked and a candidate to be killed)."
Please help me with the correct way of doing it.
IMO , it is perfectly fine to call a WebService inside the onReceive method of a broadcast receiver. I have done it in many of my applications and till now I have never faced any problem.
Infact in majority of applications, which require frequent updates from server the BroadcastReceiver component is used as the onReceive method runs in the Worker thread/task.
To be on the safe side you can set your WebService timeout to less than 10 secs.Another implementation can be that you can create a background/worker thread, send it a token from the onReceive of your BroadcastReceiver and inside that thread you can call your WebService.
No, The Android System may be kills the your BroadcastReceiver, in case of in-sufficient memory. Because user never or not recently interact with the process of Application.
A process that is currently executing a BroadcastReceiver (that is, currently running the code in its onReceive(Context, Intent) method) is considered to be a foreground process and will be kept running by the system except under cases of extreme memory pressure.
That means A Process holds only BroadcastReceiver, then it may be considered as low priority under cases of extreme memory pressure.
This means that for longer-running operations you will often use a Service in conjunction with a BroadcastReceiver to keep the containing process active for the entire time of your operation.
Intent intent = new Intent(mContext, MyService.class)
intent.setData(Uri.parse(your_url));
mContext.startService(intent);
Well, in android, what is the difference between doing something in broadcastReceiver and calling another service in broadcastReceiver? I think they both run in background,right?
Actually, what I what to do is:
In certain time of everyday, download the user event(eg: 9:00 am eat
breakfast) from database, and set up the AlarmManager to show
notification about the event.
Now I set up a alarm manager to do the above task. And I am puzzled should I directly accomplish this in BroadcastReceiver or call service in BroadcastReceiver to accomplish this.
Thank You.
You should do as LITTLE processing in a BroadcastReceiver as possible because (quoting from the Android Blog)
When handling a broadcast, the application is given a fixed set of
time (currently 10 seconds) in which to do its work. If it doesn't
complete in that time, the application is considered to be
misbehaving, and its process immediately tossed into the background
state to be killed for memory if needed.
You definitelly should call a service from the receiver for this purpose, if your action takes some longer time (connecting to the internet can take some). Broadcast receivers are limited by maximum amount of time, they have to finish.
Process Lifecycle
A process that is currently executing a BroadcastReceiver (that is,
currently running the code in its onReceive(Context, Intent) method)
is considered to be a foreground process and will be kept running by
the system except under cases of extreme memory pressure.
Once you return from onReceive(), the BroadcastReceiver is no longer
active, and its hosting process is only as important as any other
application components that are running in it. This is especially
important because if that process was only hosting the
BroadcastReceiver (a common case for applications that the user has
never or not recently interacted with), then upon returning from
onReceive() the system will consider its process to be empty and
aggressively kill it so that resources are available for other more
important processes.
This means that for longer-running operations you will often use a
Service in conjunction with a BroadcastReceiver to keep the containing
process active for the entire time of your operation.
from: BroadcastReceiver
I'm looking at using the Alarm Manager, and read this in the developer docs, which I don't really understand.
"If your alarm receiver called Context.startService(),
it is possible that the phone will sleep before the
requested service is launched. To prevent this, your
BroadcastReceiver and Service will need to implement a
separate wake lock policy to ensure that the phone
continues running until the service becomes available."
http://developer.android.com/reference/android/app/AlarmManager.html
I am specifically asking for which situations it could possible that the phone will sleep before the service is launched (as this is the part I don't comprehend)? Is it dependent on how fast the phone can execute statements? ie. it calls startService() which opens another thread and so the original thread could complete its work before the service has been made available?
Thanks
If you're starting the service from a BroadcastReceiver, you're only guaranteed that the device will not sleep during the receiver's onReceive(). According to this question, startService() is asynchronous, which means it will not block onReceive() from finishing while the service is being started. So if you need to make sure that the service starts, you have to implement your own WakeLock.