修复 setUp 和 clearServices 错误 (#39)
This commit is contained in:
@ -50,8 +50,10 @@ enum class MyBluetoothLowEnergyStateArgs(val raw: Int) {
|
||||
UNKNOWN(0),
|
||||
UNSUPPORTED(1),
|
||||
UNAUTHORIZED(2),
|
||||
POWEREDOFF(3),
|
||||
POWEREDON(4);
|
||||
OFF(3),
|
||||
TURNINGON(4),
|
||||
ON(5),
|
||||
TURNINGOFF(6);
|
||||
|
||||
companion object {
|
||||
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. */
|
||||
interface MyCentralManagerHostApi {
|
||||
fun setUp()
|
||||
fun setUp(callback: (Result<Unit>) -> Unit)
|
||||
fun startDiscovery(callback: (Result<Unit>) -> Unit)
|
||||
fun stopDiscovery()
|
||||
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)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
var wrapped: List<Any?>
|
||||
try {
|
||||
api.setUp()
|
||||
wrapped = listOf<Any?>(null)
|
||||
} catch (exception: Throwable) {
|
||||
wrapped = wrapError(exception)
|
||||
api.setUp() { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
} else {
|
||||
reply.reply(wrapResult(null))
|
||||
}
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
@ -795,7 +797,7 @@ private object MyPeripheralManagerHostApiCodec : StandardMessageCodec() {
|
||||
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
interface MyPeripheralManagerHostApi {
|
||||
fun setUp()
|
||||
fun setUp(callback: (Result<Unit>) -> Unit)
|
||||
fun addService(serviceArgs: MyGattServiceArgs, callback: (Result<Unit>) -> Unit)
|
||||
fun removeService(hashCodeArgs: Long)
|
||||
fun clearServices()
|
||||
@ -816,14 +818,14 @@ interface MyPeripheralManagerHostApi {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.bluetooth_low_energy_android.MyPeripheralManagerHostApi.setUp", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
var wrapped: List<Any?>
|
||||
try {
|
||||
api.setUp()
|
||||
wrapped = listOf<Any?>(null)
|
||||
} catch (exception: Throwable) {
|
||||
wrapped = wrapError(exception)
|
||||
api.setUp() { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
} else {
|
||||
reply.reply(wrapResult(null))
|
||||
}
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
|
@ -131,8 +131,11 @@ fun MyGattServiceArgs.toService(): BluetoothGattService {
|
||||
//region ToArgs
|
||||
fun Int.toBluetoothLowEnergyStateArgs(): MyBluetoothLowEnergyStateArgs {
|
||||
return when (this) {
|
||||
BluetoothAdapter.STATE_ON -> MyBluetoothLowEnergyStateArgs.POWEREDON
|
||||
else -> MyBluetoothLowEnergyStateArgs.POWEREDOFF
|
||||
BluetoothAdapter.STATE_OFF -> MyBluetoothLowEnergyStateArgs.OFF
|
||||
BluetoothAdapter.STATE_TURNING_ON -> MyBluetoothLowEnergyStateArgs.TURNINGON
|
||||
BluetoothAdapter.STATE_ON -> MyBluetoothLowEnergyStateArgs.ON
|
||||
BluetoothAdapter.STATE_TURNING_OFF -> MyBluetoothLowEnergyStateArgs.TURNINGOFF
|
||||
else -> MyBluetoothLowEnergyStateArgs.UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,8 +14,6 @@ import io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.Executor
|
||||
|
||||
typealias MyBluetoothLowEnergyState = MyBluetoothLowEnergyStateArgs
|
||||
|
||||
abstract class MyBluetoothLowEnergyManager(context: Context) {
|
||||
companion object {
|
||||
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 hasFeature get() = mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
|
||||
protected val manager
|
||||
get() = ContextCompat.getSystemService(
|
||||
mContext, BluetoothManager::class.java
|
||||
) as BluetoothManager
|
||||
protected val adapter get() = manager.adapter as BluetoothAdapter
|
||||
|
||||
protected fun initialize() {
|
||||
val hasFeature =
|
||||
mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
|
||||
if (hasFeature) {
|
||||
val authorized = permissions.all { permission ->
|
||||
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 checkPermissions(): Boolean {
|
||||
return permissions.all { permission ->
|
||||
ActivityCompat.checkSelfPermission(
|
||||
mContext, permission
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
}
|
||||
|
||||
protected fun requestPermissions() {
|
||||
val activity = mBinding.activity
|
||||
ActivityCompat.requestPermissions(activity, permissions, requestCode)
|
||||
}
|
||||
|
||||
fun onAttachedToActivity(binding: ActivityPluginBinding) {
|
||||
binding.addRequestPermissionsResultListener(mRequestPermissionsResultListener)
|
||||
mBinding = binding
|
||||
@ -82,8 +73,9 @@ abstract class MyBluetoothLowEnergyManager(context: Context) {
|
||||
if (this.requestCode != requestCode) {
|
||||
return false
|
||||
}
|
||||
val authorized = results.all { r -> r == PackageManager.PERMISSION_GRANTED }
|
||||
mOnAuthorizationStateChanged(authorized)
|
||||
val granted =
|
||||
permissions.contentEquals(this.permissions) && results.all { r -> r == PackageManager.PERMISSION_GRANTED }
|
||||
onPermissionsRequested(granted)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -92,23 +84,11 @@ abstract class MyBluetoothLowEnergyManager(context: Context) {
|
||||
if (action != BluetoothAdapter.ACTION_STATE_CHANGED) {
|
||||
return
|
||||
}
|
||||
val extra = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF)
|
||||
val state = extra.toBluetoothLowEnergyStateArgs()
|
||||
onStateChanged(state)
|
||||
val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF)
|
||||
onAdapterStateChanged(state)
|
||||
}
|
||||
|
||||
private fun mOnAuthorizationStateChanged(authorized: Boolean) {
|
||||
val state = if (authorized) {
|
||||
mRegisterReceiver()
|
||||
if (adapter.state == BluetoothAdapter.STATE_ON) MyBluetoothLowEnergyState.POWEREDON
|
||||
else MyBluetoothLowEnergyState.POWEREDOFF
|
||||
} else {
|
||||
MyBluetoothLowEnergyState.UNAUTHORIZED
|
||||
}
|
||||
onStateChanged(state)
|
||||
}
|
||||
|
||||
private fun mRegisterReceiver() {
|
||||
protected fun registerReceiver() {
|
||||
if (mRegistered) {
|
||||
return
|
||||
}
|
||||
@ -119,6 +99,8 @@ abstract class MyBluetoothLowEnergyManager(context: Context) {
|
||||
|
||||
abstract val permissions: Array<String>
|
||||
abstract val requestCode: Int
|
||||
abstract fun onStateChanged(state: MyBluetoothLowEnergyState)
|
||||
|
||||
abstract fun onPermissionsRequested(granted: Boolean)
|
||||
abstract fun onAdapterStateChanged(state: Int)
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ class MyCentralManager(context: Context, binaryMessenger: BinaryMessenger) :
|
||||
private val mCharacteristics: MutableMap<String, Map<Long, BluetoothGattCharacteristic>>
|
||||
private val mDescriptors: MutableMap<String, Map<Long, BluetoothGattDescriptor>>
|
||||
|
||||
private var mSetUpCallback: ((Result<Unit>) -> Unit)?
|
||||
private var mStartDiscoveryCallback: ((Result<Unit>) -> Unit)?
|
||||
private val mConnectCallbacks: 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()
|
||||
mDescriptors = mutableMapOf()
|
||||
|
||||
mSetUpCallback = null
|
||||
mStartDiscoveryCallback = null
|
||||
mConnectCallbacks = mutableMapOf()
|
||||
mDisconnectCallbacks = mutableMapOf()
|
||||
@ -93,9 +95,25 @@ class MyCentralManager(context: Context, binaryMessenger: BinaryMessenger) :
|
||||
override val requestCode: Int
|
||||
get() = REQUEST_CODE
|
||||
|
||||
override fun setUp() {
|
||||
mClearState()
|
||||
initialize()
|
||||
override fun setUp(callback: (Result<Unit>) -> Unit) {
|
||||
try {
|
||||
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) {
|
||||
@ -104,10 +122,10 @@ class MyCentralManager(context: Context, binaryMessenger: BinaryMessenger) :
|
||||
val settings =
|
||||
ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build()
|
||||
mScanner.startScan(filters, settings, mScanCallback)
|
||||
mStartDiscoveryCallback = callback
|
||||
executor.execute {
|
||||
onScanSucceed()
|
||||
}
|
||||
mStartDiscoveryCallback = callback
|
||||
} catch (e: Throwable) {
|
||||
callback(Result.failure(e))
|
||||
}
|
||||
@ -319,9 +337,19 @@ class MyCentralManager(context: Context, binaryMessenger: BinaryMessenger) :
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStateChanged(state: MyBluetoothLowEnergyState) {
|
||||
val stateNumberArgs = state.raw.toLong()
|
||||
mApi.onStateChanged(stateNumberArgs) {}
|
||||
override fun onPermissionsRequested(granted: Boolean) {
|
||||
val callback = mSetUpCallback ?: return
|
||||
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() {
|
||||
@ -554,6 +582,7 @@ class MyCentralManager(context: Context, binaryMessenger: BinaryMessenger) :
|
||||
mCharacteristics.clear()
|
||||
mDescriptors.clear()
|
||||
|
||||
mSetUpCallback = null
|
||||
mStartDiscoveryCallback = null
|
||||
mConnectCallbacks.clear()
|
||||
mDisconnectCallbacks.clear()
|
||||
@ -566,6 +595,11 @@ class MyCentralManager(context: Context, binaryMessenger: BinaryMessenger) :
|
||||
mWriteDescriptorCallbacks.clear()
|
||||
}
|
||||
|
||||
private fun mOnStateChanged(stateArgs: MyBluetoothLowEnergyStateArgs) {
|
||||
val stateNumberArgs = stateArgs.raw.toLong()
|
||||
mApi.onStateChanged(stateNumberArgs) {}
|
||||
}
|
||||
|
||||
private fun mRetrieveCharacteristic(
|
||||
addressArgs: String, hashCodeArgs: Long
|
||||
): BluetoothGattCharacteristic? {
|
||||
|
@ -19,7 +19,7 @@ import io.flutter.plugin.common.BinaryMessenger
|
||||
class MyPeripheralManager(context: Context, binaryMessenger: BinaryMessenger) :
|
||||
MyBluetoothLowEnergyManager(context), MyPeripheralManagerHostApi {
|
||||
companion object {
|
||||
const val REQUEST_CODE = 444
|
||||
const val REQUEST_CODE = 445
|
||||
}
|
||||
|
||||
private val advertiser get() = adapter.bluetoothLeAdvertiser
|
||||
@ -89,9 +89,25 @@ class MyPeripheralManager(context: Context, binaryMessenger: BinaryMessenger) :
|
||||
override val requestCode: Int
|
||||
get() = REQUEST_CODE
|
||||
|
||||
override fun setUp() {
|
||||
mClearState()
|
||||
initialize()
|
||||
override fun setUp(callback: (Result<Unit>) -> Unit) {
|
||||
try {
|
||||
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) {
|
||||
@ -143,28 +159,45 @@ class MyPeripheralManager(context: Context, binaryMessenger: BinaryMessenger) :
|
||||
}
|
||||
mAddServiceCallback = callback
|
||||
} catch (e: Throwable) {
|
||||
mClearService(serviceArgs)
|
||||
callback(Result.failure(e))
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeService(hashCodeArgs: Long) {
|
||||
val service = mServices[hashCodeArgs] as BluetoothGattService
|
||||
val hashCode = service.hashCode()
|
||||
val serviceArgs = mServicesArgs[hashCode] as MyGattServiceArgs
|
||||
val service = mServices.remove(hashCodeArgs) as BluetoothGattService
|
||||
val removed = mServer.removeService(service)
|
||||
if (!removed) {
|
||||
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() {
|
||||
mServer.clearServices()
|
||||
val servicesArgs = this.mServicesArgs.values
|
||||
for (serviceArgs in servicesArgs) {
|
||||
mClearService(serviceArgs)
|
||||
}
|
||||
mServices.clear()
|
||||
mCharacteristics.clear()
|
||||
mDescriptors.clear()
|
||||
|
||||
mServicesArgs.clear()
|
||||
mCharacteristicsArgs.clear()
|
||||
mDescriptorsArgs.clear()
|
||||
}
|
||||
|
||||
override fun startAdvertising(
|
||||
@ -235,14 +268,19 @@ class MyPeripheralManager(context: Context, binaryMessenger: BinaryMessenger) :
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStateChanged(state: MyBluetoothLowEnergyState) {
|
||||
when (state) {
|
||||
MyBluetoothLowEnergyStateArgs.POWEREDOFF -> mCloseGattServer()
|
||||
MyBluetoothLowEnergyStateArgs.POWEREDON -> mOpenGattServer()
|
||||
else -> {}
|
||||
}
|
||||
val stateNumberArgs = state.raw.toLong()
|
||||
mApi.onStateChanged(stateNumberArgs) {}
|
||||
override fun onPermissionsRequested(granted: Boolean) {
|
||||
val callback = mSetUpCallback ?: return
|
||||
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)
|
||||
}
|
||||
|
||||
fun onServiceAdded(status: Int, service: BluetoothGattService) {
|
||||
@ -253,9 +291,6 @@ class MyPeripheralManager(context: Context, binaryMessenger: BinaryMessenger) :
|
||||
} else {
|
||||
val error = IllegalStateException("Read rssi failed with status: $status")
|
||||
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()
|
||||
}
|
||||
|
||||
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) {
|
||||
return
|
||||
}
|
||||
@ -411,32 +457,11 @@ class MyPeripheralManager(context: Context, binaryMessenger: BinaryMessenger) :
|
||||
mOpening = true
|
||||
}
|
||||
|
||||
private fun mCloseGattServer() {
|
||||
private fun mCloseServer() {
|
||||
if (!mOpening) {
|
||||
return
|
||||
}
|
||||
mServer.close()
|
||||
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)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user