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

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:通过RECEIVE_BOOT_COMPLETED广播接收器自动重启服务
    • iOS:系统自动恢复后台定位服务(需用户授权Always权限)

注意事项

  • Android 12+需单独申请POST_NOTIFICATIONS权限
  • iOS需在开发者后台开启Background Modes中的Location Updates
  • 测试后台功能时,需将应用退到后台或锁屏,避免被系统优化杀死

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 03:52:47