修复 setUp 和 clearServices 错误 (#39)

This commit is contained in:
iAMD
2024-01-17 17:58:22 +08:00
committed by GitHub
parent 6f0bc77ac9
commit 5b308f044b
14 changed files with 205 additions and 126 deletions

View File

@ -1,10 +1,15 @@
## 5.0.3
* `Android` Fix the wrong blutooth low energy state caused by multi permission requests at the same time.
* `Android` Fix the ConcurrentModificationException when `PeripheralManager#clearServices` is called.
## 5.0.2 ## 5.0.2
* Fix the issue that [discoverGATT failed caused by CoW](https://github.com/yanshouwang/bluetooth_low_energy/issues/36). * `iOS` Fix the issue that [discoverGATT failed](https://github.com/yanshouwang/bluetooth_low_energy/issues/36) caused by CoW.
## 5.0.1 ## 5.0.1
* Fix the issue that [completion was called duplicately caused by CoW](https://github.com/yanshouwang/bluetooth_low_energy/issues/36). * `iOS` Fix the issue that [completion was called duplicately](https://github.com/yanshouwang/bluetooth_low_energy/issues/36) caused by CoW.
## 5.0.0 ## 5.0.0

View File

@ -23,15 +23,15 @@ packages:
path: ".." path: ".."
relative: true relative: true
source: path source: path
version: "5.0.2" version: "5.0.3"
bluetooth_low_energy_android: bluetooth_low_energy_android:
dependency: transitive dependency: transitive
description: description:
name: bluetooth_low_energy_android name: bluetooth_low_energy_android
sha256: "502382b2bc6d0bf9e7aa635bafa28057cb8538d6f2dd9c2eceb6d0111bcee94a" sha256: "703faeeecce61887af4fa34bce5e0f5c25019d585f2e05723948332512c4eedc"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.0" version: "5.0.2"
bluetooth_low_energy_darwin: bluetooth_low_energy_darwin:
dependency: transitive dependency: transitive
description: description:

View File

@ -1,6 +1,6 @@
name: bluetooth_low_energy name: bluetooth_low_energy
description: A Flutter plugin for controlling the bluetooth low energy, supports central and peripheral apis. description: A Flutter plugin for controlling the bluetooth low energy, supports central and peripheral apis.
version: 5.0.2 version: 5.0.3
homepage: https://github.com/yanshouwang/bluetooth_low_energy homepage: https://github.com/yanshouwang/bluetooth_low_energy
environment: environment:
@ -11,7 +11,7 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
bluetooth_low_energy_platform_interface: ^5.0.0 bluetooth_low_energy_platform_interface: ^5.0.0
bluetooth_low_energy_android: ^5.0.0 bluetooth_low_energy_android: ^5.0.2
bluetooth_low_energy_darwin: ^5.0.2 bluetooth_low_energy_darwin: ^5.0.2
bluetooth_low_energy_windows: ^5.0.0 bluetooth_low_energy_windows: ^5.0.0
bluetooth_low_energy_linux: ^5.0.0 bluetooth_low_energy_linux: ^5.0.0

View File

@ -1,3 +1,12 @@
## 5.0.2
* Fix the ConcurrentModificationException when `PeripheralManager#clearServices` is called.
* Fix the `CentralManager#setUp` and `PeripheralManager#setUp` were blocked.
## 5.0.1
* Fix the wrong blutooth low energy state caused by multi permission requests at the same time.
## 5.0.0 ## 5.0.0
* Now `CentralManager#writeCharacteristic` and `PeripheralManager#writeCharacteristic` will fragment the value automatically, the maximum write length is 512 bytes. * Now `CentralManager#writeCharacteristic` and `PeripheralManager#writeCharacteristic` will fragment the value automatically, the maximum write length is 512 bytes.

View File

@ -50,8 +50,10 @@ enum class MyBluetoothLowEnergyStateArgs(val raw: Int) {
UNKNOWN(0), UNKNOWN(0),
UNSUPPORTED(1), UNSUPPORTED(1),
UNAUTHORIZED(2), UNAUTHORIZED(2),
POWEREDOFF(3), OFF(3),
POWEREDON(4); TURNINGON(4),
ON(5),
TURNINGOFF(6);
companion object { companion object {
fun ofRaw(raw: Int): MyBluetoothLowEnergyStateArgs? { fun ofRaw(raw: Int): MyBluetoothLowEnergyStateArgs? {
@ -327,7 +329,7 @@ private object MyCentralManagerHostApiCodec : StandardMessageCodec() {
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
interface MyCentralManagerHostApi { interface MyCentralManagerHostApi {
fun setUp() fun setUp(callback: (Result<Unit>) -> Unit)
fun startDiscovery(callback: (Result<Unit>) -> Unit) fun startDiscovery(callback: (Result<Unit>) -> Unit)
fun stopDiscovery() fun stopDiscovery()
fun connect(addressArgs: String, callback: (Result<Unit>) -> Unit) fun connect(addressArgs: String, callback: (Result<Unit>) -> Unit)
@ -353,14 +355,14 @@ interface MyCentralManagerHostApi {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.bluetooth_low_energy_android.MyCentralManagerHostApi.setUp", codec) val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.bluetooth_low_energy_android.MyCentralManagerHostApi.setUp", codec)
if (api != null) { if (api != null) {
channel.setMessageHandler { _, reply -> channel.setMessageHandler { _, reply ->
var wrapped: List<Any?> api.setUp() { result: Result<Unit> ->
try { val error = result.exceptionOrNull()
api.setUp() if (error != null) {
wrapped = listOf<Any?>(null) reply.reply(wrapError(error))
} catch (exception: Throwable) { } else {
wrapped = wrapError(exception) reply.reply(wrapResult(null))
}
} }
reply.reply(wrapped)
} }
} else { } else {
channel.setMessageHandler(null) channel.setMessageHandler(null)
@ -795,7 +797,7 @@ private object MyPeripheralManagerHostApiCodec : StandardMessageCodec() {
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
interface MyPeripheralManagerHostApi { interface MyPeripheralManagerHostApi {
fun setUp() fun setUp(callback: (Result<Unit>) -> Unit)
fun addService(serviceArgs: MyGattServiceArgs, callback: (Result<Unit>) -> Unit) fun addService(serviceArgs: MyGattServiceArgs, callback: (Result<Unit>) -> Unit)
fun removeService(hashCodeArgs: Long) fun removeService(hashCodeArgs: Long)
fun clearServices() fun clearServices()
@ -816,14 +818,14 @@ interface MyPeripheralManagerHostApi {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.bluetooth_low_energy_android.MyPeripheralManagerHostApi.setUp", codec) val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.bluetooth_low_energy_android.MyPeripheralManagerHostApi.setUp", codec)
if (api != null) { if (api != null) {
channel.setMessageHandler { _, reply -> channel.setMessageHandler { _, reply ->
var wrapped: List<Any?> api.setUp() { result: Result<Unit> ->
try { val error = result.exceptionOrNull()
api.setUp() if (error != null) {
wrapped = listOf<Any?>(null) reply.reply(wrapError(error))
} catch (exception: Throwable) { } else {
wrapped = wrapError(exception) reply.reply(wrapResult(null))
}
} }
reply.reply(wrapped)
} }
} else { } else {
channel.setMessageHandler(null) channel.setMessageHandler(null)

View File

@ -131,8 +131,11 @@ fun MyGattServiceArgs.toService(): BluetoothGattService {
//region ToArgs //region ToArgs
fun Int.toBluetoothLowEnergyStateArgs(): MyBluetoothLowEnergyStateArgs { fun Int.toBluetoothLowEnergyStateArgs(): MyBluetoothLowEnergyStateArgs {
return when (this) { return when (this) {
BluetoothAdapter.STATE_ON -> MyBluetoothLowEnergyStateArgs.POWEREDON BluetoothAdapter.STATE_OFF -> MyBluetoothLowEnergyStateArgs.OFF
else -> MyBluetoothLowEnergyStateArgs.POWEREDOFF BluetoothAdapter.STATE_TURNING_ON -> MyBluetoothLowEnergyStateArgs.TURNINGON
BluetoothAdapter.STATE_ON -> MyBluetoothLowEnergyStateArgs.ON
BluetoothAdapter.STATE_TURNING_OFF -> MyBluetoothLowEnergyStateArgs.TURNINGOFF
else -> MyBluetoothLowEnergyStateArgs.UNKNOWN
} }
} }

View File

@ -14,8 +14,6 @@ import io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener
import java.util.UUID import java.util.UUID
import java.util.concurrent.Executor import java.util.concurrent.Executor
typealias MyBluetoothLowEnergyState = MyBluetoothLowEnergyStateArgs
abstract class MyBluetoothLowEnergyManager(context: Context) { abstract class MyBluetoothLowEnergyManager(context: Context) {
companion object { companion object {
val CLIENT_CHARACTERISTIC_CONFIG_UUID = val CLIENT_CHARACTERISTIC_CONFIG_UUID =
@ -40,33 +38,26 @@ abstract class MyBluetoothLowEnergyManager(context: Context) {
} }
protected val executor get() = ContextCompat.getMainExecutor(mContext) as Executor protected val executor get() = ContextCompat.getMainExecutor(mContext) as Executor
protected val hasFeature get() = mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
protected val manager protected val manager
get() = ContextCompat.getSystemService( get() = ContextCompat.getSystemService(
mContext, BluetoothManager::class.java mContext, BluetoothManager::class.java
) as BluetoothManager ) as BluetoothManager
protected val adapter get() = manager.adapter as BluetoothAdapter protected val adapter get() = manager.adapter as BluetoothAdapter
protected fun initialize() { protected fun checkPermissions(): Boolean {
val hasFeature = return permissions.all { permission ->
mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE) ActivityCompat.checkSelfPermission(
if (hasFeature) { mContext, permission
val authorized = permissions.all { permission -> ) == PackageManager.PERMISSION_GRANTED
ActivityCompat.checkSelfPermission(
mContext, permission
) == PackageManager.PERMISSION_GRANTED
}
if (authorized) {
mOnAuthorizationStateChanged(true)
} else {
val activity = mBinding.activity
ActivityCompat.requestPermissions(activity, permissions, requestCode)
}
} else {
val state = MyBluetoothLowEnergyState.UNSUPPORTED
onStateChanged(state)
} }
} }
protected fun requestPermissions() {
val activity = mBinding.activity
ActivityCompat.requestPermissions(activity, permissions, requestCode)
}
fun onAttachedToActivity(binding: ActivityPluginBinding) { fun onAttachedToActivity(binding: ActivityPluginBinding) {
binding.addRequestPermissionsResultListener(mRequestPermissionsResultListener) binding.addRequestPermissionsResultListener(mRequestPermissionsResultListener)
mBinding = binding mBinding = binding
@ -82,8 +73,9 @@ abstract class MyBluetoothLowEnergyManager(context: Context) {
if (this.requestCode != requestCode) { if (this.requestCode != requestCode) {
return false return false
} }
val authorized = results.all { r -> r == PackageManager.PERMISSION_GRANTED } val granted =
mOnAuthorizationStateChanged(authorized) permissions.contentEquals(this.permissions) && results.all { r -> r == PackageManager.PERMISSION_GRANTED }
onPermissionsRequested(granted)
return true return true
} }
@ -92,23 +84,11 @@ abstract class MyBluetoothLowEnergyManager(context: Context) {
if (action != BluetoothAdapter.ACTION_STATE_CHANGED) { if (action != BluetoothAdapter.ACTION_STATE_CHANGED) {
return return
} }
val extra = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF) val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF)
val state = extra.toBluetoothLowEnergyStateArgs() onAdapterStateChanged(state)
onStateChanged(state)
} }
private fun mOnAuthorizationStateChanged(authorized: Boolean) { protected fun registerReceiver() {
val state = if (authorized) {
mRegisterReceiver()
if (adapter.state == BluetoothAdapter.STATE_ON) MyBluetoothLowEnergyState.POWEREDON
else MyBluetoothLowEnergyState.POWEREDOFF
} else {
MyBluetoothLowEnergyState.UNAUTHORIZED
}
onStateChanged(state)
}
private fun mRegisterReceiver() {
if (mRegistered) { if (mRegistered) {
return return
} }
@ -119,6 +99,8 @@ abstract class MyBluetoothLowEnergyManager(context: Context) {
abstract val permissions: Array<String> abstract val permissions: Array<String>
abstract val requestCode: Int abstract val requestCode: Int
abstract fun onStateChanged(state: MyBluetoothLowEnergyState)
abstract fun onPermissionsRequested(granted: Boolean)
abstract fun onAdapterStateChanged(state: Int)
} }

View File

@ -39,6 +39,7 @@ class MyCentralManager(context: Context, binaryMessenger: BinaryMessenger) :
private val mCharacteristics: MutableMap<String, Map<Long, BluetoothGattCharacteristic>> private val mCharacteristics: MutableMap<String, Map<Long, BluetoothGattCharacteristic>>
private val mDescriptors: MutableMap<String, Map<Long, BluetoothGattDescriptor>> private val mDescriptors: MutableMap<String, Map<Long, BluetoothGattDescriptor>>
private var mSetUpCallback: ((Result<Unit>) -> Unit)?
private var mStartDiscoveryCallback: ((Result<Unit>) -> Unit)? private var mStartDiscoveryCallback: ((Result<Unit>) -> Unit)?
private val mConnectCallbacks: MutableMap<String, (Result<Unit>) -> Unit> private val mConnectCallbacks: MutableMap<String, (Result<Unit>) -> Unit>
private val mDisconnectCallbacks: MutableMap<String, (Result<Unit>) -> Unit> private val mDisconnectCallbacks: MutableMap<String, (Result<Unit>) -> Unit>
@ -61,6 +62,7 @@ class MyCentralManager(context: Context, binaryMessenger: BinaryMessenger) :
mCharacteristics = mutableMapOf() mCharacteristics = mutableMapOf()
mDescriptors = mutableMapOf() mDescriptors = mutableMapOf()
mSetUpCallback = null
mStartDiscoveryCallback = null mStartDiscoveryCallback = null
mConnectCallbacks = mutableMapOf() mConnectCallbacks = mutableMapOf()
mDisconnectCallbacks = mutableMapOf() mDisconnectCallbacks = mutableMapOf()
@ -93,9 +95,25 @@ class MyCentralManager(context: Context, binaryMessenger: BinaryMessenger) :
override val requestCode: Int override val requestCode: Int
get() = REQUEST_CODE get() = REQUEST_CODE
override fun setUp() { override fun setUp(callback: (Result<Unit>) -> Unit) {
mClearState() try {
initialize() mClearState()
val stateArgs = if (hasFeature) {
val granted = checkPermissions()
if (granted) {
registerReceiver()
adapter.state.toBluetoothLowEnergyStateArgs()
} else {
requestPermissions()
mSetUpCallback = callback
return
}
} else MyBluetoothLowEnergyStateArgs.UNSUPPORTED
mOnStateChanged(stateArgs)
callback(Result.success(Unit))
} catch (e: Throwable) {
callback(Result.failure(e))
}
} }
override fun startDiscovery(callback: (Result<Unit>) -> Unit) { override fun startDiscovery(callback: (Result<Unit>) -> Unit) {
@ -104,10 +122,10 @@ class MyCentralManager(context: Context, binaryMessenger: BinaryMessenger) :
val settings = val settings =
ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build() ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build()
mScanner.startScan(filters, settings, mScanCallback) mScanner.startScan(filters, settings, mScanCallback)
mStartDiscoveryCallback = callback
executor.execute { executor.execute {
onScanSucceed() onScanSucceed()
} }
mStartDiscoveryCallback = callback
} catch (e: Throwable) { } catch (e: Throwable) {
callback(Result.failure(e)) callback(Result.failure(e))
} }
@ -319,9 +337,19 @@ class MyCentralManager(context: Context, binaryMessenger: BinaryMessenger) :
} }
} }
override fun onStateChanged(state: MyBluetoothLowEnergyState) { override fun onPermissionsRequested(granted: Boolean) {
val stateNumberArgs = state.raw.toLong() val callback = mSetUpCallback ?: return
mApi.onStateChanged(stateNumberArgs) {} val stateArgs = if (granted) {
registerReceiver()
adapter.state.toBluetoothLowEnergyStateArgs()
} else MyBluetoothLowEnergyStateArgs.UNAUTHORIZED
mOnStateChanged(stateArgs)
callback(Result.success(Unit))
}
override fun onAdapterStateChanged(state: Int) {
val stateArgs = state.toBluetoothLowEnergyStateArgs()
mOnStateChanged(stateArgs)
} }
private fun onScanSucceed() { private fun onScanSucceed() {
@ -554,6 +582,7 @@ class MyCentralManager(context: Context, binaryMessenger: BinaryMessenger) :
mCharacteristics.clear() mCharacteristics.clear()
mDescriptors.clear() mDescriptors.clear()
mSetUpCallback = null
mStartDiscoveryCallback = null mStartDiscoveryCallback = null
mConnectCallbacks.clear() mConnectCallbacks.clear()
mDisconnectCallbacks.clear() mDisconnectCallbacks.clear()
@ -566,6 +595,11 @@ class MyCentralManager(context: Context, binaryMessenger: BinaryMessenger) :
mWriteDescriptorCallbacks.clear() mWriteDescriptorCallbacks.clear()
} }
private fun mOnStateChanged(stateArgs: MyBluetoothLowEnergyStateArgs) {
val stateNumberArgs = stateArgs.raw.toLong()
mApi.onStateChanged(stateNumberArgs) {}
}
private fun mRetrieveCharacteristic( private fun mRetrieveCharacteristic(
addressArgs: String, hashCodeArgs: Long addressArgs: String, hashCodeArgs: Long
): BluetoothGattCharacteristic? { ): BluetoothGattCharacteristic? {

View File

@ -19,7 +19,7 @@ import io.flutter.plugin.common.BinaryMessenger
class MyPeripheralManager(context: Context, binaryMessenger: BinaryMessenger) : class MyPeripheralManager(context: Context, binaryMessenger: BinaryMessenger) :
MyBluetoothLowEnergyManager(context), MyPeripheralManagerHostApi { MyBluetoothLowEnergyManager(context), MyPeripheralManagerHostApi {
companion object { companion object {
const val REQUEST_CODE = 444 const val REQUEST_CODE = 445
} }
private val advertiser get() = adapter.bluetoothLeAdvertiser private val advertiser get() = adapter.bluetoothLeAdvertiser
@ -89,9 +89,25 @@ class MyPeripheralManager(context: Context, binaryMessenger: BinaryMessenger) :
override val requestCode: Int override val requestCode: Int
get() = REQUEST_CODE get() = REQUEST_CODE
override fun setUp() { override fun setUp(callback: (Result<Unit>) -> Unit) {
mClearState() try {
initialize() mClearState()
val stateArgs = if (hasFeature) {
val granted = checkPermissions()
if (granted) {
registerReceiver()
adapter.state.toBluetoothLowEnergyStateArgs()
} else {
requestPermissions()
mSetUpCallback = callback
return
}
} else MyBluetoothLowEnergyStateArgs.UNSUPPORTED
mOnStateChanged(stateArgs)
callback(Result.success(Unit))
} catch (e: Throwable) {
callback(Result.failure(e))
}
} }
override fun addService(serviceArgs: MyGattServiceArgs, callback: (Result<Unit>) -> Unit) { override fun addService(serviceArgs: MyGattServiceArgs, callback: (Result<Unit>) -> Unit) {
@ -143,28 +159,45 @@ class MyPeripheralManager(context: Context, binaryMessenger: BinaryMessenger) :
} }
mAddServiceCallback = callback mAddServiceCallback = callback
} catch (e: Throwable) { } catch (e: Throwable) {
mClearService(serviceArgs)
callback(Result.failure(e)) callback(Result.failure(e))
} }
} }
override fun removeService(hashCodeArgs: Long) { override fun removeService(hashCodeArgs: Long) {
val service = mServices[hashCodeArgs] as BluetoothGattService val service = mServices.remove(hashCodeArgs) as BluetoothGattService
val hashCode = service.hashCode()
val serviceArgs = mServicesArgs[hashCode] as MyGattServiceArgs
val removed = mServer.removeService(service) val removed = mServer.removeService(service)
if (!removed) { if (!removed) {
throw IllegalStateException() throw IllegalStateException()
} }
mClearService(serviceArgs) val hashCode = service.hashCode()
val serviceArgs = mServicesArgs.remove(hashCode) as MyGattServiceArgs
val characteristicsArgs = serviceArgs.characteristicsArgs.filterNotNull()
for (characteristicArgs in characteristicsArgs) {
val characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
val characteristic =
mCharacteristics.remove(characteristicHashCodeArgs) as BluetoothGattCharacteristic
val characteristicHashCode = characteristic.hashCode()
mCharacteristicsArgs.remove(characteristicHashCode)
val descriptorsArgs = characteristicArgs.descriptorsArgs.filterNotNull()
for (descriptorArgs in descriptorsArgs) {
val descriptorHashCodeArgs = descriptorArgs.hashCodeArgs
val descriptor =
mDescriptors.remove(descriptorHashCodeArgs) as BluetoothGattDescriptor
val descriptorHashCode = descriptor.hashCode()
mDescriptorsArgs.remove(descriptorHashCode)
}
}
} }
override fun clearServices() { override fun clearServices() {
mServer.clearServices() mServer.clearServices()
val servicesArgs = this.mServicesArgs.values mServices.clear()
for (serviceArgs in servicesArgs) { mCharacteristics.clear()
mClearService(serviceArgs) mDescriptors.clear()
}
mServicesArgs.clear()
mCharacteristicsArgs.clear()
mDescriptorsArgs.clear()
} }
override fun startAdvertising( override fun startAdvertising(
@ -235,14 +268,19 @@ class MyPeripheralManager(context: Context, binaryMessenger: BinaryMessenger) :
} }
} }
override fun onStateChanged(state: MyBluetoothLowEnergyState) { override fun onPermissionsRequested(granted: Boolean) {
when (state) { val callback = mSetUpCallback ?: return
MyBluetoothLowEnergyStateArgs.POWEREDOFF -> mCloseGattServer() val stateArgs = if (granted) {
MyBluetoothLowEnergyStateArgs.POWEREDON -> mOpenGattServer() registerReceiver()
else -> {} adapter.state.toBluetoothLowEnergyStateArgs()
} } else MyBluetoothLowEnergyStateArgs.UNAUTHORIZED
val stateNumberArgs = state.raw.toLong() mOnStateChanged(stateArgs)
mApi.onStateChanged(stateNumberArgs) {} callback(Result.success(Unit))
}
override fun onAdapterStateChanged(state: Int) {
val stateArgs = state.toBluetoothLowEnergyStateArgs()
mOnStateChanged(stateArgs)
} }
fun onServiceAdded(status: Int, service: BluetoothGattService) { fun onServiceAdded(status: Int, service: BluetoothGattService) {
@ -253,9 +291,6 @@ class MyPeripheralManager(context: Context, binaryMessenger: BinaryMessenger) :
} else { } else {
val error = IllegalStateException("Read rssi failed with status: $status") val error = IllegalStateException("Read rssi failed with status: $status")
callback(Result.failure(error)) callback(Result.failure(error))
val hashCode = service.hashCode()
val serviceArgs = mServicesArgs[hashCode] ?: return
mClearService(serviceArgs)
} }
} }
@ -403,7 +438,18 @@ class MyPeripheralManager(context: Context, binaryMessenger: BinaryMessenger) :
mNotifyCharacteristicValueChangedCallbacks.clear() mNotifyCharacteristicValueChangedCallbacks.clear()
} }
private fun mOpenGattServer() { private fun mOnStateChanged(stateArgs: MyBluetoothLowEnergyStateArgs) {
val stateNumberArgs = stateArgs.raw.toLong()
mApi.onStateChanged(stateNumberArgs) {}
// Renew GATT server when bluetooth adapter state changed.
when (stateArgs) {
MyBluetoothLowEnergyStateArgs.OFF -> mCloseServer()
MyBluetoothLowEnergyStateArgs.ON -> mOpenServer()
else -> {}
}
}
private fun mOpenServer() {
if (mOpening) { if (mOpening) {
return return
} }
@ -411,32 +457,11 @@ class MyPeripheralManager(context: Context, binaryMessenger: BinaryMessenger) :
mOpening = true mOpening = true
} }
private fun mCloseGattServer() { private fun mCloseServer() {
if (!mOpening) { if (!mOpening) {
return return
} }
mServer.close() mServer.close()
mOpening = false mOpening = false
} }
private fun mClearService(serviceArgs: MyGattServiceArgs) {
val characteristicsArgs = serviceArgs.characteristicsArgs.filterNotNull()
for (characteristicArgs in characteristicsArgs) {
val descriptorsArgs = characteristicArgs.descriptorsArgs.filterNotNull()
for (descriptorArgs in descriptorsArgs) {
val descriptorHashCodeArgs = descriptorArgs.hashCodeArgs
val descriptor = mDescriptors.remove(descriptorHashCodeArgs) ?: continue
val descriptorHashCode = descriptor.hashCode()
mDescriptorsArgs.remove(descriptorHashCode)
}
val characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
val characteristic = mCharacteristics.remove(characteristicHashCodeArgs) ?: continue
val characteristicHashCode = characteristic.hashCode()
mCharacteristicsArgs.remove(characteristicHashCode)
}
val serviceHashCodeArgs = serviceArgs.hashCodeArgs
val service = mServices.remove(serviceHashCodeArgs) ?: return
val serviceHashCode = service.hashCode()
mServicesArgs.remove(serviceHashCode)
}
} }

View File

@ -15,7 +15,7 @@ packages:
path: ".." path: ".."
relative: true relative: true
source: path source: path
version: "5.0.0" version: "5.0.1"
bluetooth_low_energy_platform_interface: bluetooth_low_energy_platform_interface:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -14,7 +14,20 @@ export 'my_api.g.dart';
// ToObject // ToObject
extension MyBluetoothLowEnergyStateArgsX on MyBluetoothLowEnergyStateArgs { extension MyBluetoothLowEnergyStateArgsX on MyBluetoothLowEnergyStateArgs {
BluetoothLowEnergyState toState() { BluetoothLowEnergyState toState() {
return BluetoothLowEnergyState.values[index]; switch (this) {
case MyBluetoothLowEnergyStateArgs.unknown:
return BluetoothLowEnergyState.unknown;
case MyBluetoothLowEnergyStateArgs.unsupported:
return BluetoothLowEnergyState.unsupported;
case MyBluetoothLowEnergyStateArgs.unauthorized:
return BluetoothLowEnergyState.unauthorized;
case MyBluetoothLowEnergyStateArgs.off:
case MyBluetoothLowEnergyStateArgs.turningOn:
return BluetoothLowEnergyState.poweredOff;
case MyBluetoothLowEnergyStateArgs.on:
case MyBluetoothLowEnergyStateArgs.turningOff:
return BluetoothLowEnergyState.poweredOn;
}
} }
} }

View File

@ -29,8 +29,10 @@ enum MyBluetoothLowEnergyStateArgs {
unknown, unknown,
unsupported, unsupported,
unauthorized, unauthorized,
poweredOff, off,
poweredOn, turningOn,
on,
turningOff,
} }
enum MyGattCharacteristicPropertyArgs { enum MyGattCharacteristicPropertyArgs {

View File

@ -15,8 +15,10 @@ enum MyBluetoothLowEnergyStateArgs {
unknown, unknown,
unsupported, unsupported,
unauthorized, unauthorized,
poweredOff, off,
poweredOn, turningOn,
on,
turningOff,
} }
enum MyGattCharacteristicPropertyArgs { enum MyGattCharacteristicPropertyArgs {
@ -124,6 +126,7 @@ class MyGattServiceArgs {
@HostApi() @HostApi()
abstract class MyCentralManagerHostApi { abstract class MyCentralManagerHostApi {
@async
void setUp(); void setUp();
@async @async
void startDiscovery(); void startDiscovery();
@ -182,6 +185,7 @@ abstract class MyCentralManagerFlutterApi {
@HostApi() @HostApi()
abstract class MyPeripheralManagerHostApi { abstract class MyPeripheralManagerHostApi {
@async
void setUp(); void setUp();
@async @async
void addService(MyGattServiceArgs serviceArgs); void addService(MyGattServiceArgs serviceArgs);

View File

@ -1,6 +1,6 @@
name: bluetooth_low_energy_android name: bluetooth_low_energy_android
description: Android implementation of the bluetooth_low_energy plugin. description: Android implementation of the bluetooth_low_energy plugin.
version: 5.0.0 version: 5.0.2
homepage: https://github.com/yanshouwang/bluetooth_low_energy homepage: https://github.com/yanshouwang/bluetooth_low_energy
environment: environment: