【问题标题】:Getting location updates when in doze mode在打盹模式下获取位置更新
【发布时间】:2018-02-25 12:38:17
【问题描述】:

我在打瞌睡模式下尝试在我的 android 应用程序中获取位置更新,这曾经适用于 android 5.x。随着 android 6 和 doze 的出现,无论我做什么,更新都会在某个时候停止。在阅读了有关该主题的几篇文章和 stackoverflow 答案后,我进行了以下更改:

  • 使我的服务成为前台服务
  • 使服务持有部分唤醒锁
  • 我已授予我的应用 WAKE_LOCK 权限
  • 使服务在单独的进程中运行(用于解决某些 android 错误)
  • 我已为我的应用禁用电池优化

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

【问题讨论】:

    标签: android locationmanager android-gps android-doze


    【解决方案1】:

    最后我找到了解决该问题的方法,在阅读了 com.android.internal.location.GpsLocationProvider 的源代码后,我注意到向它发送 com.android.internal.location.ALARM_WAKEUP Intent 阻止了位置提供程序从打瞌睡。因此,为了防止 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");
        [...]
    }
    

    【讨论】:

    • 如果可能的话,你能分享你完整的 TrackerService 类代码吗?我是 android 新手,遇到了同样的问题。
    • 这似乎不再起作用 - 至少在 Android 11 上
    • 我正在使用 FusedLocationProviderClient.requestLocationUpdates,这种方式不起作用。在 Android 9 和 10 上测试。感谢您的分享。
    【解决方案2】:

    您的应用程序的行为正是doze 旨在阻止的行为。 Android 6 中引入的 Doze 通过将活动推迟到维护时段来降低设备的功耗。 GPS 耗电巨大,不允许在打盹模式下持续运行。如果允许,电池可能会以与屏幕打开时相似的速度耗尽;网络流量的优化不会增加电池寿命。如果您希望 GPS 位置每 1 秒更新一次,您必须阻止设备进入打盹模式。

    Android 5 中没有打盹模式。

    【讨论】:

    • 我知道打瞌睡的用途,但它是 我的 设备,我应该能够声明可以耗尽我的电池用于对我有用的目的,在这种情况下记录 GPS 轨迹。这也是一个不常见的用例,例如 runkeeper 和 strava 需要做同样的事情。阻止设备进入打瞌睡似乎是一种黑客行为,而不得不打开屏幕来对抗旨在节省电池寿命的东西对我来说似乎倒退了。
    • @KorneliusElstner 如果您正在使用该设备运行,它将不会进入打盹模式。 “一旦用户通过移动设备唤醒设备,......系统退出打盹,所有应用程序恢复正常活动。”
    • 好点 Kornelius。我们为我们的设备付费,我们应该能够对它们做任何我们想做的事情。该设备有一个权限系统谷歌,使用它并停止试图保护我们自己。我们不需要保姆像对待孩子一样对待我们。
    【解决方案3】:

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

    但是......作为“文档”代表:

    “一旦用户通过移动设备、打开屏幕或连接充电器来唤醒设备,系统就会退出打盹,所有应用都会恢复正常活动”

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

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

    【讨论】:

      猜你喜欢
      • 2018-10-22
      • 2017-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多