【问题标题】:Android timer that works when device is sleeping设备睡眠时工作的 Android 计时器
【发布时间】:2011-06-22 12:53:07
【问题描述】:

我正在编写一个体育应用程序,它需要跟踪季度/半/周期的经过时间。经过的时间需要精确到秒。即使用户通过按下电源按钮明确将设备置于睡眠模式,游戏时钟也需要继续运行。

我的第一次尝试涉及使用 Handler.postDelayed() 来触发每 200 毫秒的时钟滴答声和 WindowManager.LayoutParms.FLAG_KEEP_SCREEN_ON 以确保“时钟”是不会因屏幕超时而停止。但我很快了解到,可以通过按下电源按钮手动使设备进入睡眠状态来绕过这种方法。此外,postDelayed() 方法正在经历一些时钟漂移,这显然是由于 run() 方法所花费的时间造成的。实际数字仍然是准确的,但不是在用户容易理解的 5 秒边界上对齐 - 所涉及的计时器开始漂移,导致一些可以理解的用户混淆。

经过一番研究,我发现了使用服务java timersAlarmManagerPartialWakeLock 来实现计时器的技术。服务本身并不能解决与设备进入睡眠相关的问题。 Java 计时器和服务一样,不能解决设备进入睡眠状态的问题。 AlarmManager 似乎是一个好方法,但我担心这不是 AlarmManager 的适当使用(即警报之间的间隔非常短)。使用 PartialWakeLock 看起来也很有希望,但它本身并不能解决我遇到的时钟漂移问题。

我将尝试结合使用 AlarmManager 和 PartialWakeLock。这个想法是 AlarmManager 将帮助对抗时钟漂移和 PartialWakeLock 以帮助保持代码简单(手指交叉)。我希望这种方法能够在节能、代码复杂性和用户期望之间取得合理的平衡。非常感谢任何建议。

谢谢,

丰富

【问题讨论】:

  • 使用 PartialWakeLock 您不会看到任何漂移,但您的电池会耗尽。
  • 您说“经过的时间需要精确到秒”。为什么不使用简单的系统时间(如 System.currentTimeMillis())?只需保存开始时的时间戳,然后在需要时从当前时间中减去它

标签: android timer clock persistent reliability


【解决方案1】:

我对上面的原始帖子有部分解决方案。它还没有解决与 postDelayed() 处理期间计算所用时间相关的时钟漂移,但它向前迈出了一步。此外,它看似简单,总是一个好兆头。

原来我使用的是SystemClock.uptimeMillis(),而我应该使用SystemClock.elapsedRealtime()。两者之间的区别很微妙,但很重要。

如您所料,我的解决方案通过累积对 postDelayed() 的调用之间的持续时间来跟踪已用时间 - 即,已用时间 = elapsedTime + lastClockInterval。如上所述,最初的实现使用 uptimeMillis()。仔细阅读javadoc reveals that uptimeMillis() 不包括在“深度睡眠”中花费的时间,例如,当用户按下电源按钮时。但是 elapsedRealtime() 方法确实包括在“深度睡眠”模式下花费的时间。跟踪深度睡眠周期中的时间所需的只是将 uptimeMillis() 的使用替换为 elapsedRealtime()。成功!无需使用 AlarmManager、PartialWakeLock 或其他任何更复杂的东西。诚然,这些方法仍然有用,但在实现简单的经过时间的时钟或计时器时,它们就显得过大了。

下一个要解决的问题是与 postDelayed() 处理相关的非零执行时间导致的时钟漂移。我希望产生一个线程来进行处理将解决这个问题,允许 postDelayed() 或多或少地模仿一个异步调用。另一种方法是调整 postDelayed() 延迟时间以考虑到 postDelayed() 所花费的时间。我会发布我的结果。

在一个不相关的说明中,在我的调查过程中,我对待自己是一个CommonsWare Warescription。虽然我没有直接使用这个来源的任何想法来解决这个问题,但我确实认为在可预见的未来它将成为我的 Android 首选信息来源。我在日常工作中订阅了 O'Reilly,但我发现 CommonsWare 书籍与 O'Reilly 资源一样,是关于 Android 开发的信息来源,即使不是更好,也一样好。而且我发现 O'Reilly Safari 资源非常好。有趣...

干杯, 丰富

【讨论】:

    【解决方案2】:

    很抱歉,这不是一个完整的答案,但我觉得你的过程与我的相似,但在代码方面几乎没有说明你是如何解决睡眠问题的。我没有漂移,但应用程序在进入睡眠模式时确实挂起,然后在显示器处于活动状态时向前重置,然后在设备睡眠时再次挂起。这是定时器进程的核心。

        Handler timerHandler = new Handler();
    Runnable timerRunnable = new Runnable() {
    
        @Override
        public void run() {
    
            // do something here to display
    
            processTime();    // process what to be done on a sec by sec basis
            try {
                timerHandler.postDelayed(this, 1000
            } catch (Exception ex){
    
            }
    
        }
    };
    

    我可以做些什么来让它在睡眠模式下继续运行吗?这适用于旧版本的 android/devices。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多