10

I'm trying to get location updates in my android app when in doze mode, this used to work up to android 5.x. With android 6 and the advent of doze, no matter what I do, the updates stop at some point. After reading a few articles and stackoverflow answers on the topic I made the following changes:

  • made my service a foreground service
  • made the service hold a partial wake lock
  • I've given my app the WAKE_LOCK permission
  • made the service run in a separate process (for a workaround to some android bug)
  • I've disabled battery optimizations for my app

But still, I'm not getting location updates when doze kicks in. I've verified that my service thread keeps running when doze starts (by periodically logging a message), but somehow the location manager stops sending updates. The documentation on doze and the LocationManager is pretty scant in this regard, so I was wondering if somebody knows of a way to keep the location manager alive in doze? Is there some method on LocationManager that if called periodically will keep the LocationManager active? Note that I'm interested in GPS updates only, with a high update frequency, once every second.

3 Answers3

2

In the end I found a workaround for the issue, after reading through the source code of com.android.internal.location.GpsLocationProvider I noticed that sending it an com.android.internal.location.ALARM_WAKEUP Intent prevented the location provider from dozing. So to keep the GPS from dozing I broadcast the Intent every 10 seconds, I added the following in my service class:

[...]
private Handler handler;
private PowerManager powerManager;

private PendingIntent wakeupIntent;
private final Runnable heartbeat = new Runnable() {
    public void run() {
        try {
            if (isRecording && powerManager != null && powerManager.isDeviceIdleMode()) {
                LOG.trace("Poking location service");
                try {
                    wakeupIntent.send();
                } catch (SecurityException | PendingIntent.CanceledException e) {
                    LOG.info("Heartbeat location manager keep-alive failed", e);
                }
            }
        } finally {
            if (handler != null) {
                handler.postDelayed(this, 10000);
            }
        }
    }
};

@Override
public void onCreate() {
    handler = new Handler();
    wakeupIntent = PendingIntent.getBroadcast(getBaseContext(), 0,
        new Intent("com.android.internal.location.ALARM_WAKEUP"), 0);
    locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
    powerManager = (PowerManager) getSystemService(POWER_SERVICE);
    wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TrackService");
    [...]
}
  • 8
    can you share your complete TrackerService class code please if possible? I am new to android and having the same problem. – Shaw Aug 17 '18 at 04:17
  • This seems to no longer work - at least on Android 11 – Dave Nottage Jan 18 '21 at 21:15
  • 1
    I am using FusedLocationProviderClient.requestLocationUpdates and this way doesn't work. Testes on Android 9 and 10. Thank you for sharing. – Nghi-Le Oct 14 '21 at 00:25
1

If you test location and doze mode on the emulator with commands like "adb shell dumpsys deviceidle force-idle" etc. You probably noticed that location stops in Doze Mode.

But ... as "documentation" stands for :

"As soon as the user wakes the device by moving it, turning on the screen, or connecting a charger, the system exits Doze and all apps return to normal activity"

Source : https://developer.android.com/training/monitoring-device-state/doze-standby

So ... move Your emulator with GPS Joystick App or similar and You will notice that location wakes up from Doze Mode.

0

Your application's behavior is precisely what doze is designed to stop. Doze, introduced in Android 6, reduces a device's power usage by deferring activity to maintenance windows. GPS is a huge power draw and is not allowed to run constantly in doze mode. If this were allowed, the battery could run down at a rate similar to with the screen on; the optimizations for network traffic would not achieve increased battery life. If you want GPS location updates every 1 second, you must stop the device from entering doze mode.

There was no doze mode in Android 5.

Community
  • 1
  • 1
mattm
  • 5,851
  • 11
  • 47
  • 77
  • 4
    I'm aware of what doze is for, however it's _my_ device and I should be able to declare that's ok to drain my battery for a purpose that is useful to me, in this case record a GPS track. It's also a not uncommon use case, for example runkeeper and strava need to do the same. Stopping the device from entering doze seems to be a hack, and having to turn on the screen to fight something that is meant to save battery life seems backwards to me. – Kornelius Elstner Sep 17 '17 at 07:03
  • 1
    @KorneliusElstner If you are running with the device, it will not enter doze mode. "As soon as the user wakes the device by moving it, ... the system exits Doze and all apps return to normal activity." – mattm Sep 17 '17 at 11:26
  • 1
    Good point Kornelius. We paid for our devices, we should be able to do whatever we want with them. The device has a permission system Google, use it and stop trying to protect us from ourselves. We don't need nanny treating us like children. – Gerry Jun 03 '20 at 18:28