You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android BLE扫描ScanCallback如何实现指定间隔未发现设备的回调

实现方案

核心逻辑

你需要的超时清空逻辑属于业务层的控制逻辑,BLE扫描框架本身没有提供原生回调属于合理情况,我们可以通过Android官方标准API实现,完全符合规范,不属于变通方案:
每次收到扫描结果回调时,取消之前待触发的清空列表任务,重新提交一个延时指定间隔的清空任务。只要在间隔内有新的扫描结果到达,清空任务就会被持续推后;一旦超过间隔未收到任何扫描结果,延时任务就会正常触发执行列表清空操作。

协程实现(推荐,适配现代Android开发规范)

前置准备

首先声明两个成员变量,和扫描逻辑的生命周期绑定:

// 自定义超时间隔,示例为5秒
private val SCAN_TIMEOUT_MS = 5000L
// 存储待执行的清空任务
private var clearDevicesJob: Job? = null
// 你自己的设备列表实现,这里仅作示例
private val foundDevices = mutableListOf<BluetoothDevice>()

修改ScanCallback实现

private val leScanCallback: ScanCallback = object : ScanCallback() {
    override fun onScanResult(callbackType: Int, result: ScanResult) {
        super.onScanResult(callbackType, result)
        val device = result.device
        Log.d("LeDeviceScanner", "Device found: ${device.address} - ${device.name ?: "Unknown"}")
        onDeviceResult(result.device)
        
        // 核心逻辑:收到扫描结果后重置超时任务
        clearDevicesJob?.cancel()
        clearDevicesJob = lifecycleScope.launch { // 这里可以用和页面/扫描生命周期绑定的Scope,比如viewModelScope
            delay(SCAN_TIMEOUT_MS)
            // 超时未收到扫描结果,清空列表
            foundDevices.clear()
            // 这里可以加你自己的列表更新通知逻辑,比如notifyDataSetChanged
        }
    }

    override fun onScanFailed(errorCode: Int) {
        super.onScanFailed(errorCode)
        // 扫描失败时也可以按需取消超时任务、清空列表
        clearDevicesJob?.cancel()
        foundDevices.clear()
    }
}

生命周期适配

  • 启动扫描时,可主动提交一次超时任务,避免启动后长期未扫描到设备时列表不会清空
  • 停止扫描时,主动调用clearDevicesJob?.cancel()取消待执行任务,避免内存泄漏和不必要的逻辑触发

Handler实现(兼容旧项目无协程的场景)

前置准备

private val SCAN_TIMEOUT_MS = 5000L
private val mainHandler = Handler(Looper.getMainLooper())
private val foundDevices = mutableListOf<BluetoothDevice>()
private val clearDevicesRunnable = Runnable {
    foundDevices.clear()
    // 列表更新通知逻辑
}

修改ScanCallback实现

private val leScanCallback: ScanCallback = object : ScanCallback() {
    override fun onScanResult(callbackType: Int, result: ScanResult) {
        super.onScanResult(callbackType, result)
        val device = result.device
        Log.d("LeDeviceScanner", "Device found: ${device.address} - ${device.name ?: "Unknown"}")
        onDeviceResult(result.device)
        
        mainHandler.removeCallbacks(clearDevicesRunnable)
        mainHandler.postDelayed(clearDevicesRunnable, SCAN_TIMEOUT_MS)
    }

    override fun onScanFailed(errorCode: Int) {
        super.onScanFailed(errorCode)
        mainHandler.removeCallbacks(clearDevicesRunnable)
        foundDevices.clear()
    }
}

生命周期适配

和协程实现一致,启动扫描时按需调用postDelayed,停止扫描时调用removeCallbacks释放资源。

内容的提问来源于stack exchange,提问作者user16627306

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 12:27:03