使用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
相关产品推荐
相关产品推荐

