File operations in Android service - android

Android services might get killed by the operating system at any possible time. There are no guaranteed lifecycle calls like onDestroy() you can rely on. I have to implement a service doing a lot of long running tasks and a bunch of file operations in the background. So my questions are:
Is it generally a good idea to do that in any kind of service? What happens with an open file handle when the process gets killed?
Is there a preferred way to achieve this like using a foreground service?
I think I won't be the first person having this type of problem/question, but I could not find anything on Google or SO. Thanks in advance.

Android services might get killed by the operating system at any possible time.
More accurately, Android app processes might get killed by the operating system at any point.
There are no guaranteed lifecycle calls like onDestroy() you can rely on.
Correct. onDestroy() is very likely to be called, but it is not guaranteed.
I have to implement a service doing a lot of long running tasks and a bunch of file operations in the background.
Pretty much any piece of software bigger than "hello, world" fits that description.
Is it generally a good idea to do that in any kind of service?
You do not have much of an option. A service is what is helping to keep your process around when it no longer is in the foreground from a UI standpoint. If you do not use a service, your process lifetime will likely be on the order of minutes, maybe less. With a service, your process lifetime can be hours, though it depends a lot on the device (e.g., amount of system RAM) and user (e.g., how busy the user is and how many other apps want to do background work).
What happens with an open file handle when the process gets killed?
If you have tried writing stuff to the file at about the point of process termination, any bytes not yet handed over to the OS (e.g., buffered in Java) will not be in the file.
Is there a preferred way to achieve this
I have no idea what "this" is.
like using a foreground service?
There are three main patterns for using a foreground service:
Brief transactions. K9 Mail, for example, appears to use a foreground service while it is checking for new messages, but only during that short window.
User-controlled operations. This is the conventional use case for foreground services. Music players, for example, will usually implement a foreground service for the music playback.
"I am going to try to live forever" types of services. That's not especially practical, as foreground services do not live forever. Users also get irritated with foreground services where they do not understand what they are getting as trade-off for the system RAM/CPU consumption and the always-visible notification icon.
Whether any of these patterns fits your project is something you would need to determine for yourself.

Related

What are typical use cases for multithreading vs services?

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.

Android - Is using a foreground service all I can do to prevent my process from being killed?

Context / Current Approach
Hello, I'm curious about my usage of a Foreground Service. I have an app which performs voice communication and maintains a persistent connection to our backend via a websocket. It is a common use case for our users to background our app and do something else which is memory- and CPU-intensive, in particular playing mobile games.
In order to prevent our app's process from dying and severing the voice connection, we run a Foreground Service in our app's process (a local service, in some vocabularies). This Foreground Service doesn't actually do much, it displays a notification that allows the user to interact and mute/deafen/disconnect from the notification tray. All the voice logic doesn't actually live in the Service.
Our hypothesis is that by running a Foreground Service, we effectively mark our process as "foregrounded", and the OS is less likely to kill our app. This also allows the user to swipe away our app and have the process stay alive (including the voice connection). This appears to work and looks very similar to the process/service signatures of similar products (Skype, Spotify) using adb shell dumpsys activity services and the inspectors in the device's settings.
However, from time to time we still hear about users who experience our app being killed while gaming or streaming videos, even when they are on voice and the Service is running.
And Now For The Question(s)
After much research it FEELS like we are doing the right thing already. However, we'd like to make our voice stability more bulletproof if possible, and address those user complaints.
Am I doing the right thing already, or is my understanding of using a Service to "mark our app as foreground priority" flawed? (Addendum: It took me getting to the end of writing this for this question to pop up in my searches. It reads like we're on the right track already).
Is there any way I can verify that the OS is indeed killing my app process? Conventional wisdom says no. However I can imagine some solutions which abuse the STICKY flag to relaunch the Service, log to our servers that the Service was relaunched by the OS (and therefore, must have been killed by the OS), and then stops itself again. I just thought of this while writing so forgive me for not having tried it yet...
Do we have other options? The UI components of our app are not particularly heavyweight. This leads me to think that even if we were to invest in a Remote Service (running in another process), if the OS is already killing our Foreground Service, then the OS will likely also just kill that Remote Service. I don't want to use STICKY to combat that as it would be a poor user experience -- it makes sense for services passively processing data but for active voice chat, restarting "later" doesn't sound great...
Thank you very much for taking the time to read the question, I'm happy to provide any additional necessary context.

Why my app stop working?

I am developing a simple app that just play a white noise sound in background while I am doing other things.
It works very well when I switch to other apps ( like games, chrome browser, etc ) but sometimes ( for example when there are many chrome tab opened ) the white noise sound stop and I need to reload my app.
I am NOT using Services, is this the reason ?
Because your apps is getting killed by the system to give up resources for to other apps (games, chrome, etc). So you need to use a Service.
Here an excerpt from Processes and Application Life Cycle
for more details explanation:
An unusual and fundamental feature of Android is that an application
process's lifetime is not directly controlled by the application
itself. Instead, it is determined by the system through a combination
of the parts of the application that the system knows are running, how
important these things are to the user, and how much overall memory is
available in the system.
...
A cached process is one that is not currently needed, so the system is free to kill it as desired when memory is needed elsewhere. In a
normally behaving system, these are the only processes involved in
memory management: a well running system will have multiple cached
processes always available (for more efficient switching between
applications) and regularly kill the oldest ones as needed. Only in
very critical (and undesirable) situations will the system get to a
point where all cached processes are killed and it must start killing
service processes. These processes often hold one or more Activity
instances that are not currently visible to the user (the onStop()
method has been called and returned). Provided they implement their
Activity life-cycle correctly (see Activity for more details), when
the system kills such processes it will not impact the user's
experience when returning to that app: it can restore the previously
saved state when the associated activity is recreated in a new
process.
I think Services is What You are looking For.
A Service is an application component that can perform long-running
operations in the background, and it does not provide a user
interface.
For better chance of preventing OS to kill your app, you should use a
Foreground Service
following the official guide here: https://developer.android.com/guide/components/services.html#Foreground
Remember that there is no way to be certain that OS will never kill your app, because when RAM becomes really low it could kill every process indipendently from type, following his priority rules

Can I keep Android App alive in background?

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.

Service runs tasks on an interval; should it be its own process?

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.

Categories

Resources