设备处于休眠状态时可运行的Android计时器

Ric*_*ich 13 android timer clock reliability persistent

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

我第一次尝试使用Handler.postDelayed()来触发每200ms的时钟滴答和WindowManager.LayoutParms.FLAG_KEEP_SCREEN_ON,以确保屏幕超时不会停止"时钟".但我很快了解到,这是可以通过按下电源按钮手动把睡觉的装置来规避这种方法.此外,postDelayed()方法正在经历一些时钟漂移,显然是在run()方法中花费的时间的结果.实际数字仍然是准确的,但不是对齐,例如,在用户容易理解的5秒边界上 - 所涉及的定时器开始漂移,导致一些可理解的用户混淆.

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

我将尝试组合AlarmManager和PartialWakeLock.我们的想法是,AlarmManager将有助于对抗时钟漂移和PartialWakeLock,以帮助保持代码简单(手指交叉).我希望这种方法能够在节能,代码复杂性和用户期望之间取得合理的平衡.任何意见是极大的赞赏.

谢谢,

丰富

Ric*_*ich 4

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

事实证明,当我应该使用SystemClock.elapsedRealtime()时,我却使用了 SystemClock.uptimeMillis()。两者之间的区别很微妙,但很重要。

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

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

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

干杯,丰富