I am looking to use the Jobscheduler api to schedule a job when there's connectivity to download a bunch of images from push messages. Since wake locks are disregarded by the os in doze mode and since an fcm message can only wake the device a maximum of 10s, the maintenance window seems like the only way for me to download the images from all the push notifications.
The images will be max 100kb each and a maximum of 50 images at a time. So basically all in all maximum 5mb data usage.
I was wondering if the window during doze mode will be wide enough to allow these downloads.
I have searched across Google and have come across a few loose data details claiming 5 - 10 minutes.
Can anyone please guide me to the correct information.
Thanks and regards.
10 minutes
It seems to be documented, now, finally!
‡ If network access is restricted, the app is granted a window of 10
minutes to use the network at the specified interval.
BUT,
You can't count on it to be the same across all the Android devices out there. Of course, the OEM can alter this. The answer would therefore be, a few minutes as no OEM would insensibly put it out to be just a minute or two.
Related
I've been using WorkManager to create notifications for my app. For my purposes I figured PeriodicWorkRequest is the most fitting, but after a bit of testing and reading online it's seems extremely unreliable. Using the minimal interval (15 minutes), and the app being closed, the worker woke up 5-6 times and then seems to be killed.
So how does one go about creating background work that wakes up in reasonable time intervals? What is the best approach for creating event-based notification? My idea was checking for the event (for example, checking for something new in the database) in small time intervals (with 15 minutes also being less than ideal), but seeing as it doesn't work well with PeriodicWorkRequest and is also the recommended approach as per the documentation, what exactly are my options?
Basically, the idea of Android is for you not to be able to do what you want to do because we as developers try to kill the battery.
You need to see how the evolution of the restrictions goes:
Version 6 - Doze:
https://developer.android.com/training/monitoring-device-state/doze-standby
https://developer.android.com/about/versions/marshmallow/android-6.0-changes#behavior-power
Version 7 Another state of Doze with even more restrictions:
https://developer.android.com/about/versions/nougat/android-7.0-changes#perf
Broadcast Restrictions:
https://developer.android.com/guide/components/broadcasts
https://developer.android.com/about/versions/nougat/android-7.0-changes#bg-opt
Version 8.0 Background execution limits:
https://developer.android.com/about/versions/oreo/background#services
Version 9 StandBy Buckets - where depending on how the app is used you have different resources to use - like time to wake up the app, time to use the Network, etc
https://developer.android.com/about/versions/pie/power#buckets
https://developer.android.com/about/versions/12/behavior-changes-all#restrictive-app-standby-bucket
https://developer.android.com/topic/performance/appstandby
Battery Save improvements:
https://developer.android.com/about/versions/pie/power#battery-saver
Power Management Restrictions - really important.
https://developer.android.com/topic/performance/power/power-details
Version 11 and 12 App hibernation
https://developer.android.com/topic/performance/app-hibernation
Long story short - you need to prevent all these restrictions to harm your work. But you need to comply because it is better for the user.
But there is no API that will just say - "f**k all these restrictions and do whatever the dev wants to do."
If you need exact timing - you need AlarmManager.
If you do not know when you need to do your work and depend on the outside - Push Notifications which then can transfer the work to the WorkManager.
If you need periodic work that is not time-critical - you might not use the AlarmMangaer and be sure that the work is finished, but you can't be sure when, because there are many restrictions and the priority will be saving the resources.
Also, you can ask the user to be exempted from Battery Optimization:
https://developer.android.com/training/monitoring-device-state/doze-standby#support_for_other_use_cases
If you want to know why exactly the work is not executed you need to check the JS dump and see what restriction is not satisfied:
https://developer.android.com/topic/libraries/architecture/workmanager/how-to/debugging#use-alb-shell0dumpsys-jobscheduler
I want to sync the data with server between 12 am - 6 am only.
I have solutions like WorkManager and sync adapter at my disposal.
But some manufactures put restrictions on these work managers and syncadapter also.
What is a sure shot solution that a network request will can be made between these non active hours(most users are not using the app) ?
There is no sure solution. This is Android. Every vendor can do whatever they like.
What restrictions you are talking about? Because you are saying "some vendors"? In general Android applies restrictions related to how much time you can be executed per 24 hours period and how much network you can use. It is dependant on the Power Bucket you are in. And the Power Bucket itself depends on how often the user interacts with your app. Check here:
https://developer.android.com/topic/performance/power/power-details
You can implement a dialog asking the user to exempt you from Battery Optimization. This will fix the restrictions on most vendors. Check here:
https://developer.android.com/training/monitoring-device-state/doze-standby#support_for_other_use_cases
Problem Background
Currently, we have facing "Excessive network usage (background)" from Android Vital report. Last 30 days is 0.04%, but we're only Better than 9%
Last 30 days - 0.04%
Benchmark - Better than 9%
Since only better than 9% looks like a scary thing. We decide to look into this issue seriously.
The app is a note taking app (https://play.google.com/store/apps/details?id=com.yocto.wenote), which provides an optional feature - sync to cloud in background after the app close.
This is how we perform sync to cloud in background.
We use WorkManager.
In Application onPause, Schedule OneTimeWorkRequest, with constraint NetworkType.CONNECTED. The worker is scheduled to start with delay 8 seconds.
In case failure, we retry using BackoffPolicy.LINEAR, with delay time 1.5 hours.
The maximum number of retry is 1 time. That's mean, after the app close till the app re-open again. The maximum number of execution, of sync to cloud process is 2.
The size of data is vary, can be few KB till few hundred MB.
Additional information how we perform sync
We are using Google Drive REST API.
We are performing downloading of a zip file from Google Drive App Data folder, perform data merging in local, then zip, and re-upload the single zip file back to Google Drive App Data folder.
The zip file size can ranged from few KB, to few hundred MB. This is because our note taking app supports image as attachment.
Analysis
The only information we have is https://developer.android.com/topic/performance/vitals/bg-network-usage .
When an app connects to the mobile network in the background, the app
wakes up the CPU and turns on the radio. Doing so repeatedly can run
down a device's battery. An app is considered to be running in the
background if it is in the PROCESS_STATE_BACKGROUND or
PROCESS_STATE_CACHED state.
...
...
... Android vitals considers background network usage excessive when an
app is sending and receiving a combined total of 50 MB per hour while
running in the background in 0.10% of battery sessions.
We start the background sync job, 8 seconds after Application's onPause. During that period, will the app inside or outside PROCESS_STATE_BACKGROUND/PROCESS_STATE_CACHED? How can we avoid running inside PROCESS_STATE_BACKGROUND/PROCESS_STATE_CACHED?
What does it mean by "running in the background in 0.10% of battery sessions."? How can we avoid such?
Another assumption, is sync file is too large, and using too much data. Soon, we notice this assumption might not be true. We notice according to "Hourly mobile network usage (background)", the data size is from 0MB to 5MB.
Questions
My questions are
What is the actual root cause for such "Excessive network usage (background)" warning? How can we accurately find out the root cause.
How does other apps (Like Google Photo, Google Keep, Google Doc, ...) which perform background sync, tackle this problem?
For your first question, "Excessive network usage (background)" is triggered when:
... an app is sending and receiving a combined total of 50 MB per hour while running in the background in 0.10% of battery sessions. A battery session refers to the interval between two full battery charges.
Source
To identify what is causing this, try using Battery Historian to analyse your app's battery usage over time. For us, it helped identify a repeating wakelock we didn't intend to introduce.
Here's an example of the output, showing us that excessive BLE scanning is causing a major battery impact:
For your second question, WorkManager is likely what you are after, as you correctly identified. This allows you to schedule a task, as well as a window you'd like it to occur in. Using this allows the OS to optimise task scheduling for you, along with other app's jobs. For example, instead of 6 apps all waking the device up every 10 minutes for their hourly task, it can be scheduled to happen for all 6 apps at the same time, increasing the time spent in doze mode.
Notice the screenshot above includes a "JobScheduler Jobs" tab. After running an analysis you'll be able to see how your jobs are actually performing:
I've previously used Firebase JobDispatcher with great success (tutorial I wrote), which extends the OS' JobScheduler API and is ultimately similar.
I see you're using WorkManager now (Jetpack's version of JobDispatcher), but with 8 seconds there's no chance for the OS to optimise your jobs. Is there any capacity of scheduling them with a minimum of a few seconds, and as large a maximum as possible?
Further improvements
However, your current task scheduling setup may not be the root cause. Here's a few additional ideas that may provide the battery improvement you need. The usefulness of them will become clearer after you've run Battery Historian and identified the root cause:
Consider whether wifi-only is a feasible default / option for data syncing. You'll experience better battery usage, fewer network issues, and likely better customer satisfaction.
Why does a note taking app need to sync a few hundred MB? Can you perhaps just sync the note that has changed, instead of the entire list of notes every time?
I want to send to my server every 24 hours how many steps I walked. I have an AlarmManager to go off alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),1000*60*60*24, pendingIntent1)
Now this is where I am stuck... how should I measure the daily steps?(remember I need to send this in the background) I can use this a service that could override this function public void onSensorChanged(SensorEvent event) this doesn't seem so accurate since my Service could be destroyed(and battery will get drained very fast).
Or
I can try and use the Google Fitness but I need to request connection from user every time I try to get the data mGoogleApiClient.connect()(I need to get this data in the background)
Anyone have experience doing this?
onSensorChanged() does work properly. Sensor should be good enough in the device that it should not count vibration as a step. But the only problem while capturing the step count with onSencorChanged() is that if we shake the device it count it as a step. To avoid this, most of the solutions will implement tracking the location and send to the backend so that backend would calculate if the device has actually moved. It sends the actual step count back to device which can be displayed.
Leaving this, for your case if you think service-gets-destroyed is your concern, you can restart it in a guaranteed way. See my answer to Unable to restart the service. This explains how to restart service using UncaughtExceptionHandler when app is killed through recent tasks or by system in low memory situation. Your service does not run in deep sleep mode. You can get it run using WakefulBroadcastReceiver and startWakefulService().
You should reduce the frequency of sending data to backend to as less as possible to avoid draining battery.
I am not sure of GoogleFit API. Research on this for yourself and you can add answer to your question. ;-)
UPDATE:
Read Suspend Mode about sensors in android.
Nice point to note :
“Suspend” is a low-power mode where the SoC (System on Chip) is not
powered. The power consumption of the device in this mode is usually
100 times less than in the “On” mode.
I only need a rough guide on this really at this point, though specific calculations would obviously be welcome too!
I'm looking at using Radius Network's Android iBeacon Library in an app which will listen for iBeacon advertisements.
I'm new to this but from what I understand it's the scanning for BT devices which is the most battery intensive part of the BLE system so it's not advised to have this running constantly, however I would like to be able to 'catch' devices when they are in a certain area, i.e. a person walking through a lobby.
The Android Beacon Lib's documentation states that the Battery Manager's default setting scans for 30 seconds every 5 minutes (actively scanning for 10% of the time) and this reduces the battery drain on a Nexus 5 from roughly 90mA to 37mA.
My question is... would scanning for 3 seconds every 30 seconds (also 10% of the time) acieve the same battery savings? Or is there an overhead involved in starting the scanning process which would mean the savings would be less? and if so by how much?
You would have to measure to be sure, but I would suspect you would get similar power savings from the cycle you describe (it may be slightly less savings because of startup overhead as you suggest.)
The disadvantage of this approach is that you may miss detections in a 3 second interval, especially in areas with lots of beacons, distant beacons, or with beacons transmitting infrequently. You have to decide if it is worth the tradeoff.
To test power savings, do the following:
On a test device, uninstall as many apps as possible to limit background activity that might use power in unpredicatble ways.
Install an app that implements background scanning on the cycle you describe and start it on your device.
Charge the battery to 100℅
Turn off WiFi and mobile data to prevent system downloads from using power in unpredictable ways.
Note the time, turn off the screen, and let the device rest, checking it every hour or so for battery level.
When the battery reaches 5%, note the time.
Repeat the above test with the app doing a constant scan in the background.
The end result of the above procedure will give you the time it took to drain the battery in both cases. From this you can calculate the percentage difference in power savings.
Please let us know what you find!