I have an application that wakes up at frequent intervals (once per minute) to do some stuff in the background. I will be using the AlarmManager to schedule the wake ups.
I am looking at two different ways of structuring a Service to do the background work:
keep the service continuously running in the foreground with setForeground(). This is attractive since the application state will remain in memory between wake-ups.
use stopSelf() to destroy the Service after it has finished running the background task. This will require persisting some non-trivial objects between each wake up.
What are the pros and cons of each approach? How costly is persistence? What is the recommended approach for storage for case 2?
I will be using the AlarmManager to schedule the wake ups.
Hopefully not if you are going with option #1. If your service will be running all of the time anyway, just use Timer.
What are the pros and cons of each approach?
setForeground() doesn't work and hasn't for quite some time. startForeground() works, but it requires an active Notification.
A one-minute polling cycle is on the cusp of when I'd consider switching to AlarmManager and an IntentService. That being said, a one-minute polling cycle is awfully frequent. I strongly encourage you to make this user-configurable, including an option for "please don't poll, I'll request updates through the UI".
This will require persisting some non-trivial objects between each wake up.
You need to be persisting those objects in both cases. For example, when the user attacks your option #1 service with a task killer, it'd be nice if you did not lose their data.
How costly is persistence?
It does not really matter, since you need to be be persisting those objects in both cases.
What is the recommended approach for storage for case 2?
That is impossible to answer in the abstract.
You definently want to go with option 2 and stop your service once it's done. If you keep it running your going to keep using system resources, namely the battery. Do what you need to do, then stop the service. Also, what kind of wake up are you doing every minute? If you are doing a full-out device wake up (RTC_WAKEUP), you're once again going to kill the devices battery.
I hope this doesn't sound snooty, but I once heard a devloper say "Don't fight android, android will win". When you keep tyring to set your service to the foreground, you're fighting against androids attempts to clean up resources that aren't in use. You should instead embrace android. Do things as asynchronously as possible. That's the android way :)
Related
I'm writing an application which needs to detect when the screen turns on or off from the background (with the precision of about 1 minute). Ideally, I'd just statically register for Intent.ACTION_SCREEN_ON and Intent.ACTION_SCREEN_OFF, but unforuntately, that's not allowed.
This leaves me with two not-so-great---actually-pretty-horrible options (unless there's something I'm unaware of, which is likely):
Run a omnipresent Service + BroadcastReceiver which registers for the ACTION_SCREEN_ON and OFF intents OR
Use the AlarmManager to schedule some code to run every minute, and check if the display is on/off with isInteractive()
#1 isn't great because it can be killed, it wastes memory, it needs to be run onboot which doesn't work when installed on the SD card, etc.. the list goes on.
#2 isn't great because it's less precise and... let's face it- polling is almost never the right answer
But worst of all, they will both have a negative impact on battery life. This is actually the most important factor IMHO.
TL;DR
Which is the lesser of the two evils with respect to battery life impact?
I'm not an android developer (but it would be fun) but when reading the AlarmManager class overview, it says that it will periodically launch an application if it is not running already. This isn't polling as the code isn't running and not affecting performance or keep the processor awake (consuming energy). I'm sure the AlarmManager class itself isn't polling either.
You might also look at suspending your applications process instead and periodically waking it up. Launching a process is typically an expensive operation. Though suspending the application doesn't consume processor resources (and so affect power consumption) it does have a memory footprint.
I would like to create an Android application with real-time monitoring functions. One monitoring function is to audit the audio flow. The other function is to interact with a peripheral sensor. These monitoring functions can be triggered by others.
Besides, in order to save power consumption, the audio function will be running in a polling mode, i.e. sleep for a certain amount of time and wake for a certain amount of time.
I am considering how to design the Android application.
Whether to design the audio function as a Service or an Activity?
The problem is if it is designed as an Activity, the audio function will be off if screen turns off after a period of time.
How to design the polling function? Use an AlarmManager or a inner-thread with Timer?
My goal is to save the power consumption as much as possible. Thanks.
I would recommend following
a) Use a Service. Activity is short lived entity (it works only while it's on the screen)
b) Make the service foreground (read this: http://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification). This will decrease the chance that system will kill your service
c) In the service, start a thread and do everything you need in the thread.
d) If you want execute periodically, just do Thread.sleep() in the thread (when Thread sleeps it doesn't consume CPU cycles).
I believe c) and d) is preferable to AlarmManager.
Here is piece from documentation (http://developer.android.com/reference/android/app/AlarmManager.html) : "Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler."
Since your application running it's better to have some permanently running thread and execute something on it. Generally speaking Handler, HandlerThread, MessageQueue are just convenience classes for more complex message handling and scheduling. It looks like your case is quite simple and usual Thread should be enough.
Concurring with Victor, you definitely want to use a Service, and pin it into memory by calling startForeground()
However I suggest you look into utilizing the built in system Handler ; place your functionality in a Runnable and call mhandler.postDelayed(myRunnable, <some point in future>) ; this will allow the android framework to make the most of power management.
That's a service.
And you may want some extra robustness: the service can be killed and NOT restarted later, even being a foreground service. That will stop your monitoring.
Start your service from the UI. If you want the service to survive device reboot, also start it from a BroadcastReceiver for android.intent.action.BOOT_COMPLETED.
Create a thread in the service as described in other answers here.
Additionally, use Alarm Manager to periodically start your service again. Multiple startService() calls are OK. If already running, the service will keep running. But if it's been forgotten by the system, say, after a series of low resource conditions, it will be restarted now.
Schedule those alarms responsibly: to be a good citizen, set the absolutely minimal frequency. After all, Android had some good reasons to kill the service.
With some services, even more steps may be needed, but in this case this approach seems to be sufficient.
I am relatively new to Android, so what I am asking may seem obvious (although I have read all the similarly titled questions, and have searched extensively). I need to monitor the accelerometer continuously for long periods. Two approaches have been suggested:
1) acquire a partial wake lock that is held the entire time the acceleromtere is being monitored; and
2) monitor the accelerometer in a foreground service.
The first approach appears to use a lot of battery life. The second approach should result in a service that is only killed rarely, but I'm not sure what "rarely" means. Which approach should be used, and are there alternatives that I should consider?
Holding a WakeLock and a foreground Service are not really related and shouldn't be compared are to which direction is best.
Android OS is built to swap out processes based on a variety of factors. This means your process might get killed at any point by Android and it provides a framework to help you, the developer, to ensure your app can save and restore its state when this happens.
A WakeLock simply prevents the CPU from sleeping which helps save battery when the phone is not in use.
Now, a combination of both would help you achieve what you want but at great user cost. I wouldn't want an app in my phone to keep the CPU constantly running or a notification icon to show up constantly in the notification bar (that's what a foreground service does).
Keep in mind, starting a service in foreground mode does not guarantee your app will not get killed. It might still happen albeit rarely.
What is it you are trying to achieve here? Why keep monitoring the devices accelerometer? Perhaps you should only monitor it only when an Activity of your app is in the foreground instead.
I had exactly the same need and problem. I believe the solution is to use both a partial wake lock and a foreground service. Android will try not to kill a background service that holds a wake lock but is free to kill it when it needs the resources and possibly restart it later. That's fine for a lot of purposes but at least in my case that is not good enough. Putting a service into the foreground state is the way to tell Android that that killing it is unacceptable. Yes, it might still happen in extreme situations but that would now be a violation of the API contract whereas with a background service Android is free to kill it. You should therefore probably code as if that that will never happen but just know that this is a possible but probably rare error.
Admittedly I am just kind of hacking here so I would like some knowledge.
I have a service I run in the background connected to another thread that counts down a timer. I was having problems with the count down dying after a while and presumed it was due to garbage collection of the service. I seem to have fixed the issue (and see no real battery use) using startForeground. Now I read about wakelocks, are there any best practices on when to use one or the other?
Thanks!
I have a service I run in the background connected to another thread that counts down a timer.
Please use AlarmManager, so your service only needs to be in memory when it is actually doing work, not just watching the clock tick. One of the biggest user complaints about Android is all these background things that developers create that clog up their phones.
I seem to have fixed the issue (and see no real battery use) using startForeground.
The point behind startForeground() is to indicate that your service is continuously delivering value to the user, such that the user will notice if the service is reclaimed due to hanging around too long or low memory conditions. Sitting and watching the clock tick is not "continuously delivering value to the user". Please use AlarmManager, and you will not need startForeground().
Now I read about wakelocks, are there any best practices on when to use one or the other?
WakeLock keeps the CPU powered on (and possibly other things, like the screen). It has little to do with startForeground(). If you use AlarmManager, depending on the work that you are doing, you may need a WakeLock to ensure the device stays awake while you do your perodic wo
I'm creating a service that runs in the background. It does the following:
Gathers the user's data (with permission)
Runs certain tasks every X minutes, and sends this data to a server every Y minutes
I'd like if other people could write their own UI, widgets and other cool stuff.
Currently, the service continues to run between task runs/network sends (without a wakelock).
The service listens for validation and runtime changes; this requires a separate process. There are ways around this but they would involve using IPC (which I don't think would cause a big performance hit).
Questions:
Should the service be allowed to die between tasks or should I let it run without a wakelock?
Is it more effective to remain alive than to open a database every minute or so?
Can people use my service if it's not in a separate process?
The question the arises, should my service be in it's own process?
No. By which I mean it should run in the same process as all your other components.
I think it'd be nice if other people could write their own UI, widgets and other cool stuff.
It doesn't have to be in a separate process for this right?
No. It will automatically be in a separate process from the code from the "other people".
Right now the service stays running between task runs/network sends (not keeping a wakelock though) as I figure it will be more effective than opening a database/doing setup every minute or so.
Your users may disagree with this plan. Everlasting services are the reason why users attack developers with task killers and force-stops from the Settings app.
Should it be allowed to die between or should I let it run without a wakelock?
I recommend that you use an IntentService (since you need the background thread anyway for the network I/O) and let the service shut down in between polls. Also, please allow the user to control the values of X and Y from your opening paragraph.
Tasks run on an interval, should my service die in between (having to reopen the DB)?
Generally, yes. Opening the database takes a very small amount of time (e.g., handful of milliseconds), unless the flash storage is busy. That is a small price to pay to avoid complaints from users about your service running all of the time.
Can people use my service if it's not in a separate process?
Yes, so long as you are exposing some API (AIDL, documented set of Intents to send as commands via startService(), etc.).
It seems to me it might be worth dedicating an app purely to the service (i.e., no other components except a 'settings' Activity) and do everything through Intents.
As long as the manifest has all possible Intents registered using <intent-filter> blocks, anyone can communicate with it (your own apps as well as any 3rd party apps).
Also, you might want to use an IntentService which will process commands as they arrive and then shut itself down when finished.
Without fully understanding your requirements, i.e., what exactly the service is processing, it's difficult to advise further.