在打瞌睡模式下获取位置更新

Getting location updates when in doze mode

我正在尝试在我的 android 应用程序处于打瞌睡模式时获取位置更新,这过去一直工作到 android 5.x。随着 android 6 和打瞌睡的到来,无论我做什么,更新都会在某个时刻停止。在阅读了有关该主题的几篇文章和 Whosebug 答案后,我进行了以下更改:

但是,当打瞌睡开始时,我仍然没有获得位置更新。我已经验证我的服务线程在打瞌睡开始时保持 运行ning(通过定期记录消息),但不知何故位置经理停止发送更新。关于打瞌睡和 LocationManager 的文档在这方面非常少,所以我想知道是否有人知道让位置管理器在打瞌睡时保持活动状态的方法? LocationManager 上是否有一些方法,如果定期调用将使 LocationManager 保持活动状态? 请注意,我只对 GPS 更新感兴趣,更新频率很高,每秒一次。

您的应用程序的行为正是 doze 旨在停止的行为。 Android 6 中引入的瞌睡模式通过推迟 activity 维护 windows 来减少设备的功耗。 GPS 耗电量巨大,不允许 运行 一直处于休眠模式。如果允许这样做,电池可以 运行 以类似于屏幕打开的速度下降;网络流量的优化不会延长电池寿命。如果您希望 GPS 位置每 1 秒更新一次,则必须阻止设备进入休眠模式。

Android 5.

中没有打瞌睡模式

最后,我找到了解决该问题的方法,在通读了 com.android.internal.location.GpsLocationProvider 的源代码后,我注意到向其发送 com.android.internal.location.ALARM_WAKEUP Intent 可防止位置提供程序打瞌睡。因此,为了防止 GPS 打瞌睡,我每 10 秒广播一次 Intent,我在我的服务中添加了以下内容 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");
    [...]
}

如果您使用 "adb shell dumpsys deviceidle force-idle" 等命令在模拟器上测试定位和打盹模式。您可能注意到定位在打瞌睡模式下停止。

但是...因为"documentation"代表:

"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"

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

所以...使用 GPS 操纵杆应用程序或类似应用程序移动您的模拟器,您会注意到位置从打瞌睡模式唤醒。