Flutter后台定位插件advanced_background_locator的使用

Flutter后台定位插件advanced_background_locator的使用

advanced_background_locator 是一个用于高级后台位置跟踪的 Flutter 插件。此包提供了在应用在后台运行时跟踪用户位置的功能。

功能

  • 在后台跟踪用户位置。
  • 可自定义的通知和位置更新设置。
  • 支持不同的位置客户端。

安装

要使用此包,请在 pubspec.yaml 文件中添加 advanced_background_locator 作为依赖项:

dependencies:
  advanced_background_locator: ^0.0.3

运行 flutter pub get 来安装包。

使用

设置

1. 配置 AndroidManifest.xml

在您的 AndroidManifest.xml 文件中添加以下权限:

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

确保还添加了所需的 servicereceiver 声明。

2. 初始化插件

在您的 Flutter 应用中初始化插件。您可以在主入口文件(main.dartApplication.kt)中执行此操作。

import 'package:advanced_background_locator/advanced_background_locator.dart';

void main() {
  AdvancedBackgroundLocator.initialize();
  runApp(MyApp());
}

配置

通过 PreferencesManager 类配置插件:

import 'package:advanced_background_locator/advanced_background_locator.dart';

void configureSettings() {
  final settings = {
    'channelName': '您的通道名称',
    'channelTitle': '您的通道标题',
    'notificationMessage': '您的通知消息',
    // 其他设置
  };

  PreferencesManager.saveSettings(context, settings);
}

开始跟踪

使用以下方法开始跟踪位置:

import 'package:advanced_background_locator/advanced_background_locator.dart';

void startLocationTracking() {
  AdvancedBackgroundLocator.startTracking();
}

停止跟踪

当不再需要时停止位置跟踪:

import 'package:advanced_background_locator/advanced_background_locator.dart';

void stopLocationTracking() {
  AdvancedBackgroundLocator.stopTracking();
}

示例

以下是一个使用此包的完整示例代码:

import 'dart:async';
import 'dart:isolate';
import 'dart:ui';
import 'package:advanced_background_locator/advanced_background_locator.dart';
import 'package:advanced_background_locator/location_dto.dart';
import 'package:advanced_background_locator/settings/android_settings.dart';
import 'package:advanced_background_locator/settings/ios_settings.dart';
import 'package:advanced_background_locator/settings/locator_settings.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart'; // 替换 location_permissions

void main() => runApp(const MyApp());

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final ReceivePort port = ReceivePort();
  String logStr = '';
  bool isRunning = false;
  LocationDto? lastLocation;

  [@override](/user/override)
  void initState() {
    super.initState();

    // 注销后台监听器的端口
    if (IsolateNameServer.lookupPortByName(LocationServiceRepository.isolateName) != null) {
      IsolateNameServer.removePortNameMapping(LocationServiceRepository.isolateName);
    }

    // 注册新的端口
    IsolateNameServer.registerPortWithName(port.sendPort, LocationServiceRepository.isolateName);

    // 监听端口数据
    port.listen((dynamic data) async {
      if (data != null) {
        debugPrint('Data: $data');
        await updateUI(data);
      }
    });

    initPlatformState();
  }

  Future<void> updateUI(dynamic data) async {
    final log = await FileManager.readLogFile();
    LocationDto? locationDto = (data != null) ? LocationDto.fromJson(data) : null;
    await _updateNotificationText(locationDto!);

    setState(() {
      if (data != null) {
        lastLocation = locationDto;
      }
      logStr = log;
    });
  }

  Future<void> _updateNotificationText(LocationDto data) async {
    await AdvancedBackgroundLocator.updateNotificationText(
      title: "新位置已获取",
      msg: "${DateTime.now()}",
      bigMsg: "${data.latitude}, ${data.longitude}",
    );
  }

  Future<void> initPlatformState() async {
    await AdvancedBackgroundLocator.initialize();
    logStr = await FileManager.readLogFile();
    final isRunningResp = await AdvancedBackgroundLocator.isServiceRunning();
    setState(() {
      isRunning = isRunningResp;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter 后台定位器'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(22),
          child: SingleChildScrollView(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                ElevatedButton(
                  onPressed: _onStart,
                  child: const Text('开始'),
                ),
                ElevatedButton(
                  onPressed: onStop,
                  child: const Text('停止'),
                ),
                ElevatedButton(
                  onPressed: () {
                    FileManager.clearLogFile();
                    setState(() {
                      logStr = '';
                    });
                  },
                  child: const Text('清除日志文件'),
                ),
                Text("状态: ${isRunning ? '运行中' : '已停止'}${lastLocation != null ? "\n最后位置: ${lastLocation!.latitude}, ${lastLocation!.longitude}" : ""}"),
                Text(logStr),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Future<void> onStop() async {
    await AdvancedBackgroundLocator.unRegisterLocationUpdate();
    final isRunningResp = await AdvancedBackgroundLocator.isServiceRunning();
    setState(() {
      isRunning = isRunningResp;
    });
  }

  Future<void> _onStart() async {
    if (await _checkLocationPermission()) {
      await _startLocator();
      final isRunningResp = await AdvancedBackgroundLocator.isServiceRunning();
      setState(() {
        isRunning = isRunningResp;
        lastLocation = null;
      });
    } else {
      // 权限被拒绝
    }
  }

  Future<bool> _checkLocationPermission() async {
    final status = await Permission.location.status;
    if (status.isGranted) {
      return true;
    }

    if (status.isDenied) {
      final result = await Permission.location.request();
      return result.isGranted;
    }

    return false;
  }

  Future<void> _startLocator() async {
    final data = {'countInit': 1};
    await AdvancedBackgroundLocator.registerLocationUpdate(
      LocationCallbackHandler.callback,
      initCallback: LocationCallbackHandler.initCallback,
      initDataCallback: data,
      disposeCallback: LocationCallbackHandler.disposeCallback,
      iosSettings: const IOSSettings(
        accuracy: LocationAccuracy.NAVIGATION,
        distanceFilter: 0,
        stopWithTerminate: true,
      ),
      autoStop: false,
      androidSettings: const AndroidSettings(
        accuracy: LocationAccuracy.NAVIGATION,
        interval: 5,
        distanceFilter: 0,
        client: LocationClient.google,
        androidNotificationSettings: AndroidNotificationSettings(
          notificationChannelName: '位置跟踪',
          notificationTitle: '开始位置跟踪',
          notificationMsg: '应用将在后台跟踪您的位置',
          notificationBigMsg: '为了保持您的位置更新,请启用后台位置访问',
          notificationIconColor: Colors.grey,
          notificationTapCallback: LocationCallbackHandler.notificationCallback,
        ),
      ),
    );
  }
}

更多关于Flutter后台定位插件advanced_background_locator的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter后台定位插件advanced_background_locator的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


advanced_background_locator 是一个 Flutter 插件,用于在后台持续获取设备的位置信息。这对于需要持续跟踪用户位置的应用(如健身应用、导航应用等)非常有用。由于 Android 和 iOS 对后台服务的管理方式不同,使用该插件时需要注意平台的差异。

安装插件

首先,在 pubspec.yaml 文件中添加 advanced_background_locator 依赖:

dependencies:
  flutter:
    sdk: flutter
  advanced_background_locator: ^2.0.0

然后运行 flutter pub get 安装插件。

配置插件

Android 配置

  1. 权限:在 AndroidManifest.xml 文件中添加以下权限:

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    
  2. 服务配置:在 AndroidManifest.xml 文件中注册后台服务:

    <service
        android:name="com.rekab.app.background_locator.LocatorService"
        android:foregroundServiceType="location" />
    
  3. ProGuard 配置:如果你启用了 ProGuard,需要在 proguard-rules.pro 文件中添加以下规则:

    -keep class com.rekab.app.background_locator.** { *; }
    

iOS 配置

  1. 权限:在 Info.plist 文件中添加以下权限描述:

    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>我们需要您的位置信息来提供更好的服务。</string>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>我们需要您的位置信息来提供更好的服务。</string>
    <key>UIBackgroundModes</key>
    <array>
        <string>location</string>
    </array>
    
  2. 后台模式:确保在 Xcode 中启用了 Background Modes 并勾选了 Location updates

使用插件

  1. 初始化插件:在 main.dart 文件中初始化插件:

    import 'package:advanced_background_locator/advanced_background_locator.dart';
    
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      
      await AdvancedBackgroundLocator.initialize();
      
      runApp(MyApp());
    }
    
  2. 设置回调函数:定义一个回调函数来处理位置更新:

    static void callback(LocationDto locationDto) async {
      print('Location: ${locationDto.latitude}, ${locationDto.longitude}');
      // 在这里处理位置信息
    }
    
  3. 启动后台定位服务

    await AdvancedBackgroundLocator.registerLocationUpdate(
      callback,
      androidNotificationCallback: androidNotificationCallback,
      iosNotificationCallback: iosNotificationCallback,
      autoStop: false,
      interval: 5000, // 更新间隔时间(毫秒)
      accuracy: LocationAccuracy.NAVIGATION,
    );
    
  4. 停止后台定位服务

    await AdvancedBackgroundLocator.unRegisterLocationUpdate();
    
  5. 处理后台通知(可选):你可以在后台定位时显示通知,以提高用户体验。

    static void androidNotificationCallback() {
      // 处理 Android 通知
    }
    
    static void iosNotificationCallback() {
      // 处理 iOS 通知
    }
回到顶部