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.
Related
Since threads persist past the lifetime of the activity that spawn them, I can just put whatever background work I need to do on HandlerThreads for example, no need for a service. Also they will keep running when the app in in the background bypassing the new Oreo restrictions.
Am I missing something here?
Also, ever since the introduction of Doze mode and the addition of even more restrictions on background work starting Oreo, when exactly should I use a service to do background work? Apart from
scheduling tasks for future conditions, such as WIFI connection, or charging I would then use a JobScheduler. But even that can be handled through a BroadcastReceiver...
Also they will keep running when the app in in the background bypassing the new Oreo restrictions.
That isn't quite right. It's true that background threads will continue to execute for as long as your app is alive. The problem is, your app might not be alive for very long! A Service is used to indicate to the operating system, "I don't want to get torn down; I still have useful work I have to do".
From the docs:
...[A Service represents] either an application's desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use.
and
It is not a means itself to do work off of the main thread
Ultimately, when Android is deciding whether or not to keep your App around, it doesn't care about the number of threads you have running, the number of CountDownTimers that haven't finished yet, how many Runnables you have waiting in the queue, etc. It cares about whether or not you have any active application components. Is an Activity visible? Great, stick around. Is a Service started? Also great. None of the above? Maybe it's time to terminate the app.
So this also answers the question, "when exactly should I use a service to do background work?" As mentioned, a Service won't do the work for you, it'll just help you stay alive. You can try to kick off a thread in a BroadcastReceiver (note that most implicit broadcasts no longer work post-Oreo), but as soon as you return from onReceive(), your app is likely to be killed -- unless you have a Service going, too.
ADDITIONAL POST-OREO CAVEATS
Note that a Service is likely only going to help your app stay alive for "several minutes" after the app leaves the foreground (docs). The only way I am aware of to get around this is to get back into the foreground by making your Service a "foreground service."
Additionally, if you need to ensure the device remains awake until your work is completed, you'll need a component in the foreground. That is, you can still do that work in the "background" (in the sense of being "off-screen"), but you'd need a "foreground Service" (icon in the action bar). Otherwise, Doze will apply, and that tends to inhibit any WakeLocks your app is using.
I've been looking through many questions about services, but I couldn't find one that suited me.
I need a service that both starts on BOOT_COMPLETED (not bound to an Activity) and runs ALL the time (therefore I can't user AlarmReceiver). I know it might drain my battery but so far I don't care. It is just for research purposes.
I have a service that monitors sensor's data. What I managed to do so far was: either start the service as a regular Activity, but it runs only for +-20s and it is stopped (I think the SO cuts it down to release its memory); or start a service that runs in foreground. It worked to keep the process running, however the class that actually runs the service somehow was not started, besides an annoying notification which is required.
The code I refered as the one that runs the service in foreground was taken from here:
Implement startForeground method in Android
I mean, how does an app like WhatsApp run constantly? Is it running in foreground? Because looking at Settings it seems the service is very stable, and it does not show any permanent notification, since it is not possible for a foreground service run without one.
( How to startForeground() without showing notification? )
Any advice?
You can use a WakeLock. But please remember, with great power comes great responsibility (to release them again and not over-use them).
But for now, just acquire a hefty WakeLock and only release it until you are done. This should keep your device's screen and CPU awake and allow you to do whatever it is you want to do.
I currently have programmed a normal Andorid-App (no Service). It contains a timer for periodic checks. To avoid hassle with a service and communication between Service and App I ask myself whether there is a way to keep an App that is no longer in foreground alive.
Currently when I "close" the App, it is still alive until Android OS decides to kill it. Is there a way to avoid this kill - e.g. by a certain command in "onDestroy" or a certain App-flag?
My App is quite complex and I do not want to implement a Service as this -especially the communication/binding- increases the complexity. Is there an "easy way" or am I really forced to use Service+App? Maybe there is a trick to register the App for sth. special that has the side-effect that Android OS does not kill it when it is in the background.
Edit for better understanding: It is ok that the GUI can go into the background (vanish) when the user wants it, so my question is not how to let the GUI of my App permanently in the foreground. All I want is that the timer stays intact without the need for an additional Service.
Thank you all for ideas in advance!
Android is very unpredictable by the nature of the OS's killing selection and by the market fragmentation. I would not count 100% on anything being kept alive if it is crucial. However you can gamble and be pretty successful. This is what would help you:
Use very good "Best Practices" to keep your string pool and heap at a minimum as Android looks to kill memory hogs first off (and because you love what you do).
Add the persistent attribute to your application manifest tag.
To really help yourself out, run as a, or run a service because they are long running processes, are very light (if implemented well), and Android looks to kill these off lastly.
Give your service priority by running it as a foreground service.
Doing these things will increase the likely-hood that Android will not kill your application.
I don't think there is anything like that available. I suggest looking at AlarmManager for periodic tasks - this may mean you won't need to use a service.
The apps being available in the background is simply a caching measure by the android OS to avoid having to relaunch a frequenly used app from scratch. If you want to be able to count on your app running in the background, a Service is the correct solution. Its not the answer you are looking for, but I am not aware of any tricks to staying alive in the cache, and if there were any, I would not feel good about recommending them.
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
Basically, I want to find out when another app starts, so I can adjust my app in a particular way. For example, if the user starts the GMail app, my service can detect that and react.
My current idea is to check 'topActivity' for each element in getRunningTasks() from the ActivityManager class. But that sounds quite expensive, since it needs to be constantly checking in the background (and I'm quite fussy about the CPU usage of my app).
If anyone knows a better way, I'd love to hear it!
There is not way of doing that the "nice way" meaning a BroadcastListener since applaunch don't get broadcasted. The only way is to Start a service that checks the getRunningTasks()
(For not to load the CPU too much you can also check what app is to the foreground. I'll search for the code if you are interested on that technic)
Have the service checking at interval of 5-10 seconds. Also shut down the service at SCREEN_OFF and restart it at SCREEN_ON.
Sorry but there is no other way for that.