gpt4 book ai didi

android - 前台服务重启后多次接收BluetoothGattCallback

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:10:17 25 4
gpt4 key购买 nike

我正在使用支持 BLE 的硬件并使用 Android 的前台服务与硬件通信。前台服务负责处理 BLE 相关事件,它在一段时间内根据要求工作得很好,但不知何故,如果前台服务被杀死或 BLE 连接由于任何原因断开,则应用程序会尝试再次重新连接到 BLE,然后BLE 回调开始从 BluetoothGattCallback 获取重复事件,即使硬件向蓝牙发送单个事件但 Android BluetoothGattCallback 收到多个相同的回调,这会导致我们的实现出现很多错误。

供引用,请按如下方式查看日志,

Following are methods and callbacks from my foreground service,

BLEManagerService: *****onDescriptorWrite: 0*****<br>
BLEManagerService: *****onDescriptorWrite: 0*****<br>
BLEManagerService: *****onDescriptorWrite: 0*****<br>
BLEManagerService: Firmware: onCharacteristicRead true<br>
BLEManagerService: *****onDescriptorWrite: 0*****<br>
BLEManagerService: Firmware: onCharacteristicRead true<br>
BLEManagerService: *****onCharacteristicRead: 0*****<br>
BLEManagerService: *****onCharacteristicRead: 0*****<br>

override fun onCreate() {
super.onCreate()

mBluetoothGatt?.let { refreshDeviceCache(it) }

registerReceiver(btStateBroadcastReceiver, IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED))
}

/**
* Start BLE scan
*/
private fun scanLeDevice(enable: Boolean) {
if (enable && bleConnectionState == DISCONNECTED) {
//initialize scanning BLE
startScan()
scanTimer = scanTimer()
} else {
stopScan("scanLeDevice: (Enable: $enable)")
}
}

private fun scanTimer(): CountDownTimer {
return object : CountDownTimer(SCAN_PERIOD, 1000) {
override fun onTick(millisUntilFinished: Long) {
//Nothing to do

}

override fun onFinish() {
if (SCAN_PERIOD > 10000 && bleConnectionState == DISCONNECTED) {
stopScan("restart scanTimer")
Thread.sleep(200)
scanLeDevice(true)
SCAN_PERIOD -= 5000
if (null != scanTimer) {
scanTimer!!.cancel()
scanTimer = null
}
scanTimer = scanTimer()
} else {
stopScan("stop scanTimer")
SCAN_PERIOD = 60000
}
}
}
}


//Scan callbacks for more that LOLLIPOP versions
private val mScanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult) {
val btDevice = result.device
if (null != btDevice) {
val scannedDeviceName: String? = btDevice.name

scannedDeviceName?.let {
if (it == mBluetoothFemurDeviceName) {
stopScan("ScanCallback: Found device")
//Disconnect from current connection if any
mBluetoothGatt?.let {it1 ->
it1.close()
mBluetoothGatt = null
}
connectToDevice(btDevice)
}
}
}
}

override fun onBatchScanResults(results: List<ScanResult>) {
//Not Required
}

override fun onScanFailed(errorCode: Int) {
Log.e(TAG, "*****onScanFailed->Error Code: $errorCode*****")
}
}

/**
* Connect to BLE device
* @param device
*/
fun connectToDevice(device: BluetoothDevice) {
scanLeDevice(false)// will stop after first device detection

//Stop Scanning before connect attempt
try {
if (null != scanTimer) {
scanTimer!!.cancel()
}
} catch (e: Exception) {
//Just handle exception if something
// goes wrong while canceling the scan timer
}
//Stop scan if still BLE scanner is running
stopScan("connectToDevice")
if (mBluetoothGatt == null) {
connectedDevice = device
if (Build.VERSION.SDK_INT >= 26)
connectedDevice?.connectGatt(this, false, mGattCallback)
}else{
disconnectDevice()
connectedDevice = device
connectedDevice?.connectGatt(this, false, mGattCallback)
}
}

/**
* Disconnect from BLE device
*/
private fun disconnectDevice() {
mBluetoothGatt?.close()
mBluetoothGatt = null

bleConnectionState = DISCONNECTED
mBluetoothManager = null
mBluetoothAdapter = null
mBluetoothFemurDeviceName = null
mBluetoothTibiaDeviceName = null
connectedDevice = null
}

/****************************************
* BLE Related Callbacks starts *
* Implements callback methods for GATT *
****************************************/
// Implements callback methods for GATT events that the app cares about. For example,
// connection change and services discovered.
private val mGattCallback = object : BluetoothGattCallback() {

/**
* Connection state changed callback
*/
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
mBluetoothGatt = gatt
//Stop Scanning before connect attempt
try {
if (null != scanTimer) {
scanTimer!!.cancel()
}
} catch (e: Exception) {
//Just handle exception if something
// goes wrong while canceling the scan timer
}
stopScan("onConnectionStateChange")// will stop after first device detection

} else if (newState == BluetoothProfile.STATE_DISCONNECTED || status == 8) {

disconnectDevice()
Handler(Looper.getMainLooper()).postDelayed({
initialize()
}, 500)

}
}

/**
* On services discovered
* @param gatt
* @param status
*/
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
super.onServicesDiscovered(gatt, status)

}

override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
super.onDescriptorWrite(gatt, descriptor, status)

}

/**
* On characteristic read operation complete
* @param gatt
* @param characteristic
* @param status
*/
override fun onCharacteristicRead(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
super.onCharacteristicRead(gatt, characteristic, status)

}

/**
* On characteristic write operation complete
* @param gatt
* @param characteristic
* @param status
*/
override fun onCharacteristicWrite(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
super.onCharacteristicWrite(gatt, characteristic, status)
val data = characteristic.value
val dataHex = byteToHexStringJava(data)
}

/**
* On Notification/Data received from the characteristic
* @param gatt
* @param characteristic
*/
override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
super.onCharacteristicChanged(gatt, characteristic)
val data = characteristic.value
val dataHex = byteToHexStringJava(data)


}

override fun onReadRemoteRssi(gatt: BluetoothGatt, rssi: Int, status: Int) {
super.onReadRemoteRssi(gatt, rssi, status)
val b = Bundle()
b.putInt(BT_RSSI_VALUE_READ, rssi)
receiver?.send(APP_RESULT_CODE_BT_RSSI, b)
}
}


/**
* Bluetooth state receiver to handle the ON/OFF states
*/
private val btStateBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1)

when (state) {

BluetoothAdapter.STATE_OFF -> {
//STATE OFF
}

BluetoothAdapter.STATE_ON -> {
//STATE ON
btState = BT_ON
val b = Bundle()
receiver?.send(APP_RESULT_CODE_BT_ON, b)
initialize()
}

BluetoothAdapter.STATE_TURNING_OFF -> {
//Not Required

}

BluetoothAdapter.STATE_TURNING_ON -> {
//Not Required

}
}
}
}

private fun handleBleDisconnectedState() {
mBluetoothGatt?.let {
it.close()

receiver?.send(DISCONNECTED, b)
Handler(Looper.getMainLooper()).postDelayed({
mBluetoothManager = null
mBluetoothAdapter = null
mBluetoothFemurDeviceName = null
mBluetoothTibiaDeviceName = null

mBluetoothGatt = null
}, 1000)
}
}


/****************************************
* BLE Related Callbacks End ***
****************************************/

/****************************************************
* Register Receivers to handle calbacks to UI ***
****************************************************/

override fun onDestroy() {
super.onDestroy()

try {
mBluetoothGatt?.let {
it.close()
mBluetoothGatt = null
}
unregisterReceivers()
scanTimer?.cancel()

} catch (e: Exception) {
e.printStackTrace()
}
}

override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
Log.e(TAG, "onTaskRemoved")
stopSelf()
}

/**
* Unregister the receivers before destroying the service
*/
private fun unregisterReceivers() {
unregisterReceiver(btStateBroadcastReceiver)
}

companion object {
private val TAG = BLEManagerService::class.java.simpleName
private var mBluetoothGatt: BluetoothGatt? = null
var bleConnectionState: Int = DISCONNECTED
}

最佳答案

不要在 onConnectionStateChange 中设置 mBluetoothGatt = gatt。而是从 connectGatt 的返回值中设置它。否则,您可能会创建多个 BluetoothGatt 对象而不关闭之前的对象,从而获得多个回调。

关于android - 前台服务重启后多次接收BluetoothGattCallback,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56642287/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com