当设备处于睡眠状态时工作的Android定时器

当设备处于睡眠状态时工作的Android定时器,android,timer,clock,persistent,reliability,Android,Timer,Clock,Persistent,Reliability,我正在编写一个体育应用程序,需要跟踪四分之一/一半/期间的运行时间。经过的时间需要精确到秒。即使用户通过按下电源按钮明确将设备置于睡眠模式,游戏时钟也需要继续运行 我的第一次尝试是使用Handler.postDelayed()每200ms触发一次时钟滴答声,并使用WindowManager.LayoutParms.FLAG_KEEP_SCREEN_ON确保“时钟”不会因屏幕超时而停止。但我很快就知道,通过按下电源按钮手动使设备进入睡眠状态,可以绕过这种方法。此外,postDelayed()方法正

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

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

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

我将尝试AlarmManager和PartialWakeLock的组合。其想法是AlarmManager将帮助对抗时钟漂移和PartialWakeLock,以帮助保持代码简单(祈祷好运)。我希望这种方法能够在节能、代码复杂性和用户期望之间取得合理的平衡。非常感谢您的建议

谢谢


Rich

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

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

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

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

另一方面,在我的调查过程中,我对自己进行了一次不相关的调查。虽然我没有直接使用这个来源的任何想法来解决这个问题,但我确实认为在可预见的未来,它将成为我的Android go-to信息来源。通过我的日常工作,我得到了O'Reilly的订阅,但我发现Commonware书籍与O'Reilly资源一样好,甚至更好,是Android开发的信息来源。我发现O'Reilly野生动物园的资源非常好。有趣的

干杯,
Rich

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

    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/设备。

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