抱歉我的英语不好。
我的主要目标是构建一个电子锁,钥匙是通过 BLE 连接的手机。手机靠近必须解锁。
当手机靠近时,该应用程序会自动连接到 BLE 设备。 因此,应用程序需要在后台运行。但我是 android/Kotlin 的初学者。我看了google的官方培训,正在考虑使用WorkManager。
doWork()
函数中,我没有放置任何需要 CPU 时间的东西。只需设置一个回调 BLE(使用 BluetoothDevice.connectGatt()
)。所以,doWork()
执行得很快。我对 BLE 连接没有任何问题。为此,我使用
BluetoothDevice.connectGatt()
(view doc) 以及 autoConnect
参数为 true。当设备连接或连接丢失时正确调用回调BluetoothGattCallback.onConnectionStateChange()
(查看文档)
为了尝试了解 WorkManager 的行为,我在
Thread.sleep(60000)
的 doWork()
函数中添加了 1 分钟延迟 Worker
。这是我注意到的:
Worker
运行时(在我的例子中是最后一分钟)并且 WorkManager.cancelAllWorkByTag()
被调用:
onStopped()
的Worker
被调用,但worker继续运行。Worker
正在运行且 BLE 设备已连接且用户关闭应用程序时:
Worker
已停止Worker
一分钟后复活,BLE 回调(连接/断开)再次工作,即使在 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)
替换为等待无限时间的东西。真奇怪。否则怎么办?谢谢您的帮助。
Android和iOS可以在系统检测到BLE广告时触发应用程序功能。检查 android 库:Android Beacon Library
是的,您不需要使用后台服务或类似的东西😎