I have an active-monitoring healthcare application that needs to be synced with different BLE devices every 15min in order to collect vitals and essential data. For this, I am using a ForegroundService with a Notification, Additionally, I have taken the wake-locks, and unrestricted power plan for the app as well with 15 min Periodic WorkManager Job as a safety check which basically triggers the same ForegroundService if somehow service is killed while device goes to idle or doze mode.
Problem
Most devices seem to be working fine, However, most Samsung, Huawei, and Xiaomi devices fail in doze mode. the sync window is increased by 30-120min.
Requirement
I want devices to sync reliably even in doze mode. I want to know possible solutions which may achieve this goal. Since data is important for real-time monitoring and triage a Battery-Tradeoff is acceptable as opposed by DOZE mode. Is there any special permission or mechanism I can use to achieve this?
Related
I have an app that uses both periodic and onetime workers to perform various tasks, some of which require a network connection. My client reported to me that a certain required daily task was not performed on a day he did not use the app at all. Despite the app's not having been run on a given day, the workers still need to run in order to report various statistics to the backend server. I assume this is due to the fact that the app was in App Standby Mode for the entire day, as well as the device's being in Doze Mode for at least part of the day. So my question is, is it possible to make a periodic or onetime worker run while the app is in App Standby or Doze Mode, or will it always be delayed until the device and/or app wakes up?
Alternatively, would I be better off using alarms instead of workers? I see that it is possible to set an alarm using setExactAndAllowWhileIdle() that "will be allowed to execute even when the system is in low-power idle modes." Does "idle mode" imply Doze and/or App standby mode?
I have been grappling with this for a while now, so any help and/or guidance is greatly appreciated.
Work Manager is Deferrable background work when the
work’s constraints are satisfied. if all the constraints set on a WorkRequest are
satisfied, Work can still be run with some additional delay. It's because WorkManager respecting Android battery optimization strategies. Also, you can read more about WorkManager constraint to understanding the work's constraint here:
https://developer.android.com/reference/androidx/work/Constraints.Builder.html
I have been following https://developer.android.com/guide/topics/connectivity/wifi-scan guide in order to create a Wi-Fi scanner. I am using a foreground service with a handler to call wifiMananger.startScan(); every 30 seconds (I tried with 15 minutes).
Everything works great for about 2 hours then suddenly WifiManager.EXTRA_RESULTS_UPDATED boolean returns false and the wifiManager.getScanResults() are not getting updated. Then as soon as the phone is plugged in it starts sending results again. (No, it is not low on battery)
I have battery optimization turned off. I have all of the required permissions allowed. Locations is turned on with Wi-Fi scanning enabled. The device I'm testing on is a Samsung S7 Edge running Android 8. So I know it's not the new OS. (I also tested with a Nokia 5.1 running Android 10 with pretty much the same results).
Does anyone know why this is happening or has anyone encountered this issue before?
Thanks in advance.
Updated: In case of your problem, since you are using exactly 30 seconds due to some problem there might be more than 4 time in a 2 minutes period, make it like 35 seconds and test the result.
Original Answer: From this WifiManager startScan throttled in P Beta (Developer Preview 2) :
"Call Limitations - Throttling
We are further limiting the number of scans apps can request to improve network performance and improve battery life.
The WifiManager.startScan() usage is limited to:
Each foreground app is restricted to 4 scans every 2 minutes.
All background apps combined are restricted to one scan every 30 minutes."
It is said that this restriction is due to the battery drain, so it is normal to remove the restriction while charging.
Read more about throttling in official documentation.
This is because Android OS enters the infamous "Doze mode". I recommend you to look through the official documentation/explanation.
Unfortunately, there is no way around this. It will also affect any kind of a foreground service and pause it for longer periods. Doze mode will only trigger if the screen is locked and the device is not plugged in.
I encountered the same issue on my project and we implemented a periodic check. If the screen is locked and device not plugged in for a longer period of time, we show a notification asking the user to either plug the device in or open the app so the service could keep working. The implementation is a bit lengthy, but if it is what you decide to go with, I can update the answer with some of the code (using the AlarmManager within a BroadcastReceiver to achieve this).
In my app, I make an internet connection every 10 minutes via the AlarmManager APIs to download data.
I would like the app to make at least 6 attempts to connect, one every 30 seconds if there a problem with the network connectivity.
Is it possible?
It isn't possible to do that on a modern Android device where by modern I mean Android 6 or greater.
6: Doze [Doze that comes on roughly an hour after the screen is turned OFF]
7: Doze++ [Doze that comes on shortly after the screen is turned OFF]
8: Background restrictions [Inability to run services that are not in the foreground]
Google's recommended way of doing syncing like this is to use a JobScheduler or Firebase Cloud Messaging if you have luxury of doing a server implementation.
With out knowing all the requirements, it sounds like the app may need to use the AlarmManager if you're determined to sync more frequently than the JobScheduler allows.
There is only 1 API in the AlarmManager that is guaranteed to be called reliably once every 30 seconds and that is setAlarmClock. However, it cannot be used to start a service. It can only send a user-facing alarm and a PendingIntent that will be executed when the user clicks on the alarm.
The two APis most likely to be useful to you are setAndAllowWhileIdle and setExactAndAllowWhileIdle. Both these APIs can be used to start a service. The alarms will execute frequently when the screen is ON or the device is charging. However, when the device is in the power saving mode called Doze they can only execute during Doze maintenance windows. This means they can still run at least once every 9 minutes during most normal doze windows.
Now apps targeting Android 8 must address another new restriction, they have to call startServiceInForeground. A foreground service sets an on going notification like your media player for example. So it makes the user more aware that the service is running and usually gives them an option to stop it.
Now foreground services are 'exempt' from doze, a few things to be aware of:
When a foreground service is active it prevents the entire device from dozing which greatly increases the battery usage
In Android 6 foreground services will be dozed anyway unless they are in a separate process due to a framework defect
I've heard that some devices will eventually kill a foreground service if you leave it running for an extraordinary amount of time
But the real answer to your question is: "Don't do it". Does the app really need to use that much battery and data? Running every 30 seconds is extraordinary and even if was possible it would make the app a "bad citizen" on the phone...
Our company is developing an android application that uses network communication to send GPS signals from devices. The devices are the same and they are all work tools, so we do not have to worry about battery draining, or etc. Currently the activity has a thread, which communicates with the server. The problem is that when the device is locked and it goes to sleep, the network communication breaks.
I've tried to put a partial wake lock to the onPause method to keep the CPU on, and release the wakelock in the onResume method, but it seems not to work. Any idea how to prevent the sleep, or keep flowless communication between the client and the server?
Unfortunately, it is the new behavior, You can read here:
https://developer.android.com/about/versions/nougat/android-7.0-changes.html
See the Doze section.
When a device is on battery power, and the screen has been off for a certain time, the device enters Doze and applies the first subset of restrictions: It shuts off app network access, and defers jobs and syncs. If the device is stationary for a certain time after entering Doze, the system applies the rest of the Doze restrictions to PowerManager.WakeLock, AlarmManager alarms, GPS, and Wi-Fi scans.
It can be solved by using Foreground Service like mentioned above in comments by #egoldx.
It is surely a bad practice to try holding a wakelock, even partial, all the time.
Currently i reading in official google doc news about Android 7.0
I can not understand a few things.
They wrote Doze improve battery life by turn off network and CPU when user block the screen.
But how this works ?
1.I have Marshmallow in my device, and when my phone is blocked, i still get notifications from app with network (e.g. Messenger).
2.Second thing they wrote Nougat have improved this more by again CPU and network. So what is exacly differet ?
I have Marshmallow in my device, and when my phone is blocked, i still get notifications from app with network (e.g. Messenger).
SMS does not usually go over the Internet, assuming that is what you mean by "Messenger" (many apps use that name). Plus, high-priority FCM push messages work despite Doze mode.
Second thing they wrote Nougat have improved this more by again CPU and network. So what is exacly differet ?
There is a "Doze on the go mode" that kicks in even if the device is moving. This is covered in the documentation and in the documentation.
Push Notifications will still get through, but most services will stop running after a while if you leave your phone sitting on a table with the screen off.
For example Spotify still keeps running smoothly because it has a foreground notification. The battery savings come from when the OS can shut down most systems such as internet and geolocation as well as avoiding running other services for increasingly longer periods of time,for example reaching stretches of hours by the end of a typical user's sleep at night.
Now they're mainly doing what they were saying for a long time: background services have no guarantees of how long they will run. The biggest unintended consequence is that sometimes when they wake up there's no internet or geolocation is not available. And the time they run is less predictable.
There's still ways to wake up and perform tasks with perfect predictability using exact alarms or push notifications, depending on where the event is generated. But for most cases the recommended solution is using job schedulers.