【问题标题】:Delayed (timed) unregister sensor listener inside IntentService (WakefulIntentService)IntentService (WakefulIntentService) 中的延迟(定时)注销传感器侦听器
【发布时间】:2017-03-20 14:13:03
【问题描述】:

我已经实现了一个 IntentService,它使用 SensorManager 从心率传感器读取数据。

使用AlarmManagerWakefulBroadcastReceiver 定期调用它,然后在onSensorChanged 上,它使用Fitness History API 更新Google Fit 数据,使用onSensorChanged 调用的时间作为时间戳。

当然,IntentService 实现了 SensorEventListener,它使用 CommonsWare cwac-wakeful 实现为 WakefulIntentService

发生的情况是传感器读取任务需要一个非常可变的时间,有时,onSensorChanged - 我猜一旦注册传感器侦听器就会异步工作 - 甚至在几分钟后被调用,当时注册了 IntentService 实例传感器监听器,已经结束并且监听器监听(!)是一个连续的。

这意味着一系列数据读数重叠并插入到 Google Fit 中,相对于 IntentService 测量任务的原始定时调用没有任何时间顺序。

此外,这种行为还会导致电池使用异常,因为心率传感器使用几个非常亮的 LED 并且 - 除非未注册 - 一直保持活动状态,直到我猜它的硬件超时。

我尝试通过在特定超时(30 秒)后调用延迟 Runnable 的帖子来取消注册 IntentService 内的传感器侦听器,但它不起作用。

我的问题是:

有没有办法,在IntentServiceWakefulIntentService 内部,在一定的延迟后调用传感器unregisterListener,同时阻止线程结束?或者以某种方式清除 onSensorChanged 队列?

或者:有没有办法在注册时为传感器侦听器分配一个唯一 ID?这样,在onSensorChanged 内,就可以将事件与其原始IntentService 调用时间相匹配,并且可以 - 至少 - 可以以正确的时间顺序在 Google Fit 中插入读数。

提前谢谢你。

【问题讨论】:

    标签: android android-sensors intentservice commonsware-cwac sensormanager


    【解决方案1】:

    我已经实现了一个 IntentService,它使用 SensorManager 从心率传感器读取数据。

    恕我直言,这不是IntentService 的正确用法。恕我直言,IntentService 专为事务性工作而设计:磁盘 I/O、数据库 I/O、Web 服务调用等。它不是为无限期工作而设计的。

    当然,IntentService 实现了一个 SensorEventListener,它使用 CommonsWare cwac-wakeful 实现为一个 WakefulIntentService。

    WakefulIntentService不是为无限期工作而设计的。

    发生的情况是传感器读取任务需要一个非常可变的时间,有时,onSensorChanged - 我猜一旦注册传感器监听器就会异步工作 - 甚至在几分钟后被调用,当注册传感器监听器的 IntentService 实例时,已经结束,并且正在收听的听众(!)是一个连续的听众。

    一般来说,不能保证您将获得任何传感器读数,因为一旦服务被破坏,您的进程可能随时终止。

    有没有办法在 IntentService 或 WakefulIntentService 内部在一定延迟后调用传感器 unregisterListener,同时阻止线程结束?

    没有任何可靠的方式。

    摆脱WakefulIntentService。使用普通的Service。注册传感器事件。当您获得所需的事件时,请取消注册传感器侦听器和stopSelf() 服务。在此过程中,管理您自己的WakeLock

    或者以某种方式清除 onSensorChanged 队列?

    我不知道。

    有没有办法在传感器侦听器注册时为其分配唯一 ID?

    侦听器对象已经是唯一的。为什么 ID 会使其更加独特?

    话虽如此,欢迎您在侦听器对象中放置一个字段,该字段具有您喜欢的任何类型的独特值。

    【讨论】:

    • 谢谢。我正在实现一个由 WakefulBroadcastReceiver 启动的服务。你建议我在哪里获取和释放唤醒锁?在 onCreate 中获取并在 onDestroy 中释放,还是在 onSensorChanged 中的 stopSelf 之后立即释放它?谢谢!
    • @Veertualia:“你建议我在哪里获取和释放唤醒锁?” -- 即兴发挥,我会在onStartCommand() 中获得一个引用计数的WakeLock(然后从WakefulBroadcastReceiver 中释放WakeLock)。然后,释放WakeLock 作为stopSelf() 处理的一部分。您可以查看我的 WakefulIntentService 以获得灵感,尽管这不是直接的解决方案。
    • 我照你说的做了。现在 Runnable 工作了,我可以在取消注册监听器之前设置一个超时,所以当传感器花费太长时间并且没有更多重叠的 onSensorChanged 时,我可以停止传感器。刚刚好。我怎样才能给你正确的信用@CommonsWare?
    • @Veertualia:我很高兴事情对你有用。在 Stack Overflow 上,如果答案回答了您的问题,请选中问题旁边的复选标记,从而接受它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-14
    • 2020-05-05
    • 1970-01-01
    • 2020-07-05
    相关资源
    最近更新 更多