永久地在背景中宣传低能耗

时间:2015-04-17 15:58:45

标签: android android-service bluetooth-lowenergy android-bluetooth

我想尽可能在​​后台使用BLE宣传UUID。如果一个用例有帮助,想象我的应用程序是一个无钥匙进入应用程序,其中手机是一个外围设备,锁是一个中心,因此必须始终在BLE打开时做广告。我的应用程序包含响应BroadcastReceiver事件的ACTION_STATE_CHANGED,并在当前状态为STATE_ON时开始做广告。我的问题是坚持不懈。

如果我在没有打开应用程序的情况下打开蓝牙,广告就会开始,但会在一段时间后停止。如果我在广告正在运行的任何时候打开应用程序,然后强行关闭它,广告就会停止,引用:

04-16 15:03:11.815  19411-19424/? D/BtGatt.GattService﹕ Binder is dead - unregistering client (5)!
04-16 15:03:11.815  19411-19425/? D/BtGatt.GattService﹕ Binder is dead - unregistering server (6)!
04-16 15:03:11.815  19411-19425/? D/BtGatt.GattService﹕ unregisterServer() - serverIf=6
04-16 15:03:11.816  19411-19425/? D/BtGatt.GattService﹕ deleteServices() - serverIf=6
04-16 15:03:11.816  19411-19425/? D/BtGatt.btif﹕ btif_gatts_delete_service
04-16 15:03:11.816  19411-19432/? D/BtGatt.btif﹕ btgatts_handle_event: Event 2010
04-16 15:03:11.817  19411-19446/? E/bt-att﹕ Active Service Found
04-16 15:03:11.817  19411-19432/? D/BtGatt.btif﹕ btapp_gatts_handle_cback: Event 11
04-16 15:03:11.817  19411-19432/? D/BtGatt.GattService﹕ onServiceDeleted() srvcHandle=40, status=0
04-16 15:03:11.817  19411-19425/? D/BtGatt.btif﹕ btif_gatts_unregister_app
04-16 15:03:11.817  19411-19432/? D/BtGatt.btif﹕ btgatts_handle_event: Event 2001
04-16 15:03:11.820  19411-19432/? D/BtGatt.btif﹕ btapp_gatts_handle_cback: Event 6
04-16 15:03:11.821  19411-19444/? D/BtGatt.AdvertiseManager﹕ message : 1
04-16 15:03:11.821  19411-19444/? D/BtGatt.AdvertiseManager﹕ stop advertise for client 5
04-16 15:03:11.822  19411-19444/? D/BtGatt.AdvertiseManager﹕ app died - unregistering client : 5
04-16 15:03:11.822  19411-19444/? D/BtGatt.GattService﹕ unregisterClient() - clientIf=5
04-16 15:03:11.828  19411-19432/? D/BtGatt.GattService﹕ onAdvertiseInstanceDisabled() - clientIf=255, status=0

因此,似乎蓝牙管理器以调用应用程序组件的方式绑定。为了解决这个问题,我创建了一个由Service启动的BroadcastReceiver,具有以下特征:

  • 如果启用了蓝牙,则启用LE广告
  • 除非蓝牙已关闭(在服务中注册接收者才能执行此操作),否则切勿拨打stopSelf()
  • 如果不是第一次通话,则忽略对onStartCommand()的多次通话。
  • START_STICKY
  • 返回onStartCommand()

因此,如果收到服务,它将清除onDestroy()中的蓝牙代码并稍后重新启动。如果应用程序被强制关闭,则会发生同样的事情。

有没有办法可以强制蓝牙运行而不关心它的内容?如果没有,这看起来像一个可行的结构?请戳一下洞。编辑:我担心的一件事就是让这个Service对象永远存在并对电池寿命产生影响。应该只需要激活BLE命令,然后不消耗系统资源(除了蓝牙芯片的电源)

1 个答案:

答案 0 :(得分:0)

这是Android应用程序的常见设计问题 使用永远在线服务的问题在于,如果资源不足,操作系统可以将其终止。如果发生这种情况,您的广播将有效停止 永远在线服务也可能对电池消耗造成损失,具体取决于其中发生的动作。

一个可能但不完美的解决方案是将您的服务作为前台服务 - 这将阻止操作系统停止它,但它会带来惩罚,您必须始终在状态栏中为您的应用设置一个图标,如果您正在使用Lollipop,也可以在锁定屏幕上。

我通过不同的设计解决了这个问题 - 我有一个服务,每X秒唤醒一次,查询它需要的东西(而不是等待广播),处理数据,注册自己在X秒内唤醒并停止。如果这个解决方案适合您,它肯定会解决死机服务问题,并可能解决电池耗尽问题。

在任何情况下,看起来您的服务应该与应用程序分离以保持持久性,也许在操作系统启动时启动它,就像WhatsApp那样