处理完第一个连接后无法重新开始扫描
Can't restart scan after disposing of the first connection
我有一个相当长的 Rx 操作链用于我的初始扫描、连接和授权。这是代码。
fun startScanning() {
getScanObservable()
.take(1)
.map { scanResult ->
rxBleDevice = scanResult.bleDevice
observeDeviceState()
scanResult.bleDevice.establishConnection(false)
}
.flatMap { it }
.map { bleConnection ->
rxBleConnection = bleConnection
bleConnection.discoverServices()
}
.flatMapSingle { it }
.map { services ->
rxBleDeviceServices = services
performAuthentication()
}
.flatMap { it }
.subscribe({
state.postValue(State.AUTHENTICATED)
setupNotifications()
}, {
FirebaseCrashlytics.getInstance().recordException(it)
})
.let { disposables.add(it) }
}
因此,综上所述,代码获取第一个扫描结果并立即开始建立连接。完成后,我会发现服务,然后最终对移动客户端进行身份验证。在“链”的末尾(在订阅回调中),我设置了所有需要的特征通知,然后将 Disposable
保存到我的 CompositeDisposable
变量中,该变量还包含我从订阅特征通知中获取。
当我调用 disposables.dispose()
时,客户端确实断开了连接。我知道它是因为外围设备显示断开连接状态并且 RxBleDevice
也显示 Disconnected
状态。
问题是如果我再次调用 startScanning
方法,没有任何反应。第一个 map
操作永远不会被调用,订阅方法的 none 也会被调用。它只有在我重新启动 activity 时才有效,它会从头开始重新实例化所有内容。
这里还有 getScanObservable()
代码:
private fun getScanObservable(): Observable<ScanResult> {
val scanSettings = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
.build()
val scanFilter = ScanFilter.Builder()
.setDeviceName(token.deviceUid)
.build()
return rxBleClient.scanBleDevices(scanSettings, scanFilter)
}
我是这样处理的:
private val disposables = CompositeDisposable()
fun cleanup() {
if (!disposables.isDisposed) {
disposables.dispose()
rxBleDevice = null
rxBleDeviceServices = null
rxBleConnection = null
}
}
每当我想关闭连接并准备设备重新扫描和重新连接时,我都会调用 cleanup()
方法。这就是为什么我也销毁了所有 RxAndroidBle 引用,只保留 RxBleClient 引用。
无法启动新扫描的原因在于您如何处理前一个扫描。如果您查看实现或 CompositeDisposable.add()
Javadoc,您会看到:
/**
* Adds a disposable to this container or disposes it if the
* container has been disposed.
* @param disposable the disposable to add, not null
* @return true if successful, false if this container has been disposed
* @throws NullPointerException if {@code disposable} is null
*/
您调用 CompositeDisposable.dispose()
因此处理容器。如果您将 .doOnDispose { Log.i("startScanning", "disposed!") }
添加到 startScanning()
函数,您很快就会发现。
如果你想处理 CompositeDisposable
的内容而不是容器使用 CompositeDisposable.clear()
:
/**
* Atomically clears the container, then disposes all the previously contained Disposables.
*/
我有一个相当长的 Rx 操作链用于我的初始扫描、连接和授权。这是代码。
fun startScanning() {
getScanObservable()
.take(1)
.map { scanResult ->
rxBleDevice = scanResult.bleDevice
observeDeviceState()
scanResult.bleDevice.establishConnection(false)
}
.flatMap { it }
.map { bleConnection ->
rxBleConnection = bleConnection
bleConnection.discoverServices()
}
.flatMapSingle { it }
.map { services ->
rxBleDeviceServices = services
performAuthentication()
}
.flatMap { it }
.subscribe({
state.postValue(State.AUTHENTICATED)
setupNotifications()
}, {
FirebaseCrashlytics.getInstance().recordException(it)
})
.let { disposables.add(it) }
}
因此,综上所述,代码获取第一个扫描结果并立即开始建立连接。完成后,我会发现服务,然后最终对移动客户端进行身份验证。在“链”的末尾(在订阅回调中),我设置了所有需要的特征通知,然后将 Disposable
保存到我的 CompositeDisposable
变量中,该变量还包含我从订阅特征通知中获取。
当我调用 disposables.dispose()
时,客户端确实断开了连接。我知道它是因为外围设备显示断开连接状态并且 RxBleDevice
也显示 Disconnected
状态。
问题是如果我再次调用 startScanning
方法,没有任何反应。第一个 map
操作永远不会被调用,订阅方法的 none 也会被调用。它只有在我重新启动 activity 时才有效,它会从头开始重新实例化所有内容。
这里还有 getScanObservable()
代码:
private fun getScanObservable(): Observable<ScanResult> {
val scanSettings = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
.build()
val scanFilter = ScanFilter.Builder()
.setDeviceName(token.deviceUid)
.build()
return rxBleClient.scanBleDevices(scanSettings, scanFilter)
}
我是这样处理的:
private val disposables = CompositeDisposable()
fun cleanup() {
if (!disposables.isDisposed) {
disposables.dispose()
rxBleDevice = null
rxBleDeviceServices = null
rxBleConnection = null
}
}
每当我想关闭连接并准备设备重新扫描和重新连接时,我都会调用 cleanup()
方法。这就是为什么我也销毁了所有 RxAndroidBle 引用,只保留 RxBleClient 引用。
无法启动新扫描的原因在于您如何处理前一个扫描。如果您查看实现或 CompositeDisposable.add()
Javadoc,您会看到:
/** * Adds a disposable to this container or disposes it if the * container has been disposed. * @param disposable the disposable to add, not null * @return true if successful, false if this container has been disposed * @throws NullPointerException if {@code disposable} is null */
您调用 CompositeDisposable.dispose()
因此处理容器。如果您将 .doOnDispose { Log.i("startScanning", "disposed!") }
添加到 startScanning()
函数,您很快就会发现。
如果你想处理 CompositeDisposable
的内容而不是容器使用 CompositeDisposable.clear()
:
/** * Atomically clears the container, then disposes all the previously contained Disposables. */