* fix: 优化界面

* fix: 修复已知问题

* fix: 代码优化

* fix: 修复已知问题

* fix: 优化 getMaximumWriteLength 方法

* fix: 修改版本号

* fix: 修改版本号

* fix: 修改 CHANGELOG
This commit is contained in:
iAMD
2023-10-18 17:26:24 +08:00
committed by GitHub
parent 4bec1c9f3a
commit 728402ac16
26 changed files with 872 additions and 413 deletions

View File

@ -351,9 +351,10 @@ interface MyCentralManagerHostApi {
fun stopDiscovery()
fun connect(peripheralHashCodeArgs: Long, callback: (Result<Unit>) -> Unit)
fun disconnect(peripheralHashCodeArgs: Long, callback: (Result<Unit>) -> Unit)
fun getMaximumWriteLength(peripheralHashCodeArgs: Long, callback: (Result<Long>) -> Unit)
fun getMaximumWriteLength(peripheralHashCodeArgs: Long, typeNumberArgs: Long): Long
fun readRSSI(peripheralHashCodeArgs: Long, callback: (Result<Long>) -> Unit)
fun discoverGATT(peripheralHashCodeArgs: Long, callback: (Result<List<MyGattServiceArgs>>) -> Unit)
fun requestMTU(peripheralHashCodeArgs: Long, mtuArgs: Long, callback: (Result<Long>) -> Unit)
fun readCharacteristic(peripheralHashCodeArgs: Long, characteristicHashCodeArgs: Long, callback: (Result<ByteArray>) -> Unit)
fun writeCharacteristic(peripheralHashCodeArgs: Long, characteristicHashCodeArgs: Long, valueArgs: ByteArray, typeNumberArgs: Long, callback: (Result<Unit>) -> Unit)
fun notifyCharacteristic(peripheralHashCodeArgs: Long, characteristicHashCodeArgs: Long, stateArgs: Boolean, callback: (Result<Unit>) -> Unit)
@ -464,15 +465,14 @@ interface MyCentralManagerHostApi {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val peripheralHashCodeArgsArg = args[0].let { if (it is Int) it.toLong() else it as Long }
api.getMaximumWriteLength(peripheralHashCodeArgsArg) { result: Result<Long> ->
val error = result.exceptionOrNull()
if (error != null) {
reply.reply(wrapError(error))
} else {
val data = result.getOrNull()
reply.reply(wrapResult(data))
}
val typeNumberArgsArg = args[1].let { if (it is Int) it.toLong() else it as Long }
var wrapped: List<Any?>
try {
wrapped = listOf<Any?>(api.getMaximumWriteLength(peripheralHashCodeArgsArg, typeNumberArgsArg))
} catch (exception: Throwable) {
wrapped = wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
@ -518,6 +518,27 @@ interface MyCentralManagerHostApi {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.bluetooth_low_energy_android.MyCentralManagerHostApi.requestMTU", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val peripheralHashCodeArgsArg = args[0].let { if (it is Int) it.toLong() else it as Long }
val mtuArgsArg = args[1].let { if (it is Int) it.toLong() else it as Long }
api.requestMTU(peripheralHashCodeArgsArg, mtuArgsArg) { result: Result<Long> ->
val error = result.exceptionOrNull()
if (error != null) {
reply.reply(wrapError(error))
} else {
val data = result.getOrNull()
reply.reply(wrapResult(data))
}
}
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.bluetooth_low_energy_android.MyCentralManagerHostApi.readCharacteristic", codec)
if (api != null) {

View File

@ -15,6 +15,13 @@ class MyBluetoothGattServerCallback(private val peripheralManager: MyPeripheralM
}
}
override fun onConnectionStateChange(device: BluetoothDevice, status: Int, newState: Int) {
super.onConnectionStateChange(device, status, newState)
executor.execute {
peripheralManager.onConnectionStateChange(device, status, newState)
}
}
override fun onMtuChanged(device: BluetoothDevice, mtu: Int) {
super.onMtuChanged(device, mtu)
executor.execute {
@ -36,6 +43,13 @@ class MyBluetoothGattServerCallback(private val peripheralManager: MyPeripheralM
}
}
override fun onExecuteWrite(device: BluetoothDevice, requestId: Int, execute: Boolean) {
super.onExecuteWrite(device, requestId, execute)
executor.execute {
peripheralManager.onExecuteWrite(device, requestId, execute)
}
}
override fun onNotificationSent(device: BluetoothDevice, status: Int) {
super.onNotificationSent(device, status)
executor.execute {

View File

@ -29,6 +29,7 @@ class MyCentralManager(private val context: Context, binaryMessenger: BinaryMess
private val services = mutableMapOf<Long, BluetoothGattService>()
private val characteristics = mutableMapOf<Long, BluetoothGattCharacteristic>()
private val descriptors = mutableMapOf<Long, BluetoothGattDescriptor>()
private val mtus = mutableMapOf<Long, Int>()
private val peripheralsArgs = mutableMapOf<Int, MyPeripheralArgs>()
private val servicesArgsOfPeripherals = mutableMapOf<Long, List<MyGattServiceArgs>>()
@ -43,7 +44,7 @@ class MyCentralManager(private val context: Context, binaryMessenger: BinaryMess
private var startDiscoveryCallback: ((Result<Unit>) -> Unit)? = null
private val connectCallbacks = mutableMapOf<Long, (Result<Unit>) -> Unit>()
private val disconnectCallbacks = mutableMapOf<Long, (Result<Unit>) -> Unit>()
private val getMaximumWriteLengthCallbacks = mutableMapOf<Long, (Result<Long>) -> Unit>()
private val requestMtuCallbacks = mutableMapOf<Long, (Result<Long>) -> Unit>()
private val readRssiCallbacks = mutableMapOf<Long, (Result<Long>) -> Unit>()
private val discoverGattCallbacks = mutableMapOf<Long, (Result<List<MyGattServiceArgs>>) -> Unit>()
private val readCharacteristicCallbacks = mutableMapOf<Long, (Result<ByteArray>) -> Unit>()
@ -89,6 +90,7 @@ class MyCentralManager(private val context: Context, binaryMessenger: BinaryMess
services.clear()
characteristics.clear()
descriptors.clear()
mtus.clear()
peripheralsArgs.clear()
servicesArgsOfPeripherals.clear()
servicesArgs.clear()
@ -98,7 +100,7 @@ class MyCentralManager(private val context: Context, binaryMessenger: BinaryMess
startDiscoveryCallback = null
connectCallbacks.clear()
disconnectCallbacks.clear()
getMaximumWriteLengthCallbacks.clear()
requestMtuCallbacks.clear()
readRssiCallbacks.clear()
discoverGattCallbacks.clear()
readCharacteristicCallbacks.clear()
@ -172,23 +174,33 @@ class MyCentralManager(private val context: Context, binaryMessenger: BinaryMess
}
}
override fun getMaximumWriteLength(peripheralHashCodeArgs: Long, callback: (Result<Long>) -> Unit) {
override fun requestMTU(peripheralHashCodeArgs: Long, mtuArgs: Long, callback: (Result<Long>) -> Unit) {
try {
val unfinishedCallback = getMaximumWriteLengthCallbacks[peripheralHashCodeArgs]
val unfinishedCallback = requestMtuCallbacks[peripheralHashCodeArgs]
if (unfinishedCallback != null) {
throw IllegalStateException()
}
val gatt = bluetoothGATTs[peripheralHashCodeArgs] as BluetoothGatt
val requesting = gatt.requestMtu(517)
val mtu = mtuArgs.toInt()
val requesting = gatt.requestMtu(mtu)
if (!requesting) {
throw IllegalStateException()
}
getMaximumWriteLengthCallbacks[peripheralHashCodeArgs] = callback
requestMtuCallbacks[peripheralHashCodeArgs] = callback
} catch (e: Throwable) {
callback(Result.failure(e))
}
}
override fun getMaximumWriteLength(peripheralHashCodeArgs: Long, typeNumberArgs: Long): Long {
val mtu = mtus[peripheralHashCodeArgs] ?: 23
val maximumWriteLength = when (typeNumberArgs.toWriteTypeArgs()) {
MyGattCharacteristicWriteTypeArgs.WITHRESPONSE -> 512
MyGattCharacteristicWriteTypeArgs.WITHOUTRESPONSE -> (mtu - 3).coerceIn(20, 512)
}
return maximumWriteLength.toLong()
}
override fun readRSSI(peripheralHashCodeArgs: Long, callback: (Result<Long>) -> Unit) {
try {
val unfinishedCallback = readRssiCallbacks[peripheralHashCodeArgs]
@ -414,14 +426,15 @@ class MyCentralManager(private val context: Context, binaryMessenger: BinaryMess
val deviceHashCode = device.hashCode()
val peripheralArgs = peripheralsArgs[deviceHashCode] as MyPeripheralArgs
val peripheralHashCodeArgs = peripheralArgs.hashCodeArgs
// Check callbacks
if (newState != BluetoothProfile.STATE_CONNECTED) {
// check connection state.
if (newState == BluetoothProfile.STATE_DISCONNECTED) {
gatt.close()
bluetoothGATTs.remove(peripheralHashCodeArgs)
mtus.remove(peripheralHashCodeArgs)
val error = IllegalStateException("GATT is disconnected with status: $status")
val getMaximumWriteLengthCallback = getMaximumWriteLengthCallbacks.remove(peripheralHashCodeArgs)
if (getMaximumWriteLengthCallback != null) {
getMaximumWriteLengthCallback(Result.failure(error))
val requestMtuCallback = requestMtuCallbacks.remove(peripheralHashCodeArgs)
if (requestMtuCallback != null) {
requestMtuCallback(Result.failure(error))
}
val readRssiCallback = readRssiCallbacks.remove(peripheralHashCodeArgs)
if (readRssiCallback != null) {
@ -470,35 +483,25 @@ class MyCentralManager(private val context: Context, binaryMessenger: BinaryMess
}
}
}
// Check state
val stateArgs = newState == BluetoothProfile.STATE_CONNECTED
api.onPeripheralStateChanged(peripheralArgs, stateArgs) {}
// check connect & disconnect callbacks.
val connectCallback = connectCallbacks.remove(peripheralHashCodeArgs)
val disconnectCallback = disconnectCallbacks.remove(peripheralHashCodeArgs)
if (connectCallback == null && disconnectCallback == null) {
// State changed.
val stateArgs = newState == BluetoothProfile.STATE_CONNECTED
api.onPeripheralStateChanged(peripheralArgs, stateArgs) {}
} else {
if (connectCallback != null) {
if (status == BluetoothGatt.GATT_SUCCESS) {
// Connect succeed.
connectCallback(Result.success(Unit))
api.onPeripheralStateChanged(peripheralArgs, true) {}
} else {
// Connect failed.
val error = IllegalStateException("Connect failed with status: $status")
connectCallback(Result.failure(error))
}
if (connectCallback != null) {
if (status == BluetoothGatt.GATT_SUCCESS) {
connectCallback(Result.success(Unit))
} else {
val error = IllegalStateException("Connect failed with status: $status")
connectCallback(Result.failure(error))
}
if (disconnectCallback != null) {
if (status == BluetoothGatt.GATT_SUCCESS) {
// Disconnect succeed.
disconnectCallback(Result.success(Unit))
api.onPeripheralStateChanged(peripheralArgs, false) {}
} else {
// Disconnect failed.
val error = IllegalStateException("Connect failed with status: $status")
disconnectCallback(Result.failure(error))
}
}
if (disconnectCallback != null) {
if (status == BluetoothGatt.GATT_SUCCESS) {
disconnectCallback(Result.success(Unit))
} else {
val error = IllegalStateException("Disconnect failed with status: $status")
disconnectCallback(Result.failure(error))
}
}
}
@ -508,12 +511,15 @@ class MyCentralManager(private val context: Context, binaryMessenger: BinaryMess
val hashCode = device.hashCode()
val peripheralArgs = peripheralsArgs[hashCode] as MyPeripheralArgs
val peripheralHashCodeArgs = peripheralArgs.hashCodeArgs
val callback = getMaximumWriteLengthCallbacks.remove(peripheralHashCodeArgs) ?: return
if (status == BluetoothGatt.GATT_SUCCESS) {
val maximumWriteLengthArgs = (mtu - 3).toLong()
callback(Result.success(maximumWriteLengthArgs))
mtus[peripheralHashCodeArgs] = mtu
}
val callback = requestMtuCallbacks.remove(peripheralHashCodeArgs) ?: return
if (status == BluetoothGatt.GATT_SUCCESS) {
val mtuArgs = mtu.toLong()
callback(Result.success(mtuArgs))
} else {
val error = IllegalStateException("Get maximum write length failed with status: $status")
val error = IllegalStateException("Request MTU failed with status: $status")
callback(Result.failure(error))
}
}

View File

@ -29,6 +29,9 @@ class MyPeripheralManager(private val context: Context, binaryMessenger: BinaryM
private val descriptors = mutableMapOf<Long, BluetoothGattDescriptor>()
private val mtus = mutableMapOf<Long, Int>()
private val confirms = mutableMapOf<Long, Boolean>()
private val preparedCharacteristics = mutableMapOf<Int, BluetoothGattCharacteristic>()
private val preparedValues = mutableMapOf<Int, ByteArray>()
private val values = mutableMapOf<Long, ByteArray>()
private val centralsArgs = mutableMapOf<Int, MyCentralArgs>()
private val servicesArgs = mutableMapOf<Int, MyGattServiceArgs>()
@ -81,6 +84,9 @@ class MyPeripheralManager(private val context: Context, binaryMessenger: BinaryM
descriptors.clear()
mtus.clear()
confirms.clear()
preparedCharacteristics.clear()
preparedValues.clear()
values.clear()
centralsArgs.clear()
servicesArgs.clear()
characteristicsArgs.clear()
@ -218,7 +224,8 @@ class MyPeripheralManager(private val context: Context, binaryMessenger: BinaryM
override fun getMaximumWriteLength(centralHashCodeArgs: Long): Long {
val mtu = mtus[centralHashCodeArgs] ?: 23
return (mtu - 3).toLong()
val maximumWriteLength = (mtu - 3).coerceIn(20, 512)
return maximumWriteLength.toLong()
}
override fun sendReadCharacteristicReply(centralHashCodeArgs: Long, characteristicHashCodeArgs: Long, idArgs: Long, offsetArgs: Long, statusArgs: Boolean, valueArgs: ByteArray) {
@ -239,7 +246,7 @@ class MyPeripheralManager(private val context: Context, binaryMessenger: BinaryM
val status = if (statusArgs) BluetoothGatt.GATT_SUCCESS
else BluetoothGatt.GATT_FAILURE
val offset = offsetArgs.toInt()
val value = null
val value = values.remove(idArgs) as ByteArray
val sent = server.sendResponse(device, requestId, status, offset, value)
if (!sent) {
throw IllegalStateException("Send write characteristic reply failed.")
@ -335,6 +342,13 @@ class MyPeripheralManager(private val context: Context, binaryMessenger: BinaryM
callback(Result.failure(error))
}
fun onConnectionStateChange(device: BluetoothDevice, status: Int, newState: Int) {
val hashCode = device.hashCode()
val centralArgs = centralsArgs.getOrPut(hashCode) { device.toCentralArgs() }
val centralHashCodeArgs = centralArgs.hashCodeArgs
devices[centralHashCodeArgs] = device
}
fun onMtuChanged(device: BluetoothDevice, mtu: Int) {
val hashCode = device.hashCode()
val centralArgs = centralsArgs.getOrPut(hashCode) { device.toCentralArgs() }
@ -360,11 +374,49 @@ class MyPeripheralManager(private val context: Context, binaryMessenger: BinaryM
val centralArgs = centralsArgs.getOrPut(deviceHashCode) { device.toCentralArgs() }
val centralHashCodeArgs = centralArgs.hashCodeArgs
devices[centralHashCodeArgs] = device
if (preparedWrite) {
val preparedCharacteristic = preparedCharacteristics[deviceHashCode]
if (preparedCharacteristic != null && preparedCharacteristic != characteristic) {
val status = BluetoothGatt.GATT_CONNECTION_CONGESTED
server.sendResponse(device, requestId, status, offset, value)
return
}
val preparedValue = preparedValues[deviceHashCode]
if (preparedValue == null) {
preparedCharacteristics[deviceHashCode] = characteristic
preparedValues[deviceHashCode] = value
} else {
preparedValues[deviceHashCode] = preparedValue.plus(value)
}
val status = BluetoothGatt.GATT_SUCCESS
server.sendResponse(device, requestId, status, offset, value)
} else {
val characteristicHashCode = characteristic.hashCode()
val characteristicArgs = characteristicsArgs[characteristicHashCode] as MyGattCharacteristicArgs
val idArgs = requestId.toLong()
val offsetArgs = offset.toLong()
values[idArgs] = value
api.onWriteCharacteristicCommandReceived(centralArgs, characteristicArgs, idArgs, offsetArgs, value) {}
}
}
fun onExecuteWrite(device: BluetoothDevice, requestId: Int, execute: Boolean) {
val deviceHashCode = device.hashCode()
val centralArgs = centralsArgs[deviceHashCode] as MyCentralArgs
val characteristic = preparedCharacteristics.remove(deviceHashCode) as BluetoothGattCharacteristic
val characteristicHashCode = characteristic.hashCode()
val characteristicArgs = characteristicsArgs[characteristicHashCode] as MyGattCharacteristicArgs
val idArgs = requestId.toLong()
val offsetArgs = offset.toLong()
api.onWriteCharacteristicCommandReceived(centralArgs, characteristicArgs, idArgs, offsetArgs, value) {}
val value = preparedValues.remove(deviceHashCode) as ByteArray
if (execute) {
val idArgs = requestId.toLong()
val offsetArgs = 0L
values[idArgs] = value
api.onWriteCharacteristicCommandReceived(centralArgs, characteristicArgs, idArgs, offsetArgs, value) {}
} else {
val status = BluetoothGatt.GATT_SUCCESS
val offset = 0
server.sendResponse(device, requestId, status, offset, value)
}
}
fun onDescriptorReadRequest(device: BluetoothDevice, requestId: Int, offset: Int, descriptor: BluetoothGattDescriptor) {