Android BLE后台连接疑问:电子锁场景下WorkManager适配问题
问题求助:基于BLE的电子锁自动解锁应用开发
背景
核心需求是开发一款电子锁,将手机通过BLE连接作为解锁钥匙,实现手机靠近时自动解锁。
需求
需要开发一款能在手机靠近BLE设备时自动连接的应用,该应用需在后台运行。作为Android/Kotlin新手,查阅官方文档后考虑使用WorkManager。
遇到的问题
- 不清楚应用被用户关闭时,BLE与WorkManager的交互表现;
- Worker的
doWork()方法中仅设置BLE回调(通过BluetoothDevice.connectGatt()),无耗时操作,导致该方法执行极快; - 当BLE设备已连接时,若用户关闭应用,设备会自动断开连接。
BLE连接情况
BLE连接本身无问题,使用BluetoothDevice.connectGatt()并将autoConnect参数设为true,BluetoothGattCallback.onConnectionStateChange()回调能正常触发连接或断开事件。
WorkManager表现测试
为了解WorkManager的行为,在Worker的doWork()方法中添加了1分钟延迟Thread.sleep(60000),观察到以下现象:
- 当Worker运行时调用
WorkManager.cancelAllWorkByTag():- Worker的
onStopped()会被调用,但Worker仍继续运行;
- Worker的
- 当Worker运行且BLE设备已连接,用户关闭应用时:
- Worker被停止;
- BLE设备断开连接;
- 一分钟后Worker恢复运行,BLE回调(连接/断开)恢复正常,甚至在Worker运行结束后仍能工作。
未优化的Worker代码
class BleWorker( appContext: Context, workerParams: WorkerParameters ) : Worker(appContext, workerParams) { private val bluetoothManager: BluetoothManager = applicationContext.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager private var bleDevice: BluetoothDevice? = null private var bluetoothGatt: BluetoothGatt? = null private val SERV_UUID = UUID.fromString("44707b20-3459-11ee-aea4-0800200c9a66") private val CHAR_UUID_UNLOCK = UUID.fromString("44707b21-3459-11ee-aea4-0800200c9a66") private val CHAR_UUID_STATE = UUID.fromString("44707b22-3459-11ee-aea4-0800200c9a66") private var service: BluetoothGattService? = null private var charUnlock: BluetoothGattCharacteristic? = null private var charState: BluetoothGattCharacteristic? = null init { Log.i("learnBle","BleWorker ($id:$tags) init" ) } protected fun finalize() { Log.i("learnBle","BleWorker ($id) finalize" ) } override fun onStopped() { Log.i("learnBle","BleWorker ($id) onStopped" ) super.onStopped() } override fun doWork(): Result { var result: Result try { Log.i("learnBle","BleWorker ($id) doWork started" ) bleDevice = bluetoothManager.adapter.bondedDevices.find { it.address == BLE_ADD } if (bleDevice != null) { bluetoothGatt = bleDevice!!.connectGatt( applicationContext, true, gattCallback_auto2) } else { Log.i("learnBle","BleWorker ($id) doWork no device bonded !" ) Result.failure() } Thread.sleep(60000) Log.i("learnBle","BleWorker ($id) doWork ended" ) result = Result.success() } catch (e: Exception) { Log.i("learnBle","BleWorker ($id) doWork ended with FAILURE" ) result = Result.failure() } return result } private val gattCallback_auto2: BluetoothGattCallback = object : BluetoothGattCallback() { override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) { super.onConnectionStateChange(gatt, status, newState) if ( status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothGatt.STATE_CONNECTED) { val ret = gatt!!.discoverServices() Log.i("learnBle","BleWorker:Callback ($id) auto discover services starting:$ret" ) } else { Log.i("learnBle","BleWorker:Callback ($id) auto Connexion failed !" ) } } override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) { super.onServicesDiscovered(gatt, status) // Note: Here gatt == bluetoothGatt val services = gatt?.services service = gatt?.getService(SERV_UUID) charUnlock = service?.getCharacteristic(CHAR_UUID_UNLOCK) charState = service?.getCharacteristic(CHAR_UUID_STATE) // Unlock if (charUnlock != null) { val value = byteArrayOf(0x01) gatt?.writeCharacteristic( charUnlock!!, value, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT) Log.i("learnBle","BleWorker:Callback ($id) unloked !" ) } } } }
求助问题
WorkManager是否适合我的需求场景?- 为了让Worker在应用关闭后仍能在后台运行,我是否需要用无限等待替代
Thread.sleep(60000)?有没有更合理的实现方式? - 如何避免用户关闭应用时BLE设备自动断开连接?
感谢您的帮助!
内容的提问来源于stack exchange,提问作者Antoine163
相关产品推荐
相关产品推荐

