We are currently developing an Android app that is a fitness-tracker application. It runs constantly in the background, and it works fine on most devices, but we've been having issues with the application dying completely on some Samsung devices. After some investigation, it seems like some Samsung devices has a completely custom "App Optimisation" feature (http://forums.androidcentral.com/samsung-galaxy-s6/599408-app-optimisation-after-updating.html), which is basically a (very) primitive version of the Doze feature that exists in later versions of Android which basically just murders apps if they haven't been used for three days.
As this app is more or less only doing logging, and doesn't open the activity, it presents a big problem for us, because this feature is pre-enabled on many Samsung devices. The problem is solved by using a foreground service, but that is a sledgehammer of a solution that requires disturbing the user with a constant notification, and we really don't need the app to be in the foreground - we are fine with the normal power management of Android.
The Samsung App Optimisation feature clearly states that it will "optimise" apps if they have not been used for three days. Does anyone have insight in what Samsung considers to be "used" and can I somehow trigger that?
Side-rant: In my opinion, this is a badly implemented feature that makes development on Android more hostile. Besides our use case, it will any messenger applications break. If it were not for the fact that Facebook Messenger and Whatsapp are hard-wired to be exempt for the app, users would be going crazy because it would be breaking their experiences.
I agree with you all, the samsung app optimization is a terrible feature. Doze is much better.
Now for my answer:
I own an S6 edge, so I know a little as to how it works.
The system can detect if you open an app. Samsung uses that in their app optimization, and will save power on apps that haven't been used in over three days. It is a terrible practise though.
It ignores background-processes that may be critical to apps, and even if it is an app you actively use, e.g. a fitness tracker, it will have issues. To quote what it says inside the app optimization-list:
"To save battery power, apps that haven't been used for more than 3 days will be designated to save power. Apps designated to save power may not show notifications"(it may not be exactly correct down to every word, it is translated from my device running with norwegian as the language)
As such, apps that:
- Have been manually set to save power
- Are automatically set to save power(3 days not being used)
Will give issues with background-processes and such.
But:
The user can set any app to never save battery, even after 3 days. So with this in mind, lets consider
Solutions
There is one scenario where you do not need to worry about the app and app optimization:
When app optimization is disabled.
Looking aside that, there is really only two things you can do:
Ask users on samsung to disable battery optimization on your app to prevent issues
As @MinaSamy suggested, SyncAdapter and having a periodic syncronization. Not sure if it works, as I haven't tested it myself
and of course a third option that cannot really be looked on as a solution:
- hope app optimization is disabled or ignore the issues
Now,
Does anyone have insight in what Samsung considers to be "used" and can I somehow trigger that?
As I mentioned above, used = opened. Meaning if the app is opened, the countdown of 3 days will restart. I am not sure if samsung has considered things such as accidental opening(press icon and instantly press the home-button)
Meaning as far as I know, you cannot trigger an event that will keep it alive(unless SyncAdapter does the trick))
And to make the facts clear, from @Neil 's answer:
It does seem like the user can do this, so there must be some database or setting somewhere that controls it.
The user have full control over the feature and can do one of these four options:
- Always optimize <-- For each app
- Automatic optimization<-- For each app
- Never optimize <-- For each app
- Disable app optimization <-- Prevent anything from being optimized
Is there a reason you can't add your service to the 'don't optimise' list?
It does seem like the user can do this, so there must be some database or setting somewhere that controls it.
Alternatively, if you detect you are installing on one of the devices, open the optimise activity page, and show a message saying "Don't optimise us!".
In my opinion you should implement a 'Broadcast Receiver' that listens to a custom 'Intent' and this 'Intent' to be Broadcasted by the 'Service' from 'onDestroy()' method of the 'Service' because when the 'System' kill the 'Service' this method will be called definitely.
And when the 'Broadcast Receiver' receives the 'Intent' you should start the 'Service' again.
And to distinguish between you stopping the 'Service' or the 'System' stopping the 'Service' just use some 'booleans' stored in 'SharedPreferences' and then in the 'Broadcast Receiver' you decide whether to activate the 'Service' or not
we are fine with the normal power management of Android
Are you? From the Android docs
However, since the user is not directly aware of a background service, in that state it is considered a valid candidate to kill, and you should be prepared for this to happen. In particular, long-running services will be increasingly likely to kill and are guaranteed to be killed (and restarted if appropriate) if they remain started long enough.
Three days seems like it would fall under "long-running...guaranteed to be killed".
If the problem is not that your service is killed but that it isn't restarted, you could use the AlarmManager to regularly check the status of your service and restart, if necessary.