I'm working on an Android app to be used in an experiment we are running in our lab. The application monitors the users movement using the accelerometers, performs calculations on this data at a regular interval, and writes the results to a file.
I'm currently having a very difficult time trying to find a way to run this process for the 15-20 minutes our trials require without it being killed. Despite declaring applications persistent, trying various service approaches (startForeground(), START_STICKY, ..), etc... I cannot seem to keep the Android OS from deciding to pause or kill my service/process.
I've done some research and the only advice I can find is how to set up your processes to gracefully recover from being killed, however I cannot afford to have gaps in my data and therefore need this process to run continuously.
Could someone point me in the right direction?
From documentation I get the impression that if you want to have a service that will only be killed in extremely low memory situations you need to:
startForeground() (you have done that)
START_STICKY (you tried that too) or START_REDELIVER_INTENT (restarts service if it is killed, but that leaves gaps in your data)
run all its processing in a separate thread
use Context.startService() to start service
The only sure way is to have it as a system daemon.
The best solution I could come up with for my problem is increasing the screen sleep delay on the device to 30 minutes and pray no buttons were pressed during our trials.
Related
I have an app which is heavily based on C++ (NDK), with it comes a lot of state which is non trivial to be put in a bundle or use some other method to persist it. The app allows users to modify photos etc, so the size of file in memory can get pretty big which can make the saving operation run a little longer (3-4 secs) than what Android would allow.
Previously, I had found that starting a foreground service in onPause allowed us to keep the process alive just long enough for us to carry our work. And even though Android-12's foreground service restrictions do allow foreground services to be run during the onPause transition, but I've discovered that this isn't true for all OEMs (specifically Samsung devices have lots of ForegroundServiceStartNotAllowedException).
So my question is, is there a way I can keep process alive just a little longer for the saving operation to finish?
I've tried my luck with WorkManager when I read the setExpedited allowed the job to be run immediately (and on older devices this would just start a foreground service, so this seemed very similar to my previous approach but with added benefit of supporting newer devices). But I discovered that this isn't fast enough to escape the slaughter brought down on Android's UI thread.
PS: If it is relevant, all the saving is a simple disk I/O operation not a network one.
Search engines and Android developer website didn't help and I guess you can help with my problem.
I want to make an app for personal use, which is supposed to run all the time on my old tablet (powered all the time). The app will have several features requiring user interaction but independent of those, it should run a background job to check something continuously (real time!) for instance sound detection. It should also always try to connect another device on the network.
That means that job needs to run almost eternally without being killed. Some comments I have found suggested AlarmManager or BroadcastReceiver. But those are triggered by very defined triggers (either time or broadcast). I don't want that, because it should perform its task continuously all the time. This background job should also be able to communicate with the main Activity of my app to report what it is doing and allow user to interact with it (change settings of the job for instance).
Do you know any way how to accomplish this? Is IntentService correct choice for this (hoping that it won't get killed or maybe I should let the Activity to restart it?)
Thanks!
Do you know any way how to accomplish this?
Build your own custom ROM, with a modified version of Android that contains your code as a native Linux daemon.
Otherwise, what you want is technically impossible.
You can come fairly close by using a foreground Service (not an IntentService) and returning START_STICKY or START_REDELIVER_INTENT from onStartCommand(). Android may terminate your process from time to time, but it should restart your service automatically after a short while. That service can use its own background threads to do whatever it is that you are trying to do.
Ok, so I'm developing an Android App with news. When user runs App for the first time, a separate thread runs, then a infinite while( true ) loop starts, inside a loop a connector downloads text from the Internet to the notification and sends this notification, then sleeps for 8 hours. Which way is better to make it working best, a thread with way as above or alarm manager? Or, maybe there is a different and better way?
For now I've done two ways for testing, both work good, but I have no idea how to check which one is more efficient, which won't be killed by android, which eats less resources, etc.
And second question, is there any way to restore the loop when someone kill app? I was testing with Advanced Task Killer Free and an app Flashy (Flash Player Loader). I killed the Flashy, but 5 seconds later app was running again, so it propably is possible, but how?
And for those who think I'm developing annoying ad - no, App which I'm developing just reads news from the Internet.
Hope somebody helps,
Thanks in advance.
Thread vs AlarmManager
AlarmManager
As per Android doc
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.
So the advantage you get here is you can perform specific task in future even if you application is not in running state.( Here you can proudly call yourself good android citizen since you are not residing in android memory to get your task done).You just tell android I want to get this task executed at particular time,Android will automatically start your application at that particular time even If it is not running.
If you want to acheive same thing with thread then your thread should be alive till the time task does not start executing.( The disadvantage will be android will not kill the thread till the time process is alive and your tread will unnecessary eat up memory).
Hope this will clear your doubt.
In your case I would definitely use the alarm manager.
As a general rule of thumb, if your application "sleeps" and routinely checks for new content in long intervals (8 hours is a long time), you should use the alarm manager.
This way your app doesn't need to run in the background, thus battery life is conserved, and the application's functionality will not be affected by Android killing the service in cases of low memory.
Regarding your second question - if the Android system kills a service due to low memory, it will restart it as soon as possible. However if you kill the service manually then it should not be restarted, even if it is possible through some hack.
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