I have read many posts state that doze mode killed a running service at a particular moment e.x link or that they want to execute a long running thread.
I can't understand why you should use a service to do a background job that you know that in some point it will stop eventually.
For instance:
You could use a simple Thread:
new Thread(new Runnable).start()
and do some work in it. Using this:
In combination with a wake lock, device wont sleep and thread will keep running.
No doze mode restriction (except network but lets say we do local stuff)
So you can do background work with no restriction whatsoever. Although you should use services for these reasons link.
Is this another way (not better of course but a way nonetheless) of doing a background work? Am I wrong?
There are a lot of ways to do a background job aside of services check this link it may help you pick the best option for your work :
Job Scheduler vs Background Service
And services as #TheWanderer said will continue to work event after the app is closed for a period of time unlike a simple thread that will end immediately when the app is closed.
Read this part in the link that you linked
Services are given higher priority than other Background processes and
hence it’s less likely that Android will terminate it. Although it can
be configured to restart once there is ample resources available
again. You should go through the different processes and their
priority/important level in the documentation on processes and
threads. Assigning them the same priority as foreground activities is
definitely possible in which case it’ll need to have a visible
notification active (generally used for Services playing music).
If you are running a background thread that you start from an Activity, Android does not know that you are doing background work in the OS Process that is hosting your Activity. Android can kill the OS Process hosting your Activity at pretty much any time. If the user presses the HOME button or takes a phone call or opens a notification and goes to another application, Android can kill off the OS Process at any time. When the user returns to your application, Android will create a new OS Process and recreate all the relevant activities, but your background thread is hopelessly lost. This is the reason that Android has services.
If you start a Service to perform your background processing, the Service will also start background threads, but these are controlled. Your Service tells Android what to do if it kills the Service while it is processing an Intent. Your Service can therefore be informed and restart (or continue) the background processing as necessary. You can also run the Service in a different OS Process from the OS Process running your activities. This will prevent Android from killing the Service if the user removes your app from the list of recent tasks.
With newer Android SDKs there are other mechanisms you can use, like JobScheduler.
Related
The title isn't good, so please read this description to understand what i mean.
I created a background service that i want to run for a long time, by definition services on android can run even if user switch the app or even closes it.
My question is: how does android management system knows which threads to keep and which to wipe when the app goes background and the only running thing is the service?
My service runs by default on the mainthread, so when i want to perform a long task i do:
AsyncTask.THREAD_POOL_EXECUTOR.execute(runnable);
is that right? can i use this default threadpool created by android or the service must explicitly creates the thread in order to the system knows that thread must survive even if the app goes background?
how does android management system knows which threads to keep and which to wipe when the app goes background and the only running thing is the service?
Android does not "wipe" any threads. Android terminates processes to free up system RAM, not threads.
is that right?
I would recommend using your own Executor, RxJava, or Kotlin coroutines, over using the executor in AsyncTask. That is because I expect AsyncTask to be deprecated sometime, as it is "old school".
However, beyond that, what you are doing sounds fine.
While testing the background execution limits as stated here I created a thread in my service. Something like this :
// spawn own thread
HandlerThread thread = new HandlerThread("TestServiceThread");
thread.start();
The service is started by the usual pre Oreo startService.
What I noticed while debugging in android device monitor is that the threads I create continue to live long and healthy and execute normally. Can this be a workaround to keep abusing system resources and not do things via foreground services or jobs ? or is it just a chase against the framework which will soon end ? Any comments ?
I wouldn't expect that to change. Its impossible (not just in Android, its theoretically impossible) to safely kill a thread without the thread helping out. Otherwise you could kill the thread in a condition where other threads will deadlock, have inconsistent data, or the app may just not function. That's why thread.stop() is deprecated- because there is no way to make it safe. And that's why you interrupt a thread instead, and the thread needs to monitor isInterrupted and exit cleanly.
I would be careful with this kind of approach.
Although Gabe Sechan's answer is quite valid, the danger of relying on this working is too high to pursue this. Google are clearly out to get any app that tries to do background execution and abuses the user's battery and for good reason in my opinion. Some apps just don't respect a user's battery at all.
The documentation clearly states:
An app is considered to be in the foreground if any of the following
is true:
It has a visible activity, whether the activity is started or paused.
It has a foreground service. Another foreground app is connected to
the app, either by binding to one of its services or by making use of
one of its content providers. For example, the app is in the
foreground if another app binds to its: IME Wallpaper service
Notification listener Voice or text service If none of those
conditions is true, the app is considered to be in the background.
Source:
https://developer.android.com/about/versions/oreo/background.html#services
Although it's not safe to kill a thread due to all the reasons mentioned by Gabe, Android could well kill the app off entirely (ala kill -9). I would imagine that any deadlocks would be handled by Android (not a trivial task I'm sure). Data corruption would be considered as the app's fault for not handling background execution properly.
It's a bit of a risk for Android but they've probably weighed it up and decided this is the way to go.
Also, take care of this:
Note: By default, these restrictions only apply to apps that target
Android 8.0 (API level 26) or higher. However, users can enable most
of these restrictions for any app from the Settings screen, even if
the app targets an API level lower than 26.
Source: https://developer.android.com/about/versions/oreo/background.html#overview
I have a downloader application on Android.
It shows a notification(in-progress, not dismissable) during the download
and it also catches a wakelock.
I even asks the user to disable Doze for my app.
However, battery-saving feature from various vendors seem to ignore it and kill it randomly.
Is there a way to mark my app process "busy",
so that it has a higher priority in the not-to-kill list?
Note that I'm not using a service in my app.
Regular activity spawns up a thread and download is handled from there.
Note that I'm not using a service in my app
That would be the lion's share of your problem.
Regular activity spawns up a thread and download is handled from there.
That means that Android has no idea that you are doing anything that the user would value, when you're not in the foreground. Android will happily terminate your process to free up system RAM for other processes.
Use a service, perhaps an IntentService (since it already has a background thread for you, and it automatically shuts down once your work is complete). Convert your Notification into one for startForeground() on the service.
If you are keeping a wakelock for a longish time then it is better to let the user know about it, use a foreground service as CommonsWare pointed out.
However, if your use case does not warrant any foreground behavior then I would recommend you use framework JobScheduler that plays very well with doze and app standby as well.
For earlier than API 21 you may use JobDispatcher API.
You can read the more details here.
I am working on an Android project and I need the app to work even when the device is locked.
The idea is to open the app that will start the (Intent)Service, the service processes the data all the time. The device can be locked/put away and after some time when the app is opened the service is manually stopped. The service should be running all the time in the background.
I have found information online, but I am not sure what to use and in which way..
I have found that the IntentService can be used. Also the service should run in a new thread. I need to process the data from gps all the time, should I use WakefulBroadcastReceiver?
Thank you.
IntentService is not necessarily what you want to use. It will automatically spawn a new thread just to handle an incoming Intent. Once all incoming Intents have been handled it will stop the Service. To have a long running Service, you would need to derive from Service and when it is started return START_STICKY from the onStartCommand() method, plus spawn your own thread to handle your background work.
If you need to monitor GPS, you'll have to manage that along with keeping the device awake using a WakeLock. Note that in Marshmallow, this gets more complicated because of the new Doze mode where even wakelocks are ignored.
Also, note that the way Android is architected there is still a chance that your application running the background Service may be killed. Android uses a unique process management technique based on memory pressure and user perceived priority to determine how long a process should stick around. I recommend reading up on the Service lifecycle in the documentation.
In android their is no fool proof way to ensure that your service runs forever because the LMK(low memory killer) when the system needs resources (based on a certain memory threshold) , kills the service then if it can restarts it. If you handle the restart properly the service will continue to run.
Services that are given foreground priority are significantly less likely to be killed off, so this might be your best bet. However their will be a notification of your service running the in the background on the menu bar up top. Foreground Service
I am creating an app that has a UIThread and a background thread. The background thread is basically being used as a timer - every second it sends a message to the UIThread to update the UI. When the user exits the app by hitting the backbutton, the thread continues to run. I want this to happen since the user may want to open another app while the timer continues to count down.
My question is when the user comes back to my app. I want to connect to that background thread that is running to display the current state of the app - how much time is left, etc. My question is how to hook back in to the thread that is still running in the background. I have tried using Thread and AsyncTask, but the same issue occurs.
Thanks for any help that you can provide.
Your thread is still turning by sheer chance - your application is in fact still running but it and the thread will be shut down when Android decides it needs the resources.
However what you want to do is well-provided for in Android - you need to implement a Service to have a process that runs in the background separately from your application. You can even have a Service start at boot and run whether or not your application is started.
This http://developer.android.com/reference/android/app/Service.html has most of what you need to know. To communicate between the Service and a foreground Activity you'll need to bind to a service interface, which is fortunately very easily done.
First thing that comes to mind is to change your timer thread to a Service and have apps interested in it bind to that service. Based on the Android documentation and suggested app design, you cannot depend on that thread to not be killed by the OS whenever it deems necessary.
http://developer.android.com/guide/topics/fundamentals/services.html
The android system provides a broadcast event every minute, it's call TIME_TICK.
You should:
Create a service. This is the recommended way to have a part of the app running in the background
Listen to the TIME_TICK event. This will consume less battery. (It won't wake the phone, though, so use an ALARM, too)
Add an alarm (to wake the phone if necessary)
Let the UI and the service interact. You need a callback via rpc (see the last callback example on the api page)
You should also ensure that the phone can sleep during the timeframe. You thus may want to compute the state as a delta between the starting point and now, instead of updating the state all the time.