处理完第一个连接后无法重新开始扫描

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.
 */