My Android app activity binds to a service, which connects to a BLE peripheral and receives data. It does this until the user presses a button on the activity to disconnect from the peripheral and stop the service.
Sometimes after running with the screen locked for about ~45 minutes+ the activity and service are terminated. My conclusion was that Android 8.1 was more aggressive than previous operating systems, so I changed the background service to a foreground service, and made sure that once the peripheral is connected I stop scanning.
This didn't work, and every now and then my app is killed in the background, and I don't think it is an uncaught exception. I have read the Android docs on Services and the Application Lifecycle and have added some debugging logs into lifecycle callbacks, which hasn't helped. I have observed this behaviour on Huawei Y5 and Nokia 8 running Android 8.1 - I don't remember it being an issue on an older phone which I no longer have.
I have a few questions about behaviour that aren't clearly documented that might help me figure out this issue. Thanks for your help!
1. If an activity is killed in the background and it is bound to a service, will that kill the service?
2. If a service is killed in the background, will that kill my activity
3. If there are multiple services running and one consumes too many resources, does the OS kill everything, or just the misbehaving service?
4. What sort of things makes an activity or service a target for the OS? Holding on to wakelocks permanently? BLE scanning? Receiving too many BLE packets? Uploading too much data? Any insight here about what might be happening under the hood is appreciated.
5. Does having the phone on charge prevent the OS from killing apps? I believe it occurs in my case regardless.
There are several reasons for Android to kill.your activity. Therefore it is not a good idea to setup you bluetooth in an activity. Set it up in a seperate class or in your Application class and use other ways to send data to your activity, e.g. broadcasting. That way it will keep working even if your Activity is killed or recreated.
Is your application really being killed or is it just your Activiry that is killed?
Related
I tried to find if there's a way to run foreground service (one which would hopefully never be killed) without any ui. (Ok I guess notification is necessary but other than that)
This is a very specific use-case since the device being used is a custom one (not a phone), where we need one 'server' app, and might be couple 'client' apps. Clients app will have all necessary ui, but server app should behave in a way like a web server.
I understand this is not a intention of foreground services, but it is justified in the use-case we have.
Bonus question: Is there a 'best' way to achieve an android process/service absolutely constantly running and never being killed by platform for cleaning the memory, since this service will be de facto critical part of the system. Like a phone/dial app on phones for example
Sorry, I can't write comments so I have to post an answer.
It's not exactly what you are looking for, but maybe this google codelab can help you
start with something:
https://codelabs.developers.google.com/codelabs/while-in-use-location/#0
The code in the sample project starts a foreground service whenever the app leaves foreground, allowing the service to "survive" even if the application it's destroyed. Basically the system will not stop the service because tied to his notification.
Plus the service can be stopped from the notification itself.
Maybe with a foreground service started from a device boot broadcast you can have an "always running service"
I am developing an Android Application with Android Studio in Java, that should do the following thing:
Connect with one or multiple BLE-Devices and receive GATT-notifications of those over a long period of time (4-10h) in the background.
I wrote a Service for this which sends me an android notification when a critical value is received and only hands the data to my Activity, when the app is opened.
The whole thing works fine on the LG G6 I am testing with and also on a Huawei Mate 10 Pro.
Now I wanted to try the same App on a Samsung S9 (and S8) and the result was, that the background service stopped after 2 or 3 minutes...
I've run through every energy setting of the phone, that I found and I thought it could cause this trouble, but I found nothing.
Therefore my question: What does Samsung do different from LG and Huawei? Are there any known issues? I have no idea, what may be the problem.
The problem was indeed, that I did not use a foreground service like HarmenH told in the comments. Since I use a foreground service instead of a bound service, everything works as expected on every phone.
I can't tell you why the behaviour diverged between the different phones, but since I use the correct way it does not matter anymore.
I recommend to dive into Android services overview if you are struggeling with a similar problem.
The contract of Android stipulates that it will not kill bound services, as long as the binding context is still in scope/alive.
Say you have process A, and in its application context, bind another process's (Process B) service. That service should not be killed as long as process A is still alive.
If you want to be extra sure that the binding process (Process A) will be reaped/killed by the OS before the process/service it binds (Process B) is killed, you can use BIND_ABOVE_CLIENT flag when binding the service from the client. (see https://developer.android.com/reference/android/content/Context#BIND_ABOVE_CLIENT)
I find that in reality, when killing the main process, the OS will often kill the bound process first. That is, if, while the binding process is attempting to communicate with the bound process as part of a cleanup (onDestroy) action, it may encounter a RemoteException when writing. The binding client can also receive an onServiceDisconnected callback as the binding process is disconnected.
It seems that for some manufacturers, apps that are opened by sticky services in the background are then subsequently killed quite quickly, and can result in a lot of these transient service exceptions, which can look bad in metrics/analytics.
In reality, my team has not found an instance of the binding process, which is operating nominally, to disconnect from a bound service, even on Samsungs.
I have written an VPN using android's VPNService and it works perfectly. When I run it, it creates a foreground service and sends all traffic through my VPN server. It also has an internal reconnecting mechanism to reconnects VPN server if it disconnects for any reason without stopping service itself.
I like to have this VPN service working all the time. But my problem is that this VPN service is stopped occasionally after a completely random period(sometime it takes just 10 minutes, but other times it works for 2-3 days before stopping).
Since the stopping time is completely random and I cannot find any place in code that creates this situation (I have been debugging for weeks), I thought maybe android OS itself stops my VPNService for some reason. I wonder if there is a way to detect if system has stopped my service from outside or not. Any idea?
Unfortunately, Android OS still can terminate the service in low memory and possibly other situations, even if it's a background running service !
It is not only Android, but all Mobile Operating Systems optimize RAM usage by killing background apps.
This is done so that the foreground app can be given top priority. It ensures smooth functioning of the current app and reduces load on the system.
There's are two approaches as mentioned in this post: Background Service getting killed in android
If you are implementing the service, override onStartCommand() and
return START_STICKY as the result. It will tell the system that even
if it will want to kill your service due to low memory, it should
re-create it as soon as memory will be back to normal.
If you are not sure 1st approach will work - you'll have to use
AlarmManager
http://developer.android.com/reference/android/app/AlarmManager.html
. That is a system service, which will execute actions when you'll
tell, for example periodically. That will ensure that if your service
will be terminated, or even the whole process will die(for example
with force close) - it will be 100% restarted by AlarmManager.
I had this issue previously and I've solved it by creating the service running forever even if it's killed manually or from the system it recreates itself.
Android app that I am working on reads from near by beacons(devices) using bluetooth. It works fine when the app is in the foreground (tested it for 20 minutes). However, few minutes after app goes to background it stops reading.
I notice when app goes to background, onpause() method is executed; still my app reads for few minutes and then simply stops reading anything (when I manually bring the app to foreground, oncreate method is executed and app continuous normally).
Why is my app stopped reading few minutes after it went to background. My app is an activity and not service.
should convert the activity to service or
should I create intentservice or
should I create foregroundserive
I donot understand the difference between above 3 types of services and if any of them would help me.
Though slightly older threads, I reviewed Prevent that the app get stopped or paused by the OS and How can we prevent a Service from being killed by OS? and my app killed by android system when it running in background
But I am lost. Any discussion is appreciated
EDIT
As I understand from #davidgyoung answer, I have to write a service. I assume GUI portion of my app goes into mainactivity; then how I can ensure my mainactivity/GUI is still active in memory and was not killed by Android by the time service tries to broadcast/notify GUI
/EDIT
An Activity is not designed to run for long periods in the background. The Android OS will destroy activities that are not visible as memory is needed for other functions. While a Service is the proper alternative, even a service will be destroyed under memory pressure by the OS, so you still need to restart the service if it is killed by the OS and you continue to want to do beacon scanning.
All of these issues came up when we built the Android Beacon Library, and we settled on these solutions to keep scanning going:
Use a Service to scan for beacons in the background. It does not have to be an IntentService, but that is a reasonable option.
Use an AlarmManager to restart the scanning service 5 minutes in the future in case it gets killed. (This delay allows the OS to time to recover from a temporary need for extra memory.) If the scanning service is still running, just reschedule the alarm.
Register for OS level events (boot, power connect/disconnect) to restart the scanning service at a later time if the user kills the app with the task switcher.
All of this is built for you if you decide to use the Android Beacon Library (and we welcome contributions, too!) If you want to roll your own, you may want to look at the source code to see how these things were built. Feel free to copy and modify, too. That's the beauty of open source!
Full disclosure: I am the lead developer on the Android Beacon Library open source project.
I have a service that also contains an activity the problem is sometimes it gets shut down by the operating system.
How can I prevent that from happening?
Not sure what you mean by "service that contains an activity".
The OS can and will shut down services based on demand for memory. How often this happens depends on what you have running on your device, and the amount of memory that your device has.
To try to minimize this, you can call Service.startForeground(). Please read the javadocs for the proper usage, and please look at stopForeground() as well.
Note that this is still no guarantee. You must author your app to gracefully handle when your service is destroyed. Please read up on the Service lifecycle to understand how to handle this.
Even if you could keep your service running at all times, it would be a bad idea. This is not a personal computer plugged in to AC power. A service that is perpetually running will greatly effect the battery life of the device.
It doesn't make any sense that you would have a service that contains an activity. You can have a service to which an Activity is connected, but not one that holds an Activity. Services, along with the rest of your app, can be killed off by the Android OS at any time, and will be restored when the user navigates back to them. Instead you need to design your app in such a way that it is tolerant to these lifecycle events, and doesn't need to be kept around forever.
AFAIK, a service or an activity can not be guaranteed to run all the time. You have to handled the lifecycle events of the service like shutdown and start.