Android doze mode and foreground service - android

I read many questions here about doze mode like Android doze mode, Android N Doze mode - how to keep background download and processing?, Wakelock and doze mode and many others. But in many replies, opinions is different. I can't test it by myself (emulator does not support my processor, and my only test device is android 5.1). I would like to know the next situation. I have an activity, which controls the media player. On devices with android 6.0 and higher it wouldn't work as expected cause of doze mode. As many solutions says to prevent doze mode it should start a service in separate process in foreground and control media player from there. The question is: if i start foreground service with partial wake lock in separate process, which would do nothing except showing notification, and leave controls to media player in my activity, should it prevent the doze mode? Or maybe there any other ways except keep the screen on from window manager?

According to this SO question and answer:
In this post's comments on Sep 17 Dianne Hackborn writes:
Apps that have been running foreground services (with the associated notification) are not restricted by doze.
- Source (sec_aw)
It looks like using a foreground service prevents the app from being killed by Doze.
Please note though, that some vendors (I know of Samsung, but there are probably others) create their own RAM conservation/battery saving tools. These may exhibit patterns completely different from Doze, and there's usually a bunch of other hoops to jump through. You are not guaranteed to get the same behavior on these devices either - they may be more or less aggressive, and the more aggressive ones tend to be worse for keeping services or whatever alive.
There's also no universal way to deal with these, but someone has made an entire website dedicated to showing what vendors are problematic, as well as potential workarounds. Note that the majority of the problematic vendors only yield end-user solutions, which means you (the developer) have no way to fix it without the user doing something.
While this is unfortunate, that's pretty much what happens when companies implement their own versions of Android. Also, from my own experience (primarily as a user rather than a dev) on a Samsung phone, the settings aren't always respected and still causes annoying behavior.
Anyway, as long as Doze is present, foreground services should be fine. On other vendors, however, all bets are off and you're at the mercy of the vendor's implementation of some type of optimization system. On certain exposed operating systems (again, see the website linked earlier), you also have no choice but to ask the user to fix certain settings to keep stuff alive.

Related

Services getting killed on custom OS Devices

I'm a newbie android developer.. I have trouble keeping the background services broadcast receivers etc alive on no stock android devices.. i have tried many solutions and couldn't find one that works... Please help.
Unfortunately, many of Android devices will have issues with staying alive in the background due to aggressive battery-saving policies of their manufacturers. This leaves you with two options: either instruct your users how to "white-list" your app to not get killed because of battery consumptions.
See here: Don't kill my app.
Or, have it done automatically by special permission.
See here: Optimize for Doze and App Standby
You should know that there are some issues with the second option, as it does not solve the case with all of the manufacturers and also, your app might be banned from Play Store if you request it and unless the core function of the app is adversely affected.

Is it possible to completely disable the Doze mode and Standby mode?

I have a requirement to create an app that should run 24/7. I don't care about battery drain, becoz app will not be submitted to PlayStore and its only for the selected user.I also understand app will only last for one day, that is acceptable in my case.
The application functionality mainly dependent on network and Bluetooth functionality and the most of the code written in pre marshmallow and changing the whole implementation is not a right option for me now.
So is there any way to create the app without any restriction? Also, As observed some of the Device manufacturers put an extra layer of battery optimization to make this worse.
I tried to create a dummy foreground service with partial wakelock, but this not seems to be working. and even whitelisting the app didn't solve the issue.
There is no proper documentation from Google about what are the functionalities will be affected from doze/standby. According to Google doc the background task will not be suspended, it only deferred until the next maintenance window. If that is the case, App should be able to print all the app that is missed during doze period. But as observed app will print the log only during the maintenance window. The is will break the expected behavior.
Whitelisting is a good option but app will be still be affected by the doze mode. What is the reason to restrict the app behavior even when the user explicitly chose not to? It very frustrating when the app behaves differently in different device OS, Manufacturer etc.
Sorry for the story. I would like to understand is there any way to completely disable Doze and standby mode without changing the existing implementation? I have gone through the various document, but there is NO WAY to achieve this 100%. Please share your thoughts
I have a requirement to create an app that should run 24/7
Write a program for a desktop operating system. Or, perhaps find a mobile device that runs Linux and write a program for it. Or, create a custom version of Android that disables Doze/app standby. Or, see if there is some Android hardware that meets your requirements and does not apply Doze/app standby (e.g., devices that naturally are always plugged in, such as Android TV or a Chromebox).
So is there any way to create the app without any restriction?
No, sorry.
I would like to understand is there any way to completely disable Doze and standby mode without changing the existing implementation?
No, sorry.

When does the device go to sleep?

I saw a great speech from Commonsware's Mark about multithreading and using wakeful services yesterday at AppsWorld London. He recommends using WakefulIntentService or WakeFulBroadcastReceiver in some situations to ensure your app will be able to continue some long processing and prevent the device to go to sleep.
I have an app that does some background processing regularly when the device screen is off. I use AlarmManager to have it get the stuff done regularly.
Since I have a large user base (200.000 active users), I get to see all kind of weird cases when users send me some logfile. Among others I could see that on some devices after the alarm will be triggered, the app starts doing his job and then suddenly just doesn't do anything for many seconds, or even minutes (no entry in the logfile for a while). I assume this is because the phone goes to sleep.
What bugs me is that this happens only on some devices, for instance it would happen a lot on Samsung SGS2+, but not on SGS2, SGS3 or SGS4.
So what I'm wondering is: what is the policy to decide when to put the phone to sleep? Is it Android deciding or is it lower at the Linux level?
How much tweaking from the manufacturer is allowed? Shouldn't the sleep policy be part of the Android Compatibility definition?
Extra question: Are there some levels of being asleep, like several levels of CPU speed, or is it just boolean sleeping / not sleeping?
what is the policy to decide when to put the phone to sleep?
Generally speaking, if nothing is holding a WakeLock, the device is free to go into "opportunistic suspend" mode, where the CPU stops executing instructions.
Is it Android deciding or is it lower at the Linux level?
The Linux kernel -- via Android extensions originally, now rolled into the stock kernel -- handles opportunistic suspend. Userland apps, like SDK apps, can use WakeLock to block opportunistic suspend..
In terms of how the kernel is configured in terms of opportunistic suspend, I have no idea.
Shouldn't the sleep policy be part of the Android Compatibility definition?
Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise.
Are there some levels of being asleep, like several levels of CPU speed, or is it just boolean sleeping / not sleeping?
From the standpoint of an Android SDK app, and with respect to the CPU, right now, it is "boolean sleeping/not sleeping", as compared to Intel SpeedStep-style CPU frequency changes. Certain multi-core CPUs may turn on and off cores to save power, but this is generally independent from opportunistic suspend.

How can I find out how much battery my Android app consumes on user's devices?

I am writing an app to evaluate the feasibility of a Bluetooth P2P network on Android.
I noticed that on a Galaxy Nexus, it uses very little battery, while on a Nexus S, it drains the battery very quickly. This is directly caused by high CPU load due to Bluetooth.
Now, I would like to collect information about how much battery drain my app causes on the devices it is installed upon. Simply logging time vs. battery level is useless since I don't know when the device is in use, and even if I logged that, I would not know if the user is playing 3D games while Torrenting over WiFi or reading an eBook on a dimmed screen.
To make the problem worse, not all battery usage caused by my app is attributed to it in the battery screen - some is listed as "Bluetooth", for example (again, device-dependent).
Is there any easy, privacy-preserving way to get useful information on non-rooted devices? The devices are not under my control. I cannot simply go look in the menu, I cannot use ADB.
The Android API doesn't support this currently. The only available documentation is the one describing how to use BatteryManager's broadcasts, which only supply the overall battery level and no per-application details.
I suppose that even if there are undocumented ways to emulate what the System Settings battery manager shows, they would require rooting.
AFAIK there is no way to do this. The closest you can get to doing this is to hook up the device to a monitoring tool like little eye labs which does draw the battery consumed by your app over time on a graph. It also supports marking key events in the app's lifetime like turning on WIFI / bluetooth etc.
There is no support for doing this remotely, but you can get the data on your own test devices.
This approach is quite crude, but it may help. You can use the existing BatteryManager broadcasts to track changes to the overall battery level while your app is active.
Knowing when your app is active is a separate issue. If your app consists entirely of Activities, then you can get good results by starting to track whenever any of your Activities' onResume() methods is called, and stopping tracking in onPause(). If you can have all your Activities derive from a single base Activity class, then this is quite easy. See How to detect when an Android app goes to the background and come back to the foreground for suggestions on how to track this.
If your app is more complex, and the smart stuff happens in a longer-running component like a Service, then it's much harder.
This is crude, but at least it would help you distinguish "playing 3D games" from "using my app".

Samsung "App optimisation" feature kills background applications after 3 days

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've owned (and currently own) Samsung devices, so I know a little as to how it works from the user's point of view. The technical specifications and how it works on the inside is an entirely separate issue, and one I can't answer.
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 system though.
It ignores background-processes that may be critical to apps, and even if it is an app you actively use, like 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"
(Rough translation from Norwegian, originally taken from an S6 running Android 6)
Therefore, apps that have been manually, or automatically set (3 days of no use) may give various issues with background processes. But remember that the user can set any app to never save battery, and ignoring the automatic setting. So with this in mind, let's consider possible solutions.
There is one scenario where you do not need to worry about the app and app optimization: When app optimization is disabled entirely.
Looking aside that, there is really only two things you can do:
Ask users on Samsung to disable battery optimization for your app to prevent issues
As #MinaSamy suggested (in their now deleted answer), SyncAdapter and having a periodic synchronization. Note that I haven't tested this, so I don't know whether it works or not.
And there's also a third option, which really isn't a solution, but you can ignore it and gamble on app optimization being disabled, or just not care about it at all.
Does anyone have insight in what Samsung considers to be "used" and can I somehow trigger that?
As far as I know, unless Samsung added some safeguards against accidental opening or added some kind of minimum activity requirement, opening is enough. It appears to be a "stupid" feature, which runs on hard-coded rules rather than a dynamic system that actually detects app use and sets power saving relative to that. It's "easy to enable", but fortunately easy to disable as well.
Meaning 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.
There kinda is. There are a total of four settings, three of which are app-specific, and it is stored in a database (or some other form of data storage). These four settings can be used, although extremely shallow, to alter the behavior of the app optimization:
Always optimize
Automatic optimization
Never optimize
Disable app optimization
The first three options are on a per-app basis, which means each app can have separate settings. Disabling app optimization is exactly what you'd expect: it disables the entire feature for all apps. If it's disabled entirely, nothing is optimized.
There's also a website listing ways of bypassing optimizations on a per-brand basis. The entry for Samsung is more or less what I've said: tell the user to manually disable optimization. There are no developer solutions.
In settings>device health>battery there's an option to "put unused apps to sleep". You can turn it off, or change the amount of time it takes, which is 3 days by default.
Sounds like that's your problem.
https://forums.androidcentral.com/samsung-galaxy-s10-s10-plus/964083-whats-disabling-some-my-apps-background.html
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!".
As a workaround, i implemented the SyncAdapter mechanism, using this link as a good starting point: https://github.com/bmeike/MiniSync
It doesn't work perfectly (for testing, in my app i write a log every 1h, and after 3 days, it starts not respecting this scheduling), but at least it doesn't stop after 3 days, without the need to put the app in ignored optimization mode.
UPDATE: After the update to android PIE, scheduling stopped again after 3 days.
On another device, same app with android Oreo, scheduling is working (even if not completely respected).
On Samsung phones, the culprit is this Sleep setting:
You have got to take your users to this system settings screen and ask them to turn the feature off.
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.

Categories

Resources