简体   繁体   English

在打盹模式下获取位置更新

[英]Getting location updates when in doze mode

I'm trying to get location updates in my android app when in doze mode, this used to work up to android 5.x.在打盹模式下,我试图在我的 android 应用程序中获取位置更新,这曾经适用于 android 5.x。 With android 6 and the advent of doze, no matter what I do, the updates stop at some point.随着 android 6 和瞌睡的出现,无论我做什么,更新都会在某个时候停止。 After reading a few articles and stackoverflow answers on the topic I made the following changes:在阅读了有关该主题的几篇文章和 stackoverflow 答案后,我进行了以下更改:

  • made my service a foreground service使我的服务成为前台服务
  • made the service hold a partial wake lock使服务持有部分唤醒锁
  • I've given my app the WAKE_LOCK permission我已授予我的应用 WAKE_LOCK 权限
  • made the service run in a separate process (for a workaround to some android bug)使服务在单独的进程中运行(用于解决某些 android 错误)
  • 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?在这方面,关于打瞌睡和 LocationManager 的文档非常少,所以我想知道是否有人知道让位置管理器保持打瞌睡状态的方法? Is there some method on LocationManager that if called periodically will keep the LocationManager active? LocationManager 上是否有一些方法,如果定期调用会使 LocationManager 保持活动状态? Note that I'm interested in GPS updates only, with a high update frequency, once every second.请注意,我只对 GPS 更新感兴趣,更新频率很高,每秒一次。

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.最后我找到了解决这个问题的方法,在阅读了 com.android.internal.location.GpsLocationProvider 的源代码后,我注意到向它发送一个 com.android.internal.location.ALARM_WAKEUP Intent 阻止了位置提供者打瞌睡。 So to keep the GPS from dozing I broadcast the Intent every 10 seconds, I added the following in my service class:因此,为了防止 GPS 打瞌睡,我每 10 秒广播一次 Intent,我在服务类中添加了以下内容:

[...]
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");
    [...]
}

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. Android 6 中引入的 Doze 通过将活动推迟到维护时段来减少设备的耗电量。 GPS is a huge power draw and is not allowed to run constantly in doze mode. GPS 耗电巨大,不允许在打盹模式下持续运行。 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.如果您希望 GPS 位置每 1 秒更新一次,您必须阻止设备进入打盹模式。

There was no doze mode in Android 5. Android 5 中没有打盹模式。

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.如果您使用“adb shell dumpsys deviceidle force-idle”等命令在模拟器上测试位置和打盹模式。您可能注意到位置在打盹模式下停止。

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" “只要用户通过移动设备、打开屏幕或连接充电器来唤醒设备系统就会退出 Doze ,所有应用程序都会恢复正常活动”

Source : https://developer.android.com/training/monitoring-device-state/doze-standby来源: 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.所以...使用 GPS 操纵杆应用程序或类似程序移动您的模拟器,您会注意到该位置从打盹模式中唤醒。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM