Flutter地理围栏(Geofencing)实现求助:需支持后台运行与开机自启
Flutter地理围栏实现指南(适配Dart3+后台运行)
推荐包:flutter_background_geolocation
这款插件是当前Flutter生态中最可靠的地理围栏解决方案,完全兼容Dart3,核心优势:
- 支持后台持续监听地理围栏事件
- 设备重启后自动恢复服务
- 内置本地通知推送能力
- 跨平台(Android/iOS)适配完善
分步实现
1. 添加依赖
在pubspec.yaml中引入所需包:
dependencies: flutter_background_geolocation: ^4.12.0 flutter_local_notifications: ^16.1.0 # 用于触发本地通知 permission_handler: ^10.2.0 # 简化权限申请流程
执行flutter pub get完成安装。
2. 平台权限配置
Android(AndroidManifest.xml)
添加必要权限与服务声明:
<!-- 定位权限 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <!-- 前台服务与重启恢复 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <!-- 服务与广播接收器 --> <service android:name="com.transistorsoft.flutter.backgroundgeolocation.FLTDartBackgroundGeolocationService" android:foregroundServiceType="location" /> <receiver android:name="com.transistorsoft.flutter.backgroundgeolocation.FLTBackgroundGeolocationBootReceiver" android:enabled="true" android:exported="false"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.MY_PACKAGE_REPLACED" /> </intent-filter> </receiver>
iOS(Info.plist)
添加定位权限描述与后台模式:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key> <string>需要持续定位以监听地理围栏事件</string> <key>NSLocationWhenInUseUsageDescription</key> <string>需要定位以监听地理围栏事件</string> <key>NSLocationAlwaysUsageDescription</key> <string>需要后台定位以监听地理围栏事件</string> <key>UIBackgroundModes</key> <array> <string>location</string> </array>
3. 核心代码实现
初始化服务与配置
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:permission_handler/permission_handler.dart'; FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin(); void initGeofencing() async { // 申请必要权限 await Permission.locationAlways.request(); await Permission.notification.request(); // 初始化本地通知 const AndroidInitializationSettings initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); const InitializationSettings initSettings = InitializationSettings(android: initAndroid); await _notificationsPlugin.initialize(initSettings); // 配置后台地理定位服务 await bg.BackgroundGeolocation.ready(bg.Config( desiredAccuracy: bg.Config.DESIRED_ACCURACY_HIGH, distanceFilter: 10, // 位置变化超过10米触发更新 stopOnTerminate: false, // 应用退出后继续运行 startOnBoot: true, // 设备重启自动启动服务 enableHeadless: true, // 支持无头模式(应用完全退出仍可运行) notificationTitle: "地理围栏服务", notificationText: "正在监听位置变化", foregroundService: true, // Android前台服务,避免被系统杀死 )); // 监听地理围栏事件 bg.BackgroundGeolocation.onGeofence((bg.GeofenceEvent event) { String eventType; switch(event.action) { case bg.GeofenceEvent.ENTER: eventType = "进入"; break; case bg.GeofenceEvent.EXIT: eventType = "离开"; break; case bg.GeofenceEvent.DWELL: eventType = "停留"; break; default: eventType = "未知"; } // 触发通知或执行自定义操作 _showNotification("地理围栏事件", "您已${eventType}区域: ${event.geofence.identifier}"); // 此处可添加上传服务器、更新本地数据库等逻辑 }); // 添加预定义地理围栏 await _addGeofences(); } // 添加地理围栏 Future<void> _addGeofences() async { List<bg.Geofence> geofences = [ bg.Geofence( identifier: "公司", radius: 50.0, // 围栏半径50米 latitude: 31.2304, // 替换为目标纬度 longitude: 121.4737, // 替换为目标经度 notifyOnEntry: true, notifyOnExit: true, notifyOnDwell: false, loiteringDelay: 30000 // 停留30秒触发DWELL事件(可选) ), // 可添加更多地理围栏 ]; await bg.BackgroundGeolocation.addGeofences(geofences); } // 显示本地通知 void _showNotification(String title, String body) async { const AndroidNotificationDetails androidDetails = AndroidNotificationDetails( 'geofence_channel', '地理围栏通知', channelDescription: '地理围栏事件提醒', importance: Importance.max, priority: Priority.high, ); const NotificationDetails notificationDetails = NotificationDetails(android: androidDetails); await _notificationsPlugin.show( 0, title, body, notificationDetails, payload: 'geofence_event', ); }
启动服务
在页面initState中调用初始化方法:
@override void initState() { super.initState(); initGeofencing(); // 启动后台定位服务 bg.BackgroundGeolocation.start(); }
关键概念解析
- 地理围栏事件类型:
ENTER:用户进入围栏区域时触发EXIT:用户离开围栏区域时触发DWELL:用户在围栏内停留超过设定时长时触发
- 后台运行机制:
- Android:通过前台服务避免被系统回收,需申请
ACCESS_BACKGROUND_LOCATION权限 - iOS:依赖
Always定位权限,开启location后台模式
- Android:通过前台服务避免被系统回收,需申请
- 设备重启恢复:
- Android:通过
RECEIVE_BOOT_COMPLETED广播接收器自动重启服务 - iOS:系统自动恢复后台定位服务(需用户授权Always权限)
- Android:通过
注意事项
- Android 12+需单独申请
POST_NOTIFICATIONS权限 - iOS需在开发者后台开启
Background Modes中的Location Updates - 测试后台功能时,需将应用退到后台或锁屏,避免被系统优化杀死
内容的提问来源于stack exchange,提问作者Rohan Ahmed
相关产品推荐
相关产品推荐

