Doubts with BroadcastReceiver - android

I have an alarm that obviously calls a receiver and in the receiver it have to do some tasks and it may take some time to be done. But i heard that the onReceive() method is killed after some seconds.
I made a debug on my code and "stopped" inside the receiver and suddenly the debug stops, it happens because the onReceive() was killed?
So, what should i do?

But i heard that the onReceive() method is killed after some seconds
Correct. onReceive() is called on the main application thread. You want to get off of that thread as soon as possible. If your UI happens to be in the foreground when the broadcast is received, your UI will be frozen. Even if your UI is not in the foreground, you cannot take very long on that thread without your work being terminated.
So, what should i do?
Delegate the work to an IntentService, where you start that service in onReceive(). If the work may take 15+ seconds, I would recommend using WakefulBroadcastReceiver, so that you can ensure the device will stay awake long enough for your work to complete. But even then, "some time to be done" should be measured in seconds, maybe minutes.

Related

using broadcast recevire with alarm manager in android

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.

Keep Service Alive which Starts from Broadcast Receiver

I have a major Issue,
I make a Broadcast receiver which apply on the Device boot up, so i need to start a new service for performing long-running operation,
So in the onReceive() method of Broadcast Receiver I make a new Intent and by this Start a new service,
Now my problem is that this Service executes only for short time, as soon as the onRecieve() method finish it process is also finished and my Service is also stops with the finishing of Receiver process.
So how I can do this, to keep alive the Process of Service which starts from the BroadcastReceiver.
Now my problem is that this Service executes only for short time, as soon as the onRecieve() method finish it process is also finished and my Service is also stops with the finishing of Receiver process.
That would only occur if you are calling stopService(), or the service is calling stopSelf(). The service has an independent lifecycle from the BroadcastReceiver. It will not even be started before onReceive() ends.
but in the Service I use the Separate Thread, but this thread is also stopped.
That will only occur if you are stopping the thread yourself. Android does not know about threads you create.
Now, eventually, your app's process will be terminated. With a running service, this could take anywhere from 30 minutes to a couple of days, depending on what else is all going on with the device, whether you are using startForeground(), etc. Once the process is terminated, everything goes away, background thread and all.

How to stop a service?

I have a service [IntentService] which runs a 'timer task' scheduled to run after every 5 minutes. I start the service when my application is installed.
Now i want to stop my service [service runs a 'timer task'], but when i use stopService() method i am unable to stop my service. I tried to put a log in the onDestroy() method of my service but stopService() does not reaches there.
Also, since stopService() returns boolean i logged its output, it is returning false.
How should i stop it??
I have a service [IntentService] which runs a 'timer task' scheduled to run after every 5 minutes.
Please do not do this. Users hate developers who do this and will force-stop your application using task killers or the Settings app. Please use AlarmManager, so you can take up less RAM and be more friendly to the user.
I start the service when my application is installed.
This is not supported. In particular, as of Android 3.1, this is impossible, even by the undocumented hack you might be using.
Now i want to stop my service [service runs a 'timer task'], but when i use stopService() method i am unable to stop my service.
Most likely, your service is already stopped. IntentService stops as soon as onHandleIntent() returns. TimerTask forks a thread to maintain its timer -- if you are creating this TimerTask in onHandleIntent(), you are leaking this thread. You have no way of ever stopping this thread. It will randomly go away once Android elects to terminate your process.
If, on the other hand, you get rid of the TimerTask and use AlarmManager, you can do your real periodic work in the IntentService's onHandleIntent() method.

Alarm manager, using wakelocks to ensure all code runs

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.

Beginner questions: Wakelocks

I am new to the notion of WakeLock and need your help.
Questions:
I assume WakeLock to be some type of lock which when held by the executing code prevents the device from sleeping. What if the device is already in sleep/standby mode, will the code execute then? Assuming that it would never acquire a WakeLock?
When a long running task(abt 7-8 sec) is done in a background thread(AsyncTask) should I be bothered about holding a WakeLock? Does AsyncTask already acquire it for me?
links to official documentations and writeup on wakelocks are appreciated.
Thanks.
1.If the phone is in full sleep mode, aside from an incoming phone call, you could use an AlarmManager intent to wake the phone up.
From the AlarmManager class documentation:
The Alarm Manager holds a CPU wake
lock as long as the alarm receiver's
onReceive() method is executing. This
guarantees that the phone will not
sleep until you have finished handling
the broadcast. Once onReceive()
returns, the Alarm Manager releases
this wake lock. This means that the
phone will in some cases sleep as soon
as your onReceive() method completes.
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.
2.If you're working with an AsyncTask, you will want to publish results on to the UI thread on onPostExecute()
From the AsyncTask documentation:
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
3.I suggest you have a read at the official documentation of Power Manager which gives a good introduction to the WakeLock concept.
Typically the only code that would run while the phone is sleeping is a BroadcastReceiver. Actually, the phone wakes up for a second, runs the BroadcastReceiver's code and sleeps again. Since you should never run long code in a BroadcastReceiver (use it to launch a Service instead), you can basically assume that your code is never run while the phone is sleeping. Of course, if you are using a BroadcastReceiver to start a Service, you should usually obtain a WakeLock.
With an AsyncTask initiated by the user, you don't really need to worry about WakeLocks. It is unlikely the phone will sleep while it is running. I'm not sure if they get a WakeLock, but putting my phone to sleep while running a standard AsyncTask doesn't seem to interrupt the it.
As SteD said, check this out: http://developer.android.com/reference/android/os/PowerManager.html
Basically the only time you need to worry about WakeLocks is when you either expect your task to be interrupted by sleeping (as is the case if you set an alarm that wakes the phone up briefly) or if you absolutley cannot have the task interrupted. Otherwise, just make sure that you gracefully handle any interruptions.

Categories

Resources