安卓的Wakelock对于后台服务来说是否必要?

8

我正在编写一个长时间运行的后台服务,用于收集和分析设备数据。为此,我启动了一个服务,该服务生成一个线程并执行数据收集/分析。

经过我的阅读,我了解到如果我想在屏幕锁定/设备休眠时使服务继续运行,那么我应该使用部分唤醒锁(partial wakelock),以确保当服务的线程在运行时,CPU不会进入睡眠状态。然而,我真的很困惑,因为我目前没有使用唤醒锁,但仍然能够将我的应用程序置于后台或锁定屏幕或通过任务管理器杀死应用程序,并且每次我这样做时,我都可以通过logcat和日志语句观察到我在服务中生成的线程仍在运行并执行我想要的工作。

我甚至运行了一个 adb shell dumpsys power ,发现我对于唤醒锁的引用计数(refcount)等于0,这表明没有其他应用程序为我持有唤醒锁。

难道我的服务没有使用唤醒锁也能在后台正常运行吗?

编辑: 当连接到 USB 和断开 USB 连接时,设备均表现出此行为。我定期将收集的数据上传到服务器,并进行多次测试,在这些测试中,我不插入设备并且锁定屏幕,但我仍然看到我的线程在运行并上传数据。


你是在连接USB电缆的情况下进行这个操作吗? - adjan
@addy2012 我曾在连接到 USB 和断开 USB 时看到过这种行为。 - neonDion
1个回答

4
你并不是因为幸运才没有使用wakelock而服务正常,而是你的设备从未进入睡眠状态。
如果你连接了USB并提供电源,则你的设备将无法休眠。毕竟,如果你有现成的电源可用,节省电力有什么意义呢?
你需要使用adb通过IP连接到你的设备(adb connect),然后从那里进行logcat,查看是否仍然观察到预期的日志记录。
编辑:忘记实际回答问题了。
如果你希望你的服务一直运行,那么你需要保持wakelock。请记住,永久保持wakelock基本上是移动编程中的罪状#1。你应该绝对不要永久保持wakelock
由于你的服务正在跟踪数据使用情况,所以没有必要保持wakelock,因为如果设备处于睡眠状态,则不存在需要记录的数据。
编辑2:让我们来做个实验!
嗯,强制使设备进入睡眠状态有点困难,所以我们直接采用核选项。
  1. 修改你的代码,使其不是上传数据,而是存储一些元数据以告诉你特定时间戳会存储数据。同时,请修改你的代码,使你可以跟踪电源事件并为它们打时间戳。如果可以的话,将所有这些数据存储在内存中,以便我们没有太多系统代码运行。

  2. 将你的手机设置为飞行模式。是的,关闭所有外部连接。也不要使用ADB或logcat或任何类似的东西。

  3. 杀死所有非必要应用程序。最好卸载。

  4. 像用户一样使用UI运行你的服务。请不要使用任何测试;测试 可能 防止睡眠(在Android上了解任何事情都很难,因为睡眠是OEM的问题)。

  5. 等待一段时间。

  6. 使用带有时间戳的内存日志转储。你可能无法获得关于睡眠发生时间的准确数据,甚至可能无法告诉你是否睡眠了。但你应该能够从返回到刚才所处状态时的奇怪电源事件顺序中推断出来。


我编辑了我的问题,包括更多的信息。无论我是否连接到USB,我都会看到这种行为。我之前进行过一整天的测试,设备放在桌子上,没有插入任何东西,屏幕关闭。只要设备有电池,我的后台服务就会按预期开始并上传数据。(但是谢谢你提到USB的提示,我没有考虑到它可能会混淆我的结果)。 - neonDion
编辑了我的答案,并提供了一个你可以尝试的实验。目前为止,这可能是一个OEM的错误或者是你正在做一些事情,阻止系统认为它处于可休眠状态。睡眠是复杂的,因为几乎所有的“我能睡吗?”输入对用户来说都是不可见的。当然,除了显而易见的那些。 - justhecuke
5
我进行了一项长时间测试,尝试在手机未插电并锁屏的情况下运行一个服务,并每分钟上传数据。结果发现,在48小时内,有时设备会按照我的意图工作(每分钟上传),而有时会等待一个小时才上传。这证实了我需要使用wakelock来实现稳定的性能,但这也令人困惑,因为情况并非完全是黑白分明的,而是间歇性的,很难诊断出实际存在问题。 - neonDion
这就是安卓的睡眠状态 :/。很高兴看到你解决了它。 - justhecuke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接