From 92daec7450b172debc1c374abdf646043aaae5d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=97=AB=E5=AE=88=E6=97=BA?= Date: Fri, 2 Jul 2021 11:34:28 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E8=BF=9E=E6=8E=A5=E8=BF=87?= =?UTF-8?q?=E7=A8=8B=E4=B8=AD=E6=96=AD=E5=BC=80=E8=93=9D=E7=89=99=E4=BA=A7?= =?UTF-8?q?=E7=94=9F=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BluetoothLowEnergyPlugin.kt | 66 +++++++++---------- example/lib/main.dart | 26 ++++---- 2 files changed, 44 insertions(+), 48 deletions(-) diff --git a/android/src/main/kotlin/dev/yanshouwang/bluetooth_low_energy/BluetoothLowEnergyPlugin.kt b/android/src/main/kotlin/dev/yanshouwang/bluetooth_low_energy/BluetoothLowEnergyPlugin.kt index b04a014..3f1c82c 100644 --- a/android/src/main/kotlin/dev/yanshouwang/bluetooth_low_energy/BluetoothLowEnergyPlugin.kt +++ b/android/src/main/kotlin/dev/yanshouwang/bluetooth_low_energy/BluetoothLowEnergyPlugin.kt @@ -9,7 +9,6 @@ import android.content.Intent import android.content.IntentFilter import android.content.pm.PackageManager import android.os.Build -import android.os.DeadObjectException import android.os.Handler import android.os.ParcelUuid import android.util.Log @@ -52,6 +51,7 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler private const val NOTIFY_CHARACTERISTIC_FAILED = 7 private const val READ_DESCRIPTOR_FAILED = 8 private const val WRITE_DESCRIPTOR_FAILED = 9 + private const val BLUETOOTH_ADAPTER_CLOSED = 10 private const val REQUEST_CODE = 443 } @@ -165,56 +165,49 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler BluetoothGatt.GATT_SUCCESS -> { when (newState) { BluetoothProfile.STATE_DISCONNECTED -> { + // Maybe disconnect succeed, connect failed, or connection lost when an adaptor closed event triggered. gatts.remove(address)!!.close() val disconnect = disconnects.remove(address) if (disconnect != null) handler.post { disconnect.success() } else { - // An adapter closed event - val id = gatt.hashCode() - val connectionLost = ConnectionLost.newBuilder() - .setId(id) - .setErrorCode(status) - .build() - val event = Message.newBuilder() - .setCategory(GATT_CONNECTION_LOST) - .setConnectionLost(connectionLost) - .build() - .toByteArray() - handler.post { sink?.success(event) } + val connect = connects.remove(address) + if (connect != null) handler.post { connect.error(BLUETOOTH_ADAPTER_CLOSED) } + else { + val id = gatt.hashCode() + val connectionLost = ConnectionLost.newBuilder() + .setId(id) + .setErrorCode(BLUETOOTH_ADAPTER_CLOSED) + .build() + val event = Message.newBuilder() + .setCategory(GATT_CONNECTION_LOST) + .setConnectionLost(connectionLost) + .build() + .toByteArray() + handler.post { sink?.success(event) } + } } } BluetoothProfile.STATE_CONNECTED -> { - val code = when { - Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP -> { - // TODO: how to get exact MTU size of this device here? - if (gatt.requestMtu(512)) NO_ERROR - else REQUEST_MTU_FAILED - } - else -> { - if (gatt.discoverServices()) { - // Just use 23 as MTU before LOLLIPOP. - mtus[address] = 23 - NO_ERROR - } else DISCOVER_SERVICES_FAILED - } - } - if (code != NO_ERROR) { + // Must be connect succeed. + val requested = gatt.requestMtu(512) + if (!requested) { gatts.remove(address)!!.close() val connect = connects.remove(address)!! - handler.post { connect.error(code) } + handler.post { connect.error(REQUEST_MTU_FAILED) } } } else -> throw NotImplementedError() // should never be called. } } else -> { + // Maybe connect failed, disconnect failed or connection lost when an adaptor closed event triggered. gatts.remove(address)!!.close() val connect = connects.remove(address) - val disconnect = disconnects.remove(address) - when { - connect != null -> handler.post { connect.error(status) } - disconnect != null -> handler.post { disconnect.error(status) } - else -> { + if (connect != null) handler.post { connect.error(status) } + else { + val disconnect = disconnects.remove(address) + if (disconnect != null) handler.post { disconnect.error(status) } + else { val id = gatt.hashCode() val connectionLost = ConnectionLost.newBuilder() .setId(id) @@ -237,7 +230,8 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler val address = gatt!!.device.address val code = when (status) { BluetoothGatt.GATT_SUCCESS -> { - if (gatt.discoverServices()) { + val discovered = gatt.discoverServices() + if (discovered) { mtus[address] = mtu NO_ERROR } else DISCOVER_SERVICES_FAILED @@ -418,7 +412,7 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { val category = call.category - if (category != BLUETOOTH_AVAILABLE && category != BLUETOOTH_STATE && !bluetoothAdapter.state.opened) result.error(INVALID_REQUEST) + if (category != BLUETOOTH_AVAILABLE && category != BLUETOOTH_STATE && !bluetoothAdapter.state.opened) result.error(BLUETOOTH_ADAPTER_CLOSED) else when (category) { BLUETOOTH_AVAILABLE -> result.success(bluetoothAvailable) BLUETOOTH_STATE -> result.success(bluetoothAdapter.state.opened) diff --git a/example/lib/main.dart b/example/lib/main.dart index c96007a..45e15c0 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -40,14 +40,17 @@ class _HomeViewState extends State with WidgetsBindingObserver { void initState() { super.initState(); WidgetsBinding.instance!.addObserver(this); - stateSubscription = central.stateChanged.listen((state) { - if (state) { - startDiscovery(); - } else { - discoveries.value = {}; - discovering.value = false; - } - }); + stateSubscription = central.stateChanged.listen( + (state) { + final invisible = !ModalRoute.of(context)!.isCurrent; + if (invisible) return; + if (state) { + startDiscovery(); + } else { + discovering.value = false; + } + }, + ); discoverySubscription = central.discovered.listen( (discovery) { discoveries.value[discovery.address] = discovery; @@ -85,16 +88,15 @@ class _HomeViewState extends State with WidgetsBindingObserver { } void startDiscovery() async { - final state = await central.state; - if (!state) return; + if (discovering.value || !await central.state) return; await central.startDiscovery(); discovering.value = true; } void stopDiscovery() async { - final state = await central.state; - if (!state) return; + if (!discovering.value || !await central.state) return; await central.stopDiscovery(); + discoveries.value = {}; discovering.value = false; }