Xamarin中按钮点击后Beacon监听器持续运行问题咨询
关于BeaconDetector中监听器持续运行与定时检测的问题
先直接解答你的第一个疑问:点击按钮后,_rangeNotifier.DidRangeBeaconsInRegionComplete不会持续运行。原因是你每次调用DetectAvailableBeacons()都会重新创建全新的_rangeNotifier和_monitorNotifier实例,而且默认情况下,BeaconManager绑定完成后只会执行一次扫描流程,扫描结束后就会停止,不会主动重复触发测距逻辑。
下面给你两种可行的方案,实现每30秒自动检测一次的需求:
方案1:自定义定时器重复触发检测
你可以在Droid端的BeaconDetector类中添加一个定时器,在首次启动检测后,每隔30秒重新执行扫描逻辑。同时要注意处理好定时器的生命周期,避免内存泄漏。
修改后的BeaconDetector.cs示例代码:
private System.Timers.Timer _detectionTimer; private bool _isDetecting; // 标记是否正在检测,防止重复触发 public void DetectAvailableBeacons() { if (_isDetecting) return; _monitorNotifier = new MonitorNotifier(); _rangeNotifier = new RangeNotifier(); _tagRegion = new Region("NewRegion", null, null, null); _rangeNotifier.DidRangeBeaconsInRegionComplete += RangingBeaconsInRegionComplete; // 初始化定时器,间隔30秒 _detectionTimer = new System.Timers.Timer(30000); _detectionTimer.Elapsed += (sender, e) => RunBeaconScan(); _detectionTimer.AutoReset = true; // 设置自动重复触发 // 首次检测立即执行 RunBeaconScan(); _isDetecting = true; } private void RunBeaconScan() { // 确保在UI线程操作(如果需要更新UI的话) Activity.RunOnUiThread(() => { // 先解绑再重新绑定,触发新一轮扫描 _beaconManager.Unbind(this); _beaconManager.Bind(this); }); } // 提供停止检测的方法,在页面销毁或不需要时调用 public void StopBeaconDetection() { _isDetecting = false; _detectionTimer?.Stop(); _detectionTimer?.Dispose(); _beaconManager.Unbind(this); }
对应的按钮点击事件可以优化为支持启停切换:
private IBeaconLocator _beaconDetection; public void Button_Clicked(object sender, EventArgs e) { _beaconDetection = DependencyService.Get<IBeaconLocator>(); if (_beaconDetection is BeaconDetector detector) { if (!detector.IsDetecting) { detector.DetectAvailableBeacons(); } else { detector.StopBeaconDetection(); } } }
方案2:利用BeaconManager内置扫描周期配置
Android Beacon Library本身支持配置扫描的周期和间隔,你可以直接通过库的API设置,让它自动重复扫描,不需要自己维护定时器,更符合库的设计逻辑。
修改后的DetectAvailableBeacons()方法示例:
public void DetectAvailableBeacons() { _beaconManager = BeaconManager.GetInstanceForApplication(Application.Context); // 配置扫描参数:扫描持续1秒,两次扫描间隔29秒,总周期30秒 _beaconManager.SetForegroundScanPeriod(1000); // 单次扫描持续时长(毫秒) _beaconManager.SetForegroundBetweenScanPeriod(29000); // 扫描间隔时长(毫秒) _monitorNotifier = new MonitorNotifier(); _rangeNotifier = new RangeNotifier(); _tagRegion = new Region("NewRegion", null, null, null); _rangeNotifier.DidRangeBeaconsInRegionComplete += RangingBeaconsInRegionComplete; _beaconManager.Bind(this); }
这种方式下,BeaconManager会按照你设置的周期自动重复执行扫描,DidRangeBeaconsInRegionComplete会在每次扫描完成后触发。如果需要后台也保持扫描,还需要额外配置后台扫描参数和申请对应权限(Android 10+需要ACCESS_BACKGROUND_LOCATION权限)。
额外注意事项
- 无论用哪种方案,都要记得在页面销毁或不再需要检测时,调用
_beaconManager.Unbind(this)解除绑定,释放资源,避免内存泄漏。 - 如果需要在后台长期运行,要注意Android系统的后台限制,可能需要优化电池使用策略或者申请特殊权限。
- 在
RangingBeaconsInRegionComplete方法中处理扫描结果时,要注意线程安全,更新UI的操作必须切换到UI线程执行。
内容的提问来源于stack exchange,提问作者ExpertGenie
相关产品推荐
相关产品推荐

