Reputation: 11
Sorry for my bad English.
My main goal is to build a electronic lock, the key would be a phone connected in BLE. The proximity of the phone must unlock the lock.
A application who this connect automatically at a BLE devices when the phone is a proximity. So,the application need run in background. But I am a begin in android/Kotlin. I read the official trainings of google and I was thinking using WorkManager.
doWork()
function of a Worker, I nothing to put that takes CPU time. Just a setup a callback BLE (with BluetoothDevice.connectGatt()
). So, the doWork()
is fast executed.I don't have a problem about the BLE connection. For this, I use BluetoothDevice.connectGatt()
(view doc) with autoConnect
parameter at true. The callback in correctly called when a device is connected or the connection is lost BluetoothGattCallback.onConnectionStateChange()
(view doc)
To try to understand the behavior of WorkManager, I added 1min delay Thread.sleep(60000)
in doWork()
function of a Worker
. And here is what I noticed:
Worker
is running (last minute in my case) and WorkManager.cancelAllWorkByTag()
is called:
onStopped()
of the Worker
is called but the worker continue to run.Worker
is running and the BLE device is connected and the application is closed by de the user:
Worker
is stoppedWorker
is resurrect after a minute and the BLE callback (connection/disconnection) work again, even after end of run of 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
is it the good solution for my problem ?Worker
in background (after close the application), I should replace Thread.sleep(60000)
by something to wait infinite time. It is weird. How to do otherwise ?Thank you for your help.
Upvotes: 1
Views: 548
Reputation: 543
Android and iOS can trigger app functions when the system detects BLE advertisements. Check android library for this: Android Beacon Library
And yes, you don't need to use background services or smth like that 😎
Upvotes: 0