Flutter地理围栏功能插件easy_geofencing的使用

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

Flutter地理围栏功能插件easy_geofencing的使用

easy_geofencing 是一个用于Flutter应用程序(Android和iOS)的地理围栏插件,它提供了地理围栏的功能。这个插件完全用纯Dart语言编写。

特性

  • 根据位置变化触发地理围栏状态[初始化、进入、退出]。
  • 获取连续的地理围栏状态更新。
  • 优化的Dart代码。
  • 对电池友好的Dart包。

使用方法

要将easy_geofencing添加到你的Flutter应用中,请阅读安装说明。以下是确保easy_geofencing在Android和iOS上正常工作的具体配置。

对于Android

AndroidX

easy_geofencing插件需要AndroidX版本的Android支持库。这意味着你需要确保你的Android项目支持AndroidX。详细的指令可以在这里找到:AndroidX兼容性

简短版是:

  1. 在你的gradle.properties文件中添加以下内容:

    android.useAndroidX=true
    android.enableJetifier=true
    
  2. 确保你在android/app/build.gradle文件中设置compileSdkVersion为30:

    android {
      compileSdkVersion 30
    
      ...
    }
    
  3. 确保你将所有的android.依赖替换为其AndroidX对应物(完整的列表可以在这里找到)。

权限

在Android上,你需要在你的AndroidManifest.xml文件中添加ACCESS_COARSE_LOCATIONACCESS_FINE_LOCATION权限。打开AndroidManifest.xml文件(位于android/app/src/main),并添加以下一行作为<manifest>标签的直接子元素(如果你同时配置了这两个权限,则会使用ACCESS_FINE_LOCATION):

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

从Android 10开始,如果你想在应用运行在后台时继续接收更新,还需要添加ACCESS_BACKGROUND_LOCATION权限(除了ACCESS_COARSE_LOCATIONACCESS_FINE_LOCATION权限之外):

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

对于iOS

在iOS上,你需要向你的Info.plist文件(位于ios/Runner)中添加以下条目以访问设备的位置。只需打开你的Info.plist文件并添加以下内容:

<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location when open.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs access to location when in the background.</string>

如果你想在应用处于后台时接收更新,还需要在XCode项目中添加Background Modes能力(Project > Signing and Capabilities > "+ Capability"按钮),并选择Location Updates。请注意,当提交应用到AppStore时,你需要详细解释为什么你的应用需要此功能。如果Apple不满意你的解释,你的应用可能会被拒绝。

API

启动Easy Geofencing服务

首先,你需要启动地理围栏服务,并传递以下参数:

  • pointedLatitude: 地理围栏区域中心的纬度
  • pointedLongitude: 地理围栏区域中心的经度
  • radiusMeter: 地理围栏区域的半径(米)
  • eventPeriodInSeconds: 地理围栏状态流周期(秒)
import 'package:easy_geofencing/easy_geofencing.dart';

EasyGeofencing.startGeofenceService(
    pointedLatitude: "34.2165157",
    pointedLongitude: "71.9437819",
    radiusMeter: "250.0",
    eventPeriodInSeconds: 5
);

获取地理围栏状态流

为了获取位置变化时的地理围栏状态更新,你需要订阅getGeofenceStream来监听当前位置更新的地理围栏状态流。

import 'package:easy_geofencing/easy_geofencing.dart';

StreamSubscription<GeofenceStatus> geofenceStatusStream = EasyGeofencing.getGeofenceStream().listen(
  (GeofenceStatus status) {
    print(status.toString());
});

停止地理围栏服务

要停止地理围栏服务,你需要指定:

import 'package:easy_geofencing/easy_geofencing.dart';

EasyGeofencing.stopGeofenceService();

同时,停止地理围栏状态流订阅监听器,例如geofenceStatusStream

geofenceStatusStream.cancel();

示例Demo

下面是一个完整的示例应用,演示如何使用easy_geofencing插件。

import 'dart:async';
import 'package:easy_geofencing/easy_geofencing.dart';
import 'package:easy_geofencing/enums/geofence_status.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Easy Geofencing',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Easy Geofencing'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, this.title}) : super(key: key);

  final String? title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  TextEditingController latitudeController = TextEditingController();
  TextEditingController longitudeController = TextEditingController();
  TextEditingController radiusController = TextEditingController();
  StreamSubscription<GeofenceStatus>? geofenceStatusStream;
  String geofenceStatus = '';
  bool isReady = false;
  Position? position;

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

  Future<void> getCurrentPosition() async {
    position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
    print("LOCATION => ${position!.toJson()}");
    isReady = (position != null) ? true : false;
  }

  setLocation() async {
    await getCurrentPosition();
    latitudeController.text = position!.latitude.toString();
    longitudeController.text = position!.longitude.toString();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title!),
        actions: [
          IconButton(
            icon: Icon(Icons.my_location),
            onPressed: () {
              if (isReady) {
                setState(() {
                  setLocation();
                });
              }
            },
          ),
        ],
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(10.0),
        child: Column(
          children: <Widget>[
            TextField(
              controller: latitudeController,
              decoration: InputDecoration(border: InputBorder.none, hintText: 'Enter pointed latitude'),
            ),
            TextField(
              controller: longitudeController,
              decoration: InputDecoration(border: InputBorder.none, hintText: 'Enter pointed longitude'),
            ),
            TextField(
              controller: radiusController,
              decoration: InputDecoration(border: InputBorder.none, hintText: 'Enter radius in meter'),
            ),
            SizedBox(height: 60),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                ElevatedButton(
                  child: Text("Start"),
                  onPressed: () {
                    print("starting geoFencing Service");
                    EasyGeofencing.startGeofenceService(
                        pointedLatitude: latitudeController.text,
                        pointedLongitude: longitudeController.text,
                        radiusMeter: radiusController.text,
                        eventPeriodInSeconds: 5);
                    if (geofenceStatusStream == null) {
                      geofenceStatusStream = EasyGeofencing.getGeofenceStream()?.listen((GeofenceStatus status) {
                        print(status.toString());
                        setState(() {
                          geofenceStatus = status.toString();
                        });
                      });
                    }
                  },
                ),
                SizedBox(width: 10.0),
                ElevatedButton(
                  child: Text("Stop"),
                  onPressed: () {
                    print("stop");
                    EasyGeofencing.stopGeofenceService();
                    geofenceStatusStream?.cancel();
                  },
                ),
              ],
            ),
            SizedBox(height: 100),
            Text(
              "Geofence Status: \n\n\n" + geofenceStatus,
              textAlign: TextAlign.center,
              style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
            ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    latitudeController.dispose();
    longitudeController.dispose();
    radiusController.dispose();
    super.dispose();
  }
}

这个示例应用展示了如何启动和停止地理围栏服务,并监听地理围栏状态的变化。


更多关于Flutter地理围栏功能插件easy_geofencing的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter地理围栏功能插件easy_geofencing的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter应用中使用easy_geofencing插件来实现地理围栏功能的代码示例。

首先,你需要在你的Flutter项目中添加easy_geofencing依赖。在你的pubspec.yaml文件中添加以下依赖项:

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

然后运行flutter pub get来获取依赖。

接下来,你需要在你的AndroidManifest.xml中添加必要的权限,以便应用能够访问位置信息:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.yourapp">

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />

    <application
        ... >
        <!-- 你的其他配置 -->
    </application>
</manifest>

然后,在你的Flutter代码中,你可以这样使用easy_geofencing插件:

import 'package:flutter/material.dart';
import 'package:easy_geofencing/easy_geofencing.dart';

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

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

class _MyAppState extends State<MyApp> {
  late EasyGeofencing _easyGeofencing;
  late StreamSubscription<GeofencingEvent> _geofencingEventSubscription;

  @override
  void initState() {
    super.initState();
    
    _easyGeofencing = EasyGeofencing();

    // 请求权限
    _easyGeofencing.requestPermissions().then((isGranted) {
      if (isGranted) {
        // 初始化地理围栏
        _initializeGeofencing();
      } else {
        // 处理权限被拒绝的情况
        print("Location permissions denied");
      }
    });
  }

  void _initializeGeofencing() async {
    // 创建一个地理围栏
    GeofencingRegion region = GeofencingRegion(
      identifier: "my_geofence",
      latitude: 37.7853889,
      longitude: -122.4056973,
      radius: 100.0, // 半径为100米
    );

    // 添加地理围栏
    await _easyGeofencing.addGeofence(region);

    // 监听地理围栏事件
    _geofencingEventSubscription = _easyGeofencing.geofencingEvents.listen((event) {
      if (event.geofenceIdentifier == "my_geofence") {
        if (event.action == GeofenceAction.ENTER) {
          print("Entered the geofence");
        } else if (event.action == GeofenceAction.EXIT) {
          print("Exited the geofence");
        } else if (event.action == GeofenceAction.DWELL) {
          print("Dwelled inside the geofence");
        }
      }
    });
  }

  @override
  void dispose() {
    // 取消订阅
    _geofencingEventSubscription.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Geofencing Example'),
        ),
        body: Center(
          child: Text('Check console for geofencing events'),
        ),
      ),
    );
  }
}

在这个示例中,我们完成了以下步骤:

  1. pubspec.yaml中添加easy_geofencing依赖。
  2. AndroidManifest.xml中添加必要的权限。
  3. 在Flutter代码中请求位置权限。
  4. 初始化并添加一个地理围栏。
  5. 监听地理围栏事件,并在控制台打印事件信息。

确保你已经替换了GeofencingRegion中的经纬度和半径为你实际需要的值。这个示例展示了如何设置和监听一个基本的地理围栏,你可以根据需要进行扩展和自定义。

回到顶部