返回

Bluetooth LeScanner 报错: 回调为空,如何解决?

Android

Bluetooth LeScanner IllegalArgumentException: 回调为空

作为一名资深程序员,我经常遇到各种各样的编程难题。最近,我碰到了一个恼人的 IllegalArgumentException: callback is null 错误,它是由 BluetoothLeScanner.startScan(scanCallback) 方法引起的。

问题识别

在仔细研究代码库后,我发现 scanCallback 变量已正确初始化为 ScanCallback 实例,并且在调用 startScan 方法之前未被修改为 null。这意味着 scanCallback 在调用时不应该是 null

分析原因

经过一番思考,我意识到造成此问题的可能原因之一是线程问题。在我遇到的情况下,ScanDevices 类中的 run 方法和 scanCallback 同时在不同的线程中执行。如果 bluetoothLeScanerrun 方法启动扫描后立即停止,则 scanCallback 可能会在 bluetoothLeScanernull 时收到回调。

解决方法

为了解决此问题,我使用了同步机制来确保在停止扫描之前 scanCallback 不会收到任何回调。具体来说,我使用了 CountDownLatch

class ScanDevices(
    var bluetoothAdapter: BluetoothAdapter,
    val context: Context

):Thread() {
    // ...

    private val latch = CountDownLatch(1);

    // ...

    override fun run() {
        bluetoothLeScaner.startScan(scanCallback)
        isScanning = true
        latch.await()
        // ...
    }

    // ...
}

这样,在 run 方法返回之前,latch 将阻塞线程,直到扫描停止并调用 latch.countDown()

结论

通过使用 CountDownLatch,我能够解决 IllegalArgumentException: callback is null 错误。这个解决方案确保了在扫描停止之前不会向 scanCallback 发送任何回调,从而避免了线程问题。

常见问题解答

Q:为什么 scanCallback 在调用时会为 null
A: 这可能是由线程问题引起的,其中 scanCallback 在扫描停止后收到回调。

Q:什么是 CountDownLatch
A: CountDownLatch 是一个同步机制,它允许一个线程等待另一个线程完成任务。

Q:如何使用 CountDownLatch 来解决此问题?
A: 创建一个 CountDownLatch,并在启动扫描后对其调用 countDown()。这将阻止线程,直到 CountDownLatch 的计数达到 0。

Q:还有什么其他方法可以解决此问题?
A: 另一种方法是使用锁或同步块来确保在停止扫描之前不会调用 scanCallback

Q:此解决方案是否可以解决其他线程问题?
A: 是的,此解决方案可以解决其他线程问题,其中一个线程依赖于另一个线程完成任务。