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

使用Kotlin的Luch BLE Beacon扫描库时,如何在监听器中调用Ranger计算信标距离?

在Kotlin的Luch BLE信标扫描库中,监听器模式下计算距离的解决方案

其实你遇到的两个问题都可以通过Kotlin的变量捕获特性和线程安全集合来解决,我给你一步步拆解:

1. 在监听器内部调用Ranger计算距离

你不需要把Ranger实例拿到监听器外部,只要beaconScanner是外部作用域的可访问变量(比如类成员、局部变量),Kotlin的lambda会自动捕获它,这样你就能在setBeaconBatchListener的回调里直接获取Ranger并计算距离。

如果beaconScanner是类的成员变量:

// 类成员变量,让监听器可以捕获到
private lateinit var beaconScanner: BeaconScanner

fun setupScanner(context: Context) {
    val beaconParser = BeaconParser.Builder()
        .setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24") // 示例iBeacon布局
        .build()

    beaconScanner = BeaconScanner.Builder(context)
        .setBeaconParser(beaconParser)
        .setBeaconBatchListener { beacons ->
            // 直接在回调里获取Ranger
            val ranger = beaconScanner.getRanger()
            for (beacon in beacons) {
                val beaconPower = beacon.txPower
                // 计算距离
                val distance = ranger.calculateDistance(beacon)
                println("Beacon distance: $distance m")
            }
        }
        .setRangingEnabled()
        .build()
}

如果beaconScanner是局部变量,也可以提前拿到Ranger实例再设置监听器:

fun startLocalScan(context: Context) {
    val beaconParser = BeaconParser.Builder()
        .setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24")
        .build()

    val beaconScanner = BeaconScanner.Builder(context)
        .setBeaconParser(beaconParser)
        .setRangingEnabled()
        .build()

    // 提前获取Ranger,让监听器可以直接使用
    val ranger = beaconScanner.getRanger()

    beaconScanner.setBeaconBatchListener { beacons ->
        for (beacon in beacons) {
            val distance = ranger.calculateDistance(beacon)
            // 处理距离逻辑
        }
    }

    beaconScanner.start()
}

2. 安全保存Beacons列表供外部访问

扫描回调是在后台线程执行的,直接用普通ArrayList会有线程安全问题,建议用线程安全的集合来保存扫描结果,比如CopyOnWriteArrayList(适合读多写少的场景),同时返回不可修改的列表避免外部意外修改:

class BeaconManager(private val context: Context) {
    // 线程安全集合保存扫描到的beacons
    private val scannedBeacons = CopyOnWriteArrayList<Beacon>()
    private lateinit var beaconScanner: BeaconScanner

    fun initScanner() {
        val beaconParser = BeaconParser.Builder()
            .setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24")
            .build()

        beaconScanner = BeaconScanner.Builder(context)
            .setBeaconParser(beaconParser)
            .setBeaconBatchListener { beacons ->
                // 清空并更新集合
                scannedBeacons.clear()
                scannedBeacons.addAll(beacons)

                // 同时在这里计算距离
                val ranger = beaconScanner.getRanger()
                beacons.forEach { beacon ->
                    val distance = ranger.calculateDistance(beacon)
                    // 业务逻辑处理
                }
            }
            .setRangingEnabled()
            .build()
    }

    fun startScanning() {
        beaconScanner.start()
    }

    // 供外部获取最新扫描结果,返回不可修改视图
    fun getLatestBeacons(): List<Beacon> {
        return Collections.unmodifiableList(scannedBeacons)
    }
}

核心要点总结

  • 变量捕获:Kotlin的lambda会自动捕获外部作用域的变量,所以只要beaconScanner或ranger在监听器的作用域内可访问,就能在回调里使用它们。
  • 线程安全:扫描回调运行在后台线程,必须用线程安全集合保存数据,避免并发修改异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 20:28:17