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.
Related
I wrote an app which monitors my signal strength via a PhoneStateListener. I want this app to start up at boot time and run forever.
The way I managed this is as follows, but I'd like to know if anyone can recommend a better way of doing this.
I have registered a BroadcastReceiver which runs upon BOOT_COMPLETED.
Within this BOOT_COMPLETED BroadcastReceiver, I start a Service.
The Service starts up my PhoneStateListener.
Within my BOOT_COMPLETED BroadcastReceiver, I also start a periodic alarm via AlarmManager.setInexactRepeating.
Whenever this alarm fires off, it checks if my Service is running. If it's not running, it restarts my Service, which in turn restarts my PhoneStateListener.
This all seems to be working for me, but I'm wondering if it's the best and most efficient way to ensure that a PhoneStateListener is running all the time (or at least most of the time).
Is there perhaps a better way to manage this?
Thanks in advance.
You can make your service a foreground service, in this case your service is really unlikely to be killed (only if the currently opened app needs more memory).
In this case your app must show an ongoing notification to the user while the service is in foreground.
To do so, you must call the startForeground() method of your service, providing a notification to it:
startForeground(ONGOING_NOTIFICATION_ID, notification);
Check for more info: http://developer.android.com/guide/components/services.html#Foreground
I am making an app that needs to execute a function each hour even the app is closed.
First of all, I thought to create a service, but during my tests, I realise that android sometimes kills my service. So I was looking for another solution and I found AlarmManager. I have implemented it and it seems to work but I have the doubt if it will happen the same the service or it will run forever? (Until reboot of the mobile...)
Another question, it is necessary to create a new thread to execute the process in alarm manager or it runs directly in other thread?
I have implemented it and it seems to work but I have the doubt if it will happen the same the service or it will run forever? (Until reboot of the mobile...)
It will run until:
the device is rebooted, as you noted, or
the user uninstalls your app, or
you cancel the events yourself, or
the user goes into Settings, finds your app in the list of installed apps, taps on that entry, and clicks the Force Stop button
It's possible that alarms will need to be scheduled again after your app is upgraded (I forget...).
it is necessary to create a new thread to execute the process in alarm manager or it runs directly in other thread??
Unless the work you are going to do will take only a couple of milliseconds, you will want a background thread for it. That leads to two possible patterns:
If you are not using a _WAKEUP-style alarm, use a getService() PendingIntent to send control to an IntentService every hour
If you are using a _WAKEUP-style alarm, you will need to use a getBroadcast() PendingIntent, and have it either invoke your subclass of my WakefulIntentService, or you will need to manage a WakeLock yourself to keep the device awake while you do your bit of work
No, Android won't kill scheduled alarms and they got executed as planned unless app is replaced or device is rebooted. Use broadcast receivers for these events to reschedule Alarms. There's no way to prevent Force Stop as it kills all of your app components and threads totally.
That depends on what Alarm Manager do. If it sends a broadcast, the receiver limit is 10 second.
If it starts an Activity, Service or Intent Service, there is no limit. For Activity and Services you must finish or stop it and for Intent Services until the process is finished. Be aware that you can't have another thread inside Intent Service and you'r limited to code inside the OnHandleIntent.
Also you must consider device state. If it's sleep and you are using Wake Up flag receivers won't need a wake lock, but others do. It won't take long for device to go back to sleep.
Don't waste system resources with a service because Alarm Manager do what you want.
I have a broadcastreceiver called by an Alarm (scheduled with AlarmManager). In this receiver I'm only querying a register from the database, and launching a notification. I readed that a wake lock is needed when a service or an activity is started from a broadcast receiver, but, do I need a wake lock if I only want to show a notificacion (in the notification panel)?
In this receiver I'm only querying a register from the database, and launching a notification.
Do not do database I/O on the main application thread.
I readed that a wake lock is needed when a service or an activity is started from a broadcast receiver, but, do I need a wake lock if I only want to show a notificacion (in the notification panel)?
In general, no, you would not need a WakeLock from a BroadcastReceiver, even one that is invoked via a _WAKEUP alarm. AlarmManager guarantees in this case that it will keep the device awake using its own WakeLock.
However, again, in this case, you really should not be doing database I/O on the main application thread, and onReceive() is called on the main application thread. The proper pattern here is that you move your "querying a register from the database, and launching a notification" to an IntentService, started by your BroadcastReceiver, so that the work is done on a background thread. This will require a WakeLock, as you are now doing work outside of onReceive(). I have a WakefulIntentService that manages the WakeLock for you, if you wish to use it.
Yes, it is necessary.
I remember that in the Kernel level, the CPU will be kept running for about 5 seconds.
So if you cannot finishing send your notification within 5 seconds, you have to grasp a wake lock. And release it after you finished your work.
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 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.