Flutter项目高德地图后台持续定位功能的实现(iOS)

06/10/2022 12:10 下午 posted in  Flutter

首先高德本身就支持后台持续定位:实例文档.对于Flutter项目高德也提供了框架支持:文档

pubspec.yaml如下:

dependencies:
  flutter:
    sdk: flutter
  # 权限相关
  permission_handler: ^5.1.0+2
  # 定位功能
  amap_location_fluttify: ^0.20.0

实现逻辑我们以iOS项目为例:

iOS项目工程(ios/Runner)配置:

添加定位权限申请配置

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>申请Always权限以便应用在前台和后台(suspend 或 terminated)都可以获取到更新的位置数据</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>需要您的同意才能始终访问位置</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>需要您的同意,才能在使用期间访问位置</string>

以上权限会根据iOS 系统版本的不同有所不同

后台任务(Background Modes)模式配置

<key>UIBackgroundModes</key>
<array>
	<string>location</string>
	<string>remote-notification</string>
</array>

选择Location updates选项

Flutter项目实例

对于Flutter中的使用方法,具体实例如下:

  1. 首先要在main函数中进行高德地图组件的注册
  2. 视图中在调用定位之前必须进行权限申请
  3. 开启后台任务功能
  4. 执行持续定位

代码 main.dart:

import 'package:amap_location_fluttify/amap_location_fluttify.dart';

void main() {
  runApp(const MyApp());
  # 注册高德地图组件
  AmapLocation.instance.init(iosKey: 'xxxxxx');
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: LocationPage(),
    );
  }
}

location_page.dart:

import 'package:amap_location_fluttify/amap_location_fluttify.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:permission_handler/permission_handler.dart';

class LocationPage extends StatefulWidget {
  LocationPage({Key? key}) : super(key: key);

  _LocationPageState createState() => _LocationPageState();
}

class _LocationPageState extends State<LocationPage> {
  //获取数据
  // Map<String, Object> _locationResult;
  String _latitude = ""; //纬度
  String _longitude = ""; //经度

  @override
  void initState() {
    super.initState();
    /// 动态申请定位权限
    requestPermission();
  }

  @override
  void dispose() {
    super.dispose();
  }

  /// 动态申请定位权限
  void requestPermission() async {
    // 申请权限
    bool hasLocationPermission = await requestLocationPermission();
    if (hasLocationPermission) {
      print("定位权限申请通过");
    } else {
      print("定位权限申请不通过");
    }
  }

  ///  申请定位权限  授予定位权限返回true, 否则返回false
  Future<bool> requestLocationPermission() async {
    //获取当前的权限

    var status = await Permission.locationAlways.status;
    if (status == PermissionStatus.granted) {
      //已经授权
      return true;
    } else {
      //未授权则发起一次申请
      status = await Permission.location.request();
      if (status == PermissionStatus.granted) {
        return true;
      } else {
        return false;
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("地理定位演示"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            //  latitude: 36.570091461155336, longitude: 109.5080830206976
            //
            Text("纬度:${this._latitude}"),
            Text("经度:${this._longitude}"),
            SizedBox(height: 20),
            ElevatedButton(
              child: Text('开始定位'),
              onPressed: () {
                this._startTheLocation();
              },
            ),
          ],
        ),
      ),
    );
  }

  Future _startTheLocation() async {
    if (await Permission.location.request().isGranted) {
    
        # 开启后台持续定位功能
      await AmapLocation.instance.enableBackgroundLocation(
        10,
        BackgroundNotification(
          contentTitle: 'contentTitle',
          channelId: 'channelId',
          contentText: 'contentText',
          channelName: 'channelName',
        ),
      );
      
      # 监听持续定位
      AmapLocation.instance.listenLocation().listen((location) {
        setState(() {
          _latitude = location.latLng.latitude.toString();
          _longitude = location.latLng.longitude.toString();
          print("监听定位: {$_latitude, $_longitude}");
        });
      });
    } else {
      openAppSettings();
    }
  }

}

总结

关于后台持续定位对于高德来说核心函数只有2个:

开启后台任务

AmapLocation.instance.enableBackgroundLocation(id, notification)

执行持续定位:

AmapLocation.instance.listenLocation().listen((location) {
    // do someting
});