解决连接过程中断开蓝牙产生的问题

This commit is contained in:
闫守旺
2021-07-02 11:34:28 +08:00
parent d4e80d7232
commit 92daec7450
2 changed files with 44 additions and 48 deletions

View File

@ -9,7 +9,6 @@ import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Build import android.os.Build
import android.os.DeadObjectException
import android.os.Handler import android.os.Handler
import android.os.ParcelUuid import android.os.ParcelUuid
import android.util.Log import android.util.Log
@ -52,6 +51,7 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
private const val NOTIFY_CHARACTERISTIC_FAILED = 7 private const val NOTIFY_CHARACTERISTIC_FAILED = 7
private const val READ_DESCRIPTOR_FAILED = 8 private const val READ_DESCRIPTOR_FAILED = 8
private const val WRITE_DESCRIPTOR_FAILED = 9 private const val WRITE_DESCRIPTOR_FAILED = 9
private const val BLUETOOTH_ADAPTER_CLOSED = 10
private const val REQUEST_CODE = 443 private const val REQUEST_CODE = 443
} }
@ -165,56 +165,49 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
BluetoothGatt.GATT_SUCCESS -> { BluetoothGatt.GATT_SUCCESS -> {
when (newState) { when (newState) {
BluetoothProfile.STATE_DISCONNECTED -> { BluetoothProfile.STATE_DISCONNECTED -> {
// Maybe disconnect succeed, connect failed, or connection lost when an adaptor closed event triggered.
gatts.remove(address)!!.close() gatts.remove(address)!!.close()
val disconnect = disconnects.remove(address) val disconnect = disconnects.remove(address)
if (disconnect != null) handler.post { disconnect.success() } if (disconnect != null) handler.post { disconnect.success() }
else { else {
// An adapter closed event val connect = connects.remove(address)
val id = gatt.hashCode() if (connect != null) handler.post { connect.error(BLUETOOTH_ADAPTER_CLOSED) }
val connectionLost = ConnectionLost.newBuilder() else {
.setId(id) val id = gatt.hashCode()
.setErrorCode(status) val connectionLost = ConnectionLost.newBuilder()
.build() .setId(id)
val event = Message.newBuilder() .setErrorCode(BLUETOOTH_ADAPTER_CLOSED)
.setCategory(GATT_CONNECTION_LOST) .build()
.setConnectionLost(connectionLost) val event = Message.newBuilder()
.build() .setCategory(GATT_CONNECTION_LOST)
.toByteArray() .setConnectionLost(connectionLost)
handler.post { sink?.success(event) } .build()
.toByteArray()
handler.post { sink?.success(event) }
}
} }
} }
BluetoothProfile.STATE_CONNECTED -> { BluetoothProfile.STATE_CONNECTED -> {
val code = when { // Must be connect succeed.
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP -> { val requested = gatt.requestMtu(512)
// TODO: how to get exact MTU size of this device here? if (!requested) {
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) {
gatts.remove(address)!!.close() gatts.remove(address)!!.close()
val connect = connects.remove(address)!! 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 -> throw NotImplementedError() // should never be called.
} }
} }
else -> { else -> {
// Maybe connect failed, disconnect failed or connection lost when an adaptor closed event triggered.
gatts.remove(address)!!.close() gatts.remove(address)!!.close()
val connect = connects.remove(address) val connect = connects.remove(address)
val disconnect = disconnects.remove(address) if (connect != null) handler.post { connect.error(status) }
when { else {
connect != null -> handler.post { connect.error(status) } val disconnect = disconnects.remove(address)
disconnect != null -> handler.post { disconnect.error(status) } if (disconnect != null) handler.post { disconnect.error(status) }
else -> { else {
val id = gatt.hashCode() val id = gatt.hashCode()
val connectionLost = ConnectionLost.newBuilder() val connectionLost = ConnectionLost.newBuilder()
.setId(id) .setId(id)
@ -237,7 +230,8 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
val address = gatt!!.device.address val address = gatt!!.device.address
val code = when (status) { val code = when (status) {
BluetoothGatt.GATT_SUCCESS -> { BluetoothGatt.GATT_SUCCESS -> {
if (gatt.discoverServices()) { val discovered = gatt.discoverServices()
if (discovered) {
mtus[address] = mtu mtus[address] = mtu
NO_ERROR NO_ERROR
} else DISCOVER_SERVICES_FAILED } else DISCOVER_SERVICES_FAILED
@ -418,7 +412,7 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
val category = call.category 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) { else when (category) {
BLUETOOTH_AVAILABLE -> result.success(bluetoothAvailable) BLUETOOTH_AVAILABLE -> result.success(bluetoothAvailable)
BLUETOOTH_STATE -> result.success(bluetoothAdapter.state.opened) BLUETOOTH_STATE -> result.success(bluetoothAdapter.state.opened)

View File

@ -40,14 +40,17 @@ class _HomeViewState extends State<HomeView> with WidgetsBindingObserver {
void initState() { void initState() {
super.initState(); super.initState();
WidgetsBinding.instance!.addObserver(this); WidgetsBinding.instance!.addObserver(this);
stateSubscription = central.stateChanged.listen((state) { stateSubscription = central.stateChanged.listen(
if (state) { (state) {
startDiscovery(); final invisible = !ModalRoute.of(context)!.isCurrent;
} else { if (invisible) return;
discoveries.value = {}; if (state) {
discovering.value = false; startDiscovery();
} } else {
}); discovering.value = false;
}
},
);
discoverySubscription = central.discovered.listen( discoverySubscription = central.discovered.listen(
(discovery) { (discovery) {
discoveries.value[discovery.address] = discovery; discoveries.value[discovery.address] = discovery;
@ -85,16 +88,15 @@ class _HomeViewState extends State<HomeView> with WidgetsBindingObserver {
} }
void startDiscovery() async { void startDiscovery() async {
final state = await central.state; if (discovering.value || !await central.state) return;
if (!state) return;
await central.startDiscovery(); await central.startDiscovery();
discovering.value = true; discovering.value = true;
} }
void stopDiscovery() async { void stopDiscovery() async {
final state = await central.state; if (!discovering.value || !await central.state) return;
if (!state) return;
await central.stopDiscovery(); await central.stopDiscovery();
discoveries.value = {};
discovering.value = false; discovering.value = false;
} }