How can I know in my app if the phone is in Doze mode or if my app is in Standby mode?
Can I also know it by using some subscribing approach?
There's a difference between App Standby (where your app goes to
sleep because it's lonely) and Doze (where the system went to
sleep because users have lives).
Doze only works when your device remains stationary. If you pick it up or wake the screen, Doze mode is deactivated and the timer
resets. It won’t ever turn on when the phone is sitting in your pocket
unless you’re sitting remarkably still. Doze simply keeps your phone
from burning through the battery while it’s asleep on a desk or table
or something.
An app that goes into Standby loses all network access and all its
background sync jobs are suspended. These restrictions are temporarily
lifted when your phone is plugged in and for a few minutes every day
or two. This gives suspended apps a chance to run any pending sync
jobs, but they won’t be allowed to continue running. A high-priority
push notification will also be able to wake an app from Standby for a
short time.
Note: Google has also noted that it isn’t acceptable for apps to
fire off notifications simply to remain exempt from App Standby. This
sort of behavior can get an app banned from the Play Store.
For more details with testing Doze and App Standby, Please visit this link: https://developer.android.com/training/monitoring-device-state/doze-standby.html
Thanks!
You don't need to do anything to manage Standby mode. You just need to manage you lifecycle as usual. There will be a time in the day when you app is gonna be resumed (so you can sync data and resume delayed jobs), but notifications and alarms will always bring your app out of standby.
Check this out: https://plus.google.com/+AndroidDevelopers/posts/76eh5MaJaXj?linkId=18331776
Related
I'm currently working on an application that causes devices connected to firestore to vibrate on cue. Currently it works fine, but after ~5+ minutes of a connected device/app being put to sleep, there is no response. Currently I have it so connected devices are given a bool field which has a listener to vibrate the device when the bool is true. I was thinking of sending a push notification to try and force the device to vibrate, but that's if there's no solution. Is there anyway to force the device to remain listening for firestore changes for an extended period of time? (listening in the background)?
This is expected behavior and not anything Firebase/Firestore controls. To conserve battery life, Android closes connections from applications if they haven't been actively used in a while.
For this reason you can't expect to keep receiving updates from Firestore (or any other such mechanism) if the app is backgrounded or if the phone is put to sleep.
The common solution for this is indeed to (also) send updates through FCM, which is treated differently by Android's power management feature.
In different sources, I read that a foreground service requires a wake lock to stay active after the device goes to sleep. But when I test it by starting a foreground service and turning the screen off while the device is unplugged (both on emulator and on a real Samsung device), the foreground service keeps running.
Does a foreground service require a (partial) wake lock to stay active after the screen is off?
From my experience of developing a timer, the answer is yes, especially when the screen is off.
Without a wake lock, the foreground service will be killed or suspended in a few minutes(2 ~ 10m in my tests). Sometimes, when the screen is off, the code won't be executed but the foreground notification still exists and the code only starts being executed after the screen is turned on. This makes debug very hard. This situation is more common if the test device is from Chinese manufacturers(Foreground service + Wake Lock + Letting user whitelist your app seems the only solid option if your app targets Chinese market).
Use a wake lock if you want your service keep running after the screen is off.
Context
We are developing an android app that is supposed to do the following:
the user installs the app, registers and closes the app
once or twice a year an admin sends a Firebase data message with priority high to the user containing a geo fence
the FCM message starts a JobService that locates where the phone is
if the phone is inside the given area an Activity is started and user interaction starts
if the phone is outside the area the service is stopped and the user is never disturbed
I developed the app based on the Firebase push example found here
The problem
The application works fine on my older phones but on my new test phone (android 8.1.0, LineageOS 15.1) we have a problem when the phone is in sleep mode. In this case the FCM message arrives instantly but the service is first started once the phone is unlocked. So the message is stuck between 2. and 3.
We need the app to respond at once - not when the user decides to use his phone 2 hours later.
I assume the problem is due to the Doze mode introduced with android 6. I tried to solve it by adding the app to the whitelist in settings->battery->battery optimization but this did not solve the problem.
Questions
Is it Doze mode that delays my app between 2. and 3.? If so why is it not solved when the app is in the whitelist?
Is there any other way to start the location service at once? This post suggests that a foreground service can do it but this requires that a notification is shown which breaks with 5.
Is there another way to start my service at once besides whitelist and foreground service?
Yes! you are right this may be due to the Doze and App Standby features introduced in API 23 Marshmallow.
As mentioned in the documentation, the system do ignore wakelocks and system doesn't allow JobScheduler to run, which effectively prevents your app from running the Job.
An easy and effective workaround would be to run Location detecting routine inside a normal background service and start it using startService() when you receive FCM push.
Note that you might still need to white-list your app because as mentioned in another post here, only a whitelisted app can use the network and hold partial wake locks.
Is it Doze mode that delays my app between 2. and 3.?
From the documentation Doze mode affect Network access and blocks JobScheduler.
If so why is it not solved when the app is in the whitelist?
Also from the documentation: An app that is whitelisted can use the network and hold partial wake locks during Doze and App Standby. However, other restrictions still apply to the whitelisted app, just as they do to other apps.
So the blocking of JobScheduler still applies.
Is there any other way to start the location service at once? This
post suggests that a foreground service can do it but this requires
that a notification is shown which breaks with 5.
Ignore Battery Optimizations (for Internet access) in combination with an AlarmManager with setAndAllowWhileIdle() or setExactAndAllowWhileIdle() should work.
Be careful with Ignore Battery Optimizations
Google Play policies prohibit apps from requesting direct exemption from Power Management features in Android 6.0+ (Doze and App Standby) unless the core function of the app is adversely affected.
I think an important question here is: Do you really need to execute the JobScheduler immediately.
If a user leaves a device unplugged and stationary for a period of time, with the screen off, the device enters Doze mode.
If the device is in Doze mode, it means the user is not using it.
if the phone is inside the given area an Activity is started and user interaction starts
This is the step Doze blocks
We need the app to respond at once - not when the user decides to use his phone 2 hours later.
If the device is in Doze it means the user is not interacting with it. Even if you show the Activity the user is not using the phone, he will see it when he starts using it 2 hours later :)
I still didn't try that,
but you might use a WakefulBroadcastReceiver:
https://developer.android.com/training/scheduling/wakelock.html
https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html
According with this links, you should declare your receiver as:
public class YourReceiver extends WakefulBroadcastReceiver {
Probably your receiver is already a WakefulBroadcastReceiver because notifications are showing..
In the receiver, you start the service (your service has to be an IntentService) using:
startWakefulService(context, your service);
Finally, remember to release the wake lock in the service:
#Override
protected void onHandleIntent(Intent intent) {
<Your_broadcast_receiver_class>.completeWakefulIntent(intent);
}
I hope it helped
I made the device which monitors person's health in sleep time and it connects to a smartphone via BLE.
It's working great with the iOS app.
But since Doze mode came on Android world.
It's really hard to deal with it because my device is working in his sleep time.
The main feature is that it detects particular danger and notify to the user while he is sleeping with the device. I need a network connection when it occurs.
Many articles tell me that I can use a network even in the doze mode if my app is in the whitelist. But it does not seem true after I tested Doze mode.
Am I right?
I can ensure that I can find my app in the lists, when I fire
adb shell dumpsys deviceidle
What is the best approach that I can take to make my app working correctly?
foreground services
alarm manager with SetExactAndAllowWhileIdle.
GCM (it means push, right?)
anything else
Any tips will help me.
Thanks.
Edit
Unfortunately, I tested with using GCM but it only wakes my app in short time. It means I have to send GCM as many as I want to keep it awake. I don't think I can use it.
Many articles tell me that I can use a network even in the doze mode if my app is in the whitelist. But it does not seem true after I tested Doze mode. Am I right?
You are not right. One of the restrictions of doze that are lifted when your app is on the whitelist, is the ability to use the network when doze is active.
An app that is whitelisted can use the network and hold partial wake locks during Doze and App Standby. However, other restrictions still apply to the whitelisted app, just as they do to other apps. For example, the whitelisted app’s jobs and syncs are deferred (on API level 23 and below), and its regular AlarmManager alarms do not fire.
From here.
In other words: you should be able to use the network in doze if you are on the whitelist.
What is the best approach that I can take to make my app working correctly?
Considering your app is a health monitor and thus should be able to do its work constantly or at least very regularly, you could put the functionality in a foreground service. Foreground services are not effected by doze.
You should be aware that you should have a good reason to use a foreground service since the user is aware of them, but I think you have one with the health monitoring etc.
Note: You should only use a foreground service for tasks the user expects the system to execute immediately or without interruption. Such cases include uploading a photo to social media, or playing music even while the music-player app is not in the foreground. You should not start a foreground service simply to prevent the system from determining that your app is idle.
From here.
I'm getting stuck on my project based on real time location tracking and update to the server.
Here i tested OS status in doze mode implementing FCM Push notification..
I used two methods to test:
Push Notification after device entering in Doze mode(Deep Sleep) :
When server send push notification to device during Deep sleep mode then
Android OS Open their Internet service for a moment and again go back to
previous mode..
During that short period we can't able to update real time tracking to
the server(some time may update to server but maximum failure case)
Push Notification before Doze mode(Deep Sleep) : Push notification
working fine but it don't affect the original deep sleep time and again
Android OS entering in Deep sleep mode without extending Doze mode time
interval.
So again we failed to track real time location update to server.
Note: Push notification can not change the Android OS status . Only OS
allows FCM for a moment and again it goes back to deep sleep mode.
Is any alternate solution to continuously track and update to the server?