Flutter蓝牙信标监测插件beacon_monitoring的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

Flutter蓝牙信标监测插件beacon_monitoring的使用

安装

pubspec.yaml 文件中添加 beacon_monitoring 插件作为依赖:

dependencies:
  beacon_monitoring: latest

iOS设置

1. 更新 Info.plist

对于早于iOS 13的部署目标,需要在应用的信息属性列表文件中添加 NSBluetoothAlwaysUsageDescriptionNSBluetoothPeripheralUsageDescription。运行较旧版本iOS的设备依赖于 NSBluetoothPeripheralUsageDescription,而运行较新版本iOS的设备依赖于 NSBluetoothAlwaysUsageDescription

打开 Info.plist 文件并添加以下键值对(以源代码形式):

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>应用程序始终需要访问您的位置信息的原因。</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>应用程序在前台运行时请求访问您的位置信息的原因。</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>应用程序需要访问蓝牙的原因。</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>应用程序请求连接到蓝牙外设的原因。</string>

2. 更新能力

  1. 打开 Signing & Capabilities
  2. 点击 + Capability
  3. 添加 Background Modes 能力
  4. 选择 Location updates

3. 更新 AppDelegate

  1. 打开 AppDelegate.swift
  2. 导入 beacon_monitoring
  3. 添加静态方法以注册插件
import Flutter
import beacon_monitoring

static func registerPlugins(with registry: FlutterPluginRegistry) {
  GeneratedPluginRegistrant.register(with: registry)
}
  1. 注册你的 AppDelegate 为注册器
AppDelegate.registerPlugins(with: self)
  1. 设置 BeaconMonitoringPlugin 的注册回调
BeaconMonitoringPlugin.setPluginRegistrantCallback { registry in
  AppDelegate.registerPlugins(with: registry)
}

因此,AppDelegate.swift 应该看起来像这样:

import UIKit
import Flutter
import beacon_monitoring

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {

    // MARK: - UIApplicationDelegate Methods
    override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // ...
        setupAppDelegateRegistry()
        setupBeaconMonitoringPluginCallback()
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    // MARK: - Register Plugins
    static func registerPlugins(with registry: FlutterPluginRegistry) {
        GeneratedPluginRegistrant.register(with: registry)
    }

    // MARK: - Private Methods
    private func setupAppDelegateRegistry() {
        AppDelegate.registerPlugins(with: self)
    }
    private func setupBeaconMonitoringPluginCallback() {
        BeaconMonitoringPlugin.setPluginRegistrantCallback { registry in
            AppDelegate.registerPlugins(with: registry)
        }
    }
}

使用说明

beacon_monitoring 插件可以在应用程序处于前台和后台模式下监控信标。

前台监控

我们通过拦截由流产生的事件来实现前台监控,如以下代码所示:

monitoring().listen((event) {
    print("Monitoring stream received: $event");  
});

后台监控

对于后台监控,我们需要实现一个回调方法,并将其作为参数传递给 startBackgroundMonitoring 方法:

void backgroundMonitoringCallback(MonitoringResult result) {
    print('Background monitoring received: $result');
}

startBackgroundMonitoring(backgroundMonitoringCallback);

如何使用

首先,注册被监控的区域。区域由信标的标识符及其ID(ID可选)表示。

假设我们有两个iBeacon:

iBeacon one: UUID: 400CD186-C779-024B-2F19-89DCF74987E9
iBeacon two: UUID: D66BA202-6589-677F-C735-17E3856F065C

在插件中注册这些信标可以按以下方式完成:

import 'package:beacon_monitoring/beacon_monitoring.dart';

void activateBeacon() async{
    // 定义我们的区域
    Region regionOne = Region(
        identifier: '400CD186-C779-024B-2F19-89DCF74987E9');
    Region regionTwo = Region(
        identifier: 'D66BA202-6589-677F-C735-17E3856F065C');
    
    List<Region> regions = [regionOne, regionTwo];
    
    // 注册定义的区域
    await registerAllRegions(regions);
...
}

现在,我们需要实现处理所有来自信标事件的方法。回调事件处理器必须是一个静态方法或函数(不能是匿名函数或对象方法)。

然后调用 startBackgroundMonitoring 方法,其中我们传递我们的回调:

import 'package:beacon_monitoring/beacon_monitoring.dart';

startBackgroundMonitoring(handleEventCallback);

整个示例代码如下:

import 'package:beacon_monitoring/beacon_monitoring.dart';

void activateBeacon() async{
    // 定义我们的区域
    Region regionOne = Region(
        identifier: '400CD186-C779-024B-2F19-89DCF74987E9');
    Region regionTwo = Region(
        identifier: 'D66BA202-6589-677F-C735-17E3856F065C');
    
    List<Region> regions = [regionOne, regionTwo];
    
    // 注册定义的区域
    await registerAllRegions(regions);
    
    // 定义一个方法来处理信标的事件
    startBackgroundMonitoring(handleEventCallback);
}

// 信标事件由这个方法处理
void handleEventCallback(MonitoringResult result) {
    print('$result');
}

从现在开始,每个与注册信标相关的事件都将由 handleEventCallback 方法处理。如果我们在信标的范围内,handleEventCallback 方法将被调用,并带有 MonitoringResult 中的数据。

额外信息

为了能够监控信标,蓝牙和位置服务都需要开启并且可供应用程序使用。

插件提供了处理请求所需权限的方法。

可以通过 isBluetoothEnabled() 方法检查蓝牙是否启用,并使用 openBluetoothSettings() 方法为Android设备和 openApplicationSettings() 方法为iOS设备开启蓝牙。

位置服务可以通过 isLocationEnabled() 方法检查是否启用,并使用 openLocationSettings() 方法为Android设备和 openApplicationSettings() 方法为iOS设备开启位置服务。

类似地,请求位置权限的方法也包含在插件中。插件提供了 checkLocationPermission()requestLocationPermission() 函数。

例如:

import 'package:beacon_monitoring/beacon_monitoring.dart';
import 'dart:io' show Platform;

final bluetoothEnabled = await isBluetoothEnabled();
final locationEnabled = await isLocationEnabled();
final locationPermission = await checkLocationPermission();

/// 如果你在后台进程中,应该检查 `LocationPermission.always` 权限而不是 `LocationPermissions.whileInUse`。
if (locationPermission != LocationPermission.whileInUse) {
    await requestLocationPermission();
}

if (Platform.isAndroid) {
    if(!bluetoothEnabled) openBluetoothSettings();
    if(!locationEnabled) openLocationSettings();
} else if (Platform.isIOS) {
    if(!bluetoothEnabled || !locationEnabled) openApplicationSettings();
}

更多关于Flutter蓝牙信标监测插件beacon_monitoring的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter蓝牙信标监测插件beacon_monitoring的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用beacon_monitoring插件来监测蓝牙信标的示例代码。这个插件允许你扫描并监听附近的蓝牙信标。

首先,你需要在你的pubspec.yaml文件中添加beacon_monitoring依赖:

dependencies:
  flutter:
    sdk: flutter
  beacon_monitoring: ^x.y.z  # 请替换为最新版本号

然后运行flutter pub get来安装依赖。

接下来,在你的Flutter应用中,你需要请求必要的权限(例如位置权限),并初始化beacon_monitoring插件。以下是一个完整的示例代码:

import 'package:flutter/material.dart';
import 'package:beacon_monitoring/beacon_monitoring.dart';
import 'package:permission_handler/permission_handler.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  BeaconMonitoring? _beaconMonitoring;
  List<Beacon> _beacons = [];

  @override
  void initState() {
    super.initState();
    _initializeBeaconMonitoring();
  }

  Future<void> _initializeBeaconMonitoring() async {
    // 请求位置权限
    var status = await Permission.locationWhenInUse.status;
    if (!status.isGranted) {
      var result = await Permission.locationWhenInUse.request();
      if (!result.isGranted) {
        return;
      }
    }

    // 初始化beacon_monitoring插件
    _beaconMonitoring = BeaconMonitoring();

    // 设置扫描区域(可选)
    // BeaconRegion region = BeaconRegion(
    //   identifier: 'myRegion',
    //   uuid: 'your-beacon-uuid',
    //   major: 1,
    //   minor: 1,
    // );
    // await _beaconMonitoring!.startMonitoringForRegion(region);

    // 开始扫描所有信标
    _beaconMonitoring!.startRangingBeaconsInRegion(BeaconRegion.allIdentifiers());

    // 监听扫描结果
    _beaconMonitoring!.rangingBeaconsInRegionStream!.listen((beacons) {
      setState(() {
        _beacons = beacons;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Beacon Monitoring'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text('Scanned Beacons:'),
              SizedBox(height: 20),
              Expanded(
                child: ListView.builder(
                  shrinkWrap: true,
                  itemCount: _beacons.length,
                  itemBuilder: (context, index) {
                    Beacon beacon = _beacons[index];
                    return Card(
                      child: ListTile(
                        title: Text('UUID: ${beacon.uuid}'),
                        subtitle: Text('Major: ${beacon.major}, Minor: ${beacon.minor}, Distance: ${beacon.proximity.toString()}'),
                      ),
                    );
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _beaconMonitoring?.stopRangingBeaconsInRegion(BeaconRegion.allIdentifiers());
    _beaconMonitoring = null;
    super.dispose();
  }
}

注意事项:

  1. 权限处理:在iOS和Android上,蓝牙扫描通常需要位置权限。在示例代码中,我们使用了permission_handler插件来处理权限请求。
  2. 依赖项:确保你已经添加了permission_handler依赖,并在ios/Podfile中启用了Swift支持(如果适用)。
  3. 后台扫描:在iOS上,后台扫描蓝牙信标需要配置Info.plistBackground Modes。在Android上,你可能需要在AndroidManifest.xml中添加必要的权限和服务声明。
  4. 区域监控:示例代码中注释了区域监控的部分。如果你只对特定区域的信标感兴趣,可以取消注释并配置相应的BeaconRegion

这个示例代码提供了一个基本框架,你可以根据实际需求进行扩展和修改。

回到顶部