我们的应用程序可以连接到HVAC设备,并且需要每10秒对其状态进行一次采样。
HVAC设备暴露Modbus接口,CAN NOT缓冲样本。我们实际上需要每10秒唤醒一次服务。典型的样本会话持续1小时到几个小时。 (有各种连接类型/电缆/桥接器:OTG + RS232 USB转换器,TCP通过RS232 / TCP桥接器,蓝牙经典和BLE通过RS232 / BT或BLE桥接器。)
当然,用户应该可以关闭显示屏以节省电量,并在采样会话期间导航到其他应用程序。
直到Nougat 7.0我们的工作解决方案是:
IntenService
,然后将其设置为Foreground
服务Bounded
服务(停止它,从GUI传播与HVAC设备的交互等)。PowerManager.PARTIAL_WAKE_LOCK
Thread.Sleep()
进行10秒循环,还可以管理各种连接的传输实施中的超时我应该发布代码吗?相关部件是最常见的样板。
尽管没有书面保证,但前景服务中Thread.Sleep()
PowerManager.PARTIAL_WAKE_LOCK
的工作完全正常,直到Nougat 7.0
在我们测试的Oreo设备上,编译目标API 26和23(作为我们之前发布的版本),同时不与应用程序活动交互(关闭显示,其他应用程序在前台等),服务不会唤醒,它会一直睡到第一次与应用程序交互。
为了能够在Oreo目标API 26上启动前台服务,我实施了来自Android O - Old start foreground service still working?的Bikram Pandit解决方案。 什么都没有改变。
我通过ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
(如https://developer.android.com/training/monitoring-device-state/doze-standby#whitelisting-cases中所述)要求电池优化例外,并授予它。没有改变。 (并且应用程序在没有它的情况下工作,直到Nougat 7.0)
有关Oreo的后台执行限制https://developer.android.com/about/versions/oreo/background的文档指出,有界服务或前台服务不应受到这些限制。然而,服务并没有醒来。
AlarmManager
无法使用,因为从奥利奥开始,它最多可以每9分钟触发一次,即使setAndAllowWhileIdle()
也不setExactAndAllowWhileIdle()
。 (再次在https://developer.android.com/training/monitoring-device-state/doze-standby#whitelisting-cases)
我还尝试使用wait(sleepTime)
代替Thread.sleep()
:更糟糕的是,它在重新启动交互时甚至没有唤醒。
我在作为JobIntentService
或使用JobScheduler
/ JobService
重新实施之前停了下来,将每个样本重新定义为作业,但是:
Thread.Sleep()
,在工作期间会唤醒吗?JobScheduler
实际上是否允许每10秒运行一次作业,还是会将它们捆绑在Oreo上?我们实际上每10秒需要一个样本。我们可能会放松到1分钟,但不能更大。JobService
中保留非常复杂的状态(我的ModbusDevice对象),在所有这些工作中分享它还是会有限制?同样,我应该发布一些代码吗?这是最常见的样板。