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.
Related
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);
I'm following this basic tutorial:
http://karanbalkar.com/2013/07/tutorial-41-using-alarmmanager-and-broadcastreceiver-in-android/
As you can see, it basically does the following (correct me if i'm wrong, please):
Once MainActivity is launched, sets an Alarm for a specific date and time.
As soon as this date and time is reached, it starts an intent to MyReceiver.class
First stop.: MyReceiver is extending BroadcastReceiver. Is it possible to start an Intent to a normal Activity?
BroadcastReceiver just triggers a new Intent to open a Service, which just shows a Notification.
Second stop.: Same as before: BroadcastReceiver, can only launch Intents which are Services? Or can it launch normal activities? Why do I even have to call any new intent? Why can't I just do the job in BroadcastReceiver (like downloading some content over internet)?
I'm a bit new about Services, so I'm sorry if I said something extremly weird.
Thank you so much.
Why can't I just do the job in BroadcastReceiver (like downloading
some content over internet)?
As per Android Documentation Broadcast receivers onReceive method is called on Main Thread so you can not perform downloading task in onReceive.Since it will freeze the UI and may throw exception in 3.0 and above version.
If you want to perform download,then the best bet would be to trigger IntentService inside onReceive ( IntentService by default runs on background thread.)
BroadcastReceiver is just a means to do anything you want upon receiving a broadcast.
A Service is something that won't easily be killed by the Android OS unlike an Activity. Service has no GUI though.
BroadcastReceivers can launch anything you want (Activities, Services) with an intent.
The reason you dont want to stuff in a BroadcastReceiver is because they only live so long where as a service runs until you tell it to stop.
If you are doing polling or something you really dont need a BroadcastReceiver and you can just use a service (IntentService specifically) with your alarm manager. An IntentService only runs a long as it has something to do meaning it will stop itself unlike a normal service where you have to stop it when its done.
I'm trying to update the state of a UI on receipt of a push notification. In order to do this, I need to start an AsyncTask that performs some network operations and then updates the UI based on the result.
According to the documentation for BroadcastReceiver, performing asynchronous operations within a receiver is unsafe because the process executing it may be killed as soon as onReceive() returns, assuming there are no other "application components" in that process.
Is the BroadcastReceiver running in its own process, or in the same process as the containing Activity? Since I only care about the completion of the task as long as there is a UI to update, I'm not worried about the AsyncTask dying if the activity is closed. Assuming the BroadcastReceiver is in the same process as the activity, does this make it okay/safe to launch the task I've described from within the receiver?
Edit:
To clarify, I am registering the receiver in the activity's onResume() and unregistering it onPause(), so it should only be receiving intents when the activity is already active.
Broadcast receiver is not running on it's own process, it's running on UI thread.
Your process will be killed after onReceive method returns only if there is no other activity or service in your app is running.
If your broadcast receiver is an instance of an inner class and only receive when your activity is active, then your process will not be killed after onReceive method returns.
If inside your AsyncTask, you need a context, then I think a service is better. If not, there is no problem using AsyncTask.
Before Honeycomb (API11), you had to use a service.
Since Honeycomb (API11), you can use goAsync() :
This can be called by an application in onReceive(Context, Intent) to
allow it to keep the broadcast active after returning from that
function. This does not change the expectation of being relatively
responsive to the broadcast (finishing it within 10s), but does allow
the implementation to move work related to it over to another thread
to avoid glitching the main UI thread due to disk IO.
What I would recommend doing is startActivity(intent) from the broadcast receiver. Thats all. Inside the intent I would provide the event information you speak of, you can just set a parameter in the bundle. You can then examine this inside the Activity onStart() or onCreate() whichever gets called. If the flag is there, then from the Activity kick off the AsyncTask.
No need to use a service at all, with all the binding and communication limitations from service-activity.
Remember you can also startActivityForResult() as well. I think that you don't want to do anything except pass and forward inside a broadcast receiver.
BTW, Activities don't need to have UI's. There can be faceless activities.
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.
I'm reading the documentation now, and I have 1 thing to be fixed - please, tell me, what is difference between broadcast receiver and activity (without the fact that activity can show UI)? Broadcast receiver gets announcements using intent-filter, but Activity can do it too! Please, make me clear. Thank you.
Activity is something which work on your input or require an user intruption for launching any task but with the help of broadcast reciever you can listen the system services as once a broadcast receiver is started for listening incoming calls then each time when a incoming call it will launch your method what you have written for that for more explanation check these
http://developer.android.com/reference/android/content/BroadcastReceiver.html
http://www.vogella.de/articles/AndroidServices/article.html
You basically have it. An Activity is intended to be associated with a UI. By contrast a Broadcast receiver only 'catches' intents broadcast through the app / system. However, there are also implications for how the object is loaded into the system, and how long it sticks around. From the BroadcastReciever documentation:
A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this function, the system considers the object to be finished and no longer active.
This has important repercussions to what you can do in an onReceive(Context, Intent) implementation: anything that requires asynchronous operation is not available, because you will need to return from the function to handle the asynchronous operation, but at that point the BroadcastReceiver is no longer active and thus the system is free to kill its process before the asynchronous operation completes.
Keeping these differences in mind, the system may be able to more efficiently execute pieces of your app...
Activity is only active when you open it. When it is moved to the background, it is either paused or shut down.
A listener is always active on the background. The only thing that can "activate" a listener, is the thing it is listening for. Ex.: a broadcastlistener will detect (and react) when you receive a phonecall/sms, but will ignore the fact that you set your alarm (since it only pays attention to incoming/outgoing broadcasts)
the intent filter does pretty much the same thing for both, the difference is just how it is called. With activities, it requires the user to do something; with listeners, it requires the listener to be triggered.