I am running service background to execute some tasks with some interval using AlaramManager (setExactAndAllowWhileIdle). If its connected the power charger its running. But if its unplugged device power after some i am loosing the network to my application.
Alaram is waking up the service even device is idle.But my app don't have network.
As per https://developer.android.com/training/monitoring-device-state/doze-standby.html# its restricting the network when phone is idle.I tested the same with applying phone idle ($ adb shell dumpsys battery unplug)
But is there any possible to get network access to my application even phone is idle mode.
Application is not of play store. Its really appropriated for suggestion.
I've used PowerManager.isDeviceIdleMode() in your running service to detect whether you're in Doze and if so just invoke setAlarmClock() method with 250 millis (for example) and random broadcast just to wake the device up, it'll completely wake up from doze and thus will get network access as usual. THe down side is that you lose the battery saving that comes with doze.. :D Please mark this as useful should it actually be usefull in your case.
Once your service (set up with setExactAndAllowWhileIdle()) you can go :
private boolean isDeviceInDozeMode() {
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
return pm.isDeviceIdleMode();
So now you know that you're in DOZE or not.
Then you can just set up AlarmClock and set it with setAlarmClock(AlarmClockInfo a, PendingIntent p)
And you're out of Doze with normal network access.
NOTE: Please remember that using setExactAndAllowWhileIdle doesn't mean that your alarm will go off at specified time, it will go off sooner than normal set() method, but not exact (as the method name would suggest). Generally my way isn't perfect in terms of scheduling, but it does exit DOZE programmatically once it's detected on device.
Let me know should you need more update.
I tried many options but none of them works, But finally this works to me.It might help for others.
we can always ask the user to let your app ignore battery optimization functionality using
PowerManager powerManager = (PowerManager)
getSystemService(Context.POWER_SERVICE);
Intent intent=new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
if (powerManager.isIgnoringBatteryOptimizations(getPackageName())) {
intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
}
else {
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
and in the manifest
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"></uses-permission>
But remember this might make your app not approved by Google Play
https://developer.android.com/training/monitoring-device-state/doze-standby.html#whitelisting-cases
Related
I'm developing a tracking application that runs on Wear OS watches. I have some troubles when the watch goes to sleep. As soon as the watch goes to Deep Idle mode, all sensors acquisition stops. For that I'll need to whitelist the app using:
Intent intent = new Intent();
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
context.startActivity(intent);
This piece of code works well on mobile version but nothing happen on Wear OS version. I realized that Wear OS as no UI to set the battery optimization mode which should be the cause of the fact that nothing happens when trying to change the optimization.
I also used a wake lock to keep the CPU partially awake with:
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MY-WAKELOCK");
But even with that the watch goes to deep sleep after about 15min ?
The last solution I see is to force the screen on or at least dimmed but it will drain the battery very fast.
Is there another solution to keep sensors working ? How can I whitelist my app on a Wear OS device as no UI seems available ? As anyone already encountered this issue?
I have created an application that generates a tracklog of the Android devices location. A GPS coordinate is recorded at regular intervals and stored on the device for later download. Currently, when the phone goes on standby, the program stops recording points. Is there a method that would allow the application to continue documenting location while the unit is on standby? Thanks in advance.
According to android documentation, if your app targets API level 26 or higher, the system imposes restrictions on running background services when the app itself isn't in the foreground. Also for accessing location in the background you may need additional permissions
You can run a foreground service with showing an ongoing notification if you want to run a service which is always alive in the background. Or you can schedule tasks using WorkManager.
I found two solutions.
1.) Use Wakelock
public void wakeLock() {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "MyApp::MyWakelockTag");
wakeLock.acquire();
}
with the following added to the manifest XML file,
<uses-permission android:name="android.permission.WAKE_LOCK"/>
or, 2.) use WindowManager to keep the device awake,
public void noSleep() {
if (bNoSleep == true){
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
} else if (bNoSleep != true){
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
}
I've chosen the latter as a user selectable feature accessible via checkbox in the main workspace. I've also set this to engage automatically when a tracklog is initiated with the user having the option to disable this and allow standby/sleep to occur. I did implement a wakelock, but had some issues with it that may be related to a custom ROM on some of my Android devices. This is why I went ultimately went w/the windowmanager solution.
I was having problem whit android media player because when I turn off the screen the system goes to sleep mode and stop it and I didnt want that because nobody wants to listen music and have the screen on (who do that?).
I noticed that the problem was on the battery optimizations because if the mobile was plug to power cable it keeps the music playin even if it goes to sleep mode.
I tried with a lot of posibilities to fix it (reading android documentation and trying every thing I was finding in the net) but what works was this code:
public void doPower() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String packageName = getActivity().getPackageName();
PowerManager pm = (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE);
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
try {
//some device doesn't has activity to handle this intent
//so add try catch
Intent intent = new Intent();
intent.setAction(android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);
} catch (Exception e) {
}
}
}
}
The problem here is: The app at the beginning shows an alert asking the user to disable the battery optimizations and I dont want that, because some users may thinks "this is a bad thing" or "why its asking this?" Because an app like spotify doesnt do it.
How can I avoid the alert message? If I cant, how can I add something else to the message? (something like this: "So you will able to listen the radio with the screen turn off")
Thanks in advance and best regards.
You can't avoid that dialog and asking to avoid battery optimizations is absolutely not needed.
What is needed is a wakelock, as described in the MediaPlayer Using wake locks documentation:
When designing applications that play media in the background, the device may go to sleep while your service is running. Because the Android system tries to conserve battery while the device is sleeping, the system tries to shut off any of the phone's features that are not necessary, including the CPU and the WiFi hardware. However, if your service is playing or streaming music, you want to prevent the system from interfering with your playback.
In order to ensure that your service continues to run under those conditions, you have to use "wake locks." A wake lock is a way to signal to the system that your application is using some feature that should stay available even if the phone is idle.
If you're using MediaPlayer, this only requires you use the setWakeMode() method:
mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
(Note the additional note on the documentation page about holding a wifi lock if you're streaming your media from the network.)
Hi:
I'm curiously about how to show this dialog. When I press allow, the battery optimize is disabled for this app. Is it an new android api
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String packageName = context.getPackageName();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
Intent intent = new Intent();
intent.setAction(android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse("package:" + packageName));
context.startActivity(intent);
}
}
Also, you need to add the following permission in manifest
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
This is part of the new App Standby feature introduced with API 23 (Marshmallow) alongside Doze Battery Optimization aimed to optimize power and resource usage while the app is in background (App Standby) or when the device has long been in sleep (Doze).
Following is the explanation from the Android Developer's site page:
Specifically, in the App Standby mode, the system determines that an app is idle when the user is not actively using it. The system makes this determination when the user does not touch the app for a certain period of time and none of the following conditions applies:
The user explicitly launches the app.
The app has a process currently in the foreground (either as an activity or foreground service, or in use by another activity or foreground service).
The app generates a notification that users see on the lock screen or in the notification tray.
The app is an active device admin app (for example, a device policy controller). Although they generally run in the background, device admin apps never enter App Standby because they must remain available to receive policy from a server at any time.
When the user plugs the device into a power supply, the system releases apps from the standby state, allowing them to freely access the network and to execute any pending jobs and syncs. If the device is idle for long periods of time, the system allows idle apps network access around once a day.
So, this means that starting from API 23 (Marshmallow), the device may actively put your app on standby, preventing network access (say for task like sync) and limiting (or disabling) background executions. Now, for most of the apps this behavior is fine or you could easily optimize for such behavior, but for some apps out there this may cause some unexpected behavior, especially for apps that have been poorly optimized or use non-standard sync strategies or some other means of background sync/execution.
So to circumvent that, the user can explicitly mark the app as non-optimized and the system will fallback and not put the app to standby, although this leads to a poorer user experience and you should not be doing this for regular apps that could be optimized.
Is it possible to use network access when doze is active? If my app is ignoring battery optimization doesn't go in standby but it's affected by doze anyway. Am I missing anything?
Network access is disabled in doze mode, regardless if your application is ignoring battery optimizations. The only way to wake-up your device from doze mode and to get network access is by sending a high priority Google Cloud Message to your application.
Edit: it is possible to let Android ignore battery optimization for your application, which effectively disables doze mode for your application. However, this requires using the method setExactAndAllowWhileIdle (maximum one wakeup each 15 minutes) and user interaction, which can be done like this:
Intent intent = new Intent();
String packageName = context.getPackageName();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
//battery optimizations toggle
if (pm.isIgnoringBatteryOptimizations(packageName))
//give the user the option to enable battery optimizations again
intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
else {
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
}
context.startActivity(intent);
Edit: it was suggested to add the permission android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS to the manifest. Besides that this is unnecessary for the suggested solution, it will result your app to be removed from the Play store.
According to the documentation, you can now have a foreground notification for your app which would defy the doze mode and your app should be able to access the network.