Flutter 中集成高德定位获取地理位置

Flutter 中使用高德定位准备工作获取key

  1. 申请成为开发者
  2. 创建应用配置获取Key (参考教程演示)

Flutter 高德定位配置

官方文档:https://developer.amap.com/api/flutter/gettingstarted

https://pub.dev/packages/amap_flutter_location

  1. 配置安装依赖

    dependencies:
        amap_flutter_location: ^3.0.0
    
  1. 修改你的/app/build.gradle 文件配置签名文件以及配置implementation

    配置签名文件找到android /app/build.gradle 配置下面代码

    signingConfigs {
        release {//发布版本的签名配置
        storeFile file('jdshop.jks')
        keyAlias "仿京东商城"
        storePassword "123456"
        keyPassword "123456"
      }
      debug {//调试版本的签名配置
        storeFile file('jdshop.jks')
        keyAlias "仿京东商城"
        storePassword "123456"
        keyPassword "123456"
      }
    }
    buildTypes {
      release {
        // TODO: Add your own signing config for the release build.
        // Signing with the debug keys for now, so `flutter run --release` works.
        signingConfig signingConfigs.release
      }
      debug {
        // TODO: Add your own signing config for the release build.
        // Signing with the debug keys for now, so `flutter run --release` works.
        signingConfig signingConfigs.debug
      }
    }
    

    配置:implementation

    dependencies {
      implementation('com.amap.api:location:5.2.0')
      implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    }
    
  1. 修改你的android/app/src/main/AndroidManifest.xml

    增加权限

    <!--访问网络-->
    <uses-permission android:name="android.permission.INTERNET" />
    <!--粗略定位-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <!--精确定位-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <!--申请调用A-GPS 模块-->
    <uses-permissionandroid:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
    <!--用于获取运营商信息,用于支持提供运营商信息相关的接口-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!--用于访问wifi 网络信息,wifi 信息会用于进行网络定位-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <!--用于获取wifi 的获取权限,wifi 信息会用来进行网络定位-->
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <!--用于读取手机当前的状态-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <!--用于写入缓存数据到扩展存储卡-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    

    配置定位Service

    <application
    ......
    <!-- 配置定位Service -->
    <service android:name="com.amap.api.location.APSService"/>
    ......
    </application>
    

    注意:如果参考教程配置完毕提示下面错误

    ix this issue by adding the following to \android\app\build.gradle:
    android {
        compileSdkVersion 33
        ...
    }
    

    打开android\app\build.gradle 配置下面代码

    android {
      compileSdkVersion 33
      ...
    }
    

Flutter 高德定位源码

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:amap_flutter_location/amap_flutter_location.dart';
import 'package:amap_flutter_location/amap_location_option.dart';
import 'package:permission_handler/permission_handler.dart';
void main() {
  runApp(new MyApp());
}
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
  Map<String, Object> _locationResult;
  StreamSubscription<Map<String, Object>> _locationListener;
  AMapFlutterLocation _locationPlugin = new AMapFlutterLocation();
  @override
  void initState() {
    super.initState();
    //私权政策是否弹窗展示告知用户
    AMapFlutterLocation.updatePrivacyShow(true, true);
    // [hasAgree] 隐私权政策是否已经取得用户同意
    AMapFlutterLocation.updatePrivacyAgree(true);
    /// 动态申请定位权限
    requestPermission();
    ///设置Android 和iOS 的apiKey<br>
    ///
    /// 定位Flutter 插件提供了单独的设置ApiKey 的接口,
    /// 使用接口的优先级高于通过Native 配置ApiKey 的优先级(通过Api 接口配置后,
    ///通过Native 配置文件设置的key 将不生效),
    /// 使用时可根据实际情况决定使用哪种方式
    ///
    ///key 的申请请参考高德开放平台官网说明<br>
    ///
    ///Android:https://lbs.amap.com/api/android-location-sdk/guide/create-project/get-key
    ///iOS: https://lbs.amap.com/api/ios-location-sdk/guide/create-project/get-key
    AMapFlutterLocation.setApiKey(
      "a8879945e00xxxxxe427f4929cdc", "ios ApiKey");
    ///iOS 获取native 精度类型
    if (Platform.isIOS) {
      requestAccuracyAuthorization();
    }
    ///注册定位结果监听
    _locationListener = _locationPlugin
      .onLocationChanged()
      .listen((Map<String, Object> result) {
        setState(() {
          _locationResult = result;
        });
      });
  }
  @override
  void dispose() {
    super.dispose();
    ///移除定位监听
    if (null != _locationListener) {
      _locationListener.cancel();
    }
    ///销毁定位
    if (null != _locationPlugin) {
      _locationPlugin.destroy();
    }
  }
  ///设置定位参数
  void _setLocationOption() {
    if (null != _locationPlugin) {
      AMapLocationOption locationOption = new AMapLocationOption();
      ///是否单次定位
      locationOption.onceLocation = false;
      ///是否需要返回逆地理信息
      locationOption.needAddress = true;
      ///逆地理信息的语言类型
      locationOption.geoLanguage = GeoLanguage.DEFAULT;
      locationOption.desiredLocationAccuracyAuthorizationMode =
        AMapLocationAccuracyAuthorizationMode.ReduceAccuracy;
      locationOption.fullAccuracyPurposeKey = "AMapLocationScene";
      ///设置Android 端连续定位的定位间隔
      locationOption.locationInterval = 2000;
      ///设置Android 端的定位模式<br>
      ///可选值:<br>
      ///<li>[AMapLocationMode.Battery_Saving]</li>
      ///<li>[AMapLocationMode.Device_Sensors]</li>
      ///<li>[AMapLocationMode.Hight_Accuracy]</li>
      locationOption.locationMode = AMapLocationMode.Hight_Accuracy;
      ///设置iOS 端的定位最小更新距离<br>
      locationOption.distanceFilter = -1;
      ///设置iOS 端期望的定位精度
      /// 可选值:<br>
      /// <li>[DesiredAccuracy.Best] 最高精度</li>
      /// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度</li>
      /// <li>[DesiredAccuracy.NearestTenMeters] 10 米</li>
      /// <li>[DesiredAccuracy.Kilometer] 1000 米</li>
      /// <li>[DesiredAccuracy.ThreeKilometers] 3000 米</li>
      locationOption.desiredAccuracy = DesiredAccuracy.Best;
      ///设置iOS 端是否允许系统暂停定位
      locationOption.pausesLocationUpdatesAutomatically = false;
      ///将定位参数设置给定位插件
      _locationPlugin.setLocationOption(locationOption);
    }
  }
  ///开始定位
  void _startLocation() {
    if (null != _locationPlugin) {
      ///开始定位之前设置定位参数
      _setLocationOption();
      _locationPlugin.startLocation();
    }
  }
  ///停止定位
  void _stopLocation() {
    if (null != _locationPlugin) {
      _locationPlugin.stopLocation();
    }
  }
  Container _createButtonContainer() {
    return new Container(
      alignment: Alignment.center,
      child: new Row(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          new RaisedButton(
            onPressed: _startLocation,
            child: new Text('开始定位'),
            color: Colors.blue,
            textColor: Colors.white,
          ),
          new Container(width: 20.0),
          new RaisedButton(
            onPressed: _stopLocation,
            child: new Text('停止定位'),
            color: Colors.blue,
            textColor: Colors.white,
          )
        ],
      ));
  }
  Widget _resultWidget(key, value) {
    return new Container(
      child: new Row(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          new Container(
            alignment: Alignment.centerRight,
            width: 100.0,
            child: new Text('$key :'),
          ),
          new Container(width: 5.0),
          new Flexible(child: new Text('$value', softWrap: true)),
        ],
      ),
    );
  }
  @override
  Widget build(BuildContext context) {
    List<Widget> widgets = new List();
    widgets.add(_createButtonContainer());
    if (_locationResult != null) {
      _locationResult.forEach((key, value) {
        widgets.add(_resultWidget(key, value));
      });
    }
    return new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('AMap Location plugin example app'),
        ),
        body: new Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: widgets,
        ),
      ));
  }
  ///获取iOS native 的accuracyAuthorization 类型
  void requestAccuracyAuthorization() async {
    AMapAccuracyAuthorization currentAccuracyAuthorization =
      await _locationPlugin.getSystemAccuracyAuthorization();
    if (currentAccuracyAuthorization ==
        AMapAccuracyAuthorization.AMapAccuracyAuthorizationFullAccuracy) {
      print("精确定位类型");
    } else if (currentAccuracyAuthorization ==
               AMapAccuracyAuthorization.AMapAccuracyAuthorizationReducedAccuracy) {
      print("模糊定位类型");
    } else {
      print("未知定位类型");
    }
  }
  /// 动态申请定位权限
  void requestPermission() async {
    // 申请权限
    bool hasLocationPermission = await requestLocationPermission();
    if (hasLocationPermission) {
      print("定位权限申请通过");
    } else {
      print("定位权限申请不通过");
    }
  }
  /// 申请定位权限
  /// 授予定位权限返回true, 否则返回false
  Future<bool> requestLocationPermission() async {
    //获取当前的权限
    var status = await Permission.location.status;
    if (status == PermissionStatus.granted) {
      //已经授权
      return true;
    } else {
      //未授权则发起一次申请
      status = await Permission.location.request();
      if (status == PermissionStatus.granted) {
        return true;
      } else {
        return false;
      }
    }
  }
}

Flutter Ios 项目中配置定位权限

  1. https://lbs.amap.com/api/ios-location-sdk/guide/create-project/permission-description

  2. 配置权限

    <key>UIBackgroundModes</key>
    <array>
    <string>location</string>
    </array>
    <key>NSLocationDefaultAccuracyReduced</key>
    <true/>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>应用需要访问定位</string>
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>应用需要访问定位</string>
    <key>allowsBackgroundLocationUpdates</key>
    <string>应用需要访问后台定位</string>
    
  3. ios 配置permission_handler 权限申请

    在flutter 项目中集成了高德定位flutter SDK,在iOS 上运行第一次安装不会弹出定位请求弹窗。

    解决办法:

    参考:http://bbs.itying.com/topic/631987c16275cc0bec05aaa1

    在iOS 项目的Podfile 中, 替换一段内容, 然后根据情况进行开启, 定位为

    PERMISSION_LOCATION=1 如下:

    post_install do |installer|
      installer.pods_project.targets.each do |target|
          flutter_additional_ios_build_settings(target)
        end
    end
    替换为
    post_install do |installer|
        installer.pods_project.targets.each do |target|
            target.build_configurations.each do |config|
                flutter_additional_ios_build_settings(target)
          # You can enable the permissions needed here. For example to enable camera
          # permission, just remove the `#` character in front so it looks like this:
          #
          # ## dart: PermissionGroup.camera
          # 'PERMISSION_CAMERA=1'
          #
    # Preprocessor definitions can be found in:
    https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_h
    andler/ios/Classes/PermissionHandlerEnums.h
            config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
          '$(inherited)',
          ## dart: PermissionGroup.calendar
          # 'PERMISSION_EVENTS=1',
          ## dart: PermissionGroup.reminders
          # 'PERMISSION_REMINDERS=1',
          ## dart: PermissionGroup.contacts
          # 'PERMISSION_CONTACTS=1',
          ## dart: PermissionGroup.camera
          'PERMISSION_CAMERA=1',
          ## dart: PermissionGroup.microphone
          # 'PERMISSION_MICROPHONE=1',
          ## dart: PermissionGroup.speech
          # 'PERMISSION_SPEECH_RECOGNIZER=1',
          ## dart: PermissionGroup.photos
          'PERMISSION_PHOTOS=1',
          ## dart: [PermissionGroup.location, PermissionGroup.locationAlways,
          PermissionGroup.locationWhenInUse]
          'PERMISSION_LOCATION=1',
          ## dart: PermissionGroup.notification
          'PERMISSION_NOTIFICATIONS=1',
          ## dart: PermissionGroup.mediaLibrary
          # 'PERMISSION_MEDIA_LIBRARY=1',
          ## dart: PermissionGroup.sensors
          # 'PERMISSION_SENSORS=1',
          ## dart: PermissionGroup.bluetooth
          # 'PERMISSION_BLUETOOTH=1',
          ## dart: PermissionGroup.appTrackingTransparency
          # 'PERMISSION_APP_TRACKING_TRANSPARENCY=1',
          ## dart: PermissionGroup.criticalAlerts
          # 'PERMISSION_CRITICAL_ALERTS=1'
          ]
            end
        end
    end
    

Flutter 高德定位源码

import 'package:flutter/material.dart';
import 'dart:async';
// import 'dart:io';
import 'package:amap_flutter_location/amap_flutter_location.dart';
import 'package:amap_flutter_location/amap_location_option.dart';
import 'package:permission_handler/permission_handler.dart';
class LocationPage extends StatefulWidget {
  const LocationPage({Key? key}) : super(key: key);
  @override
  State<LocationPage> createState() => _LocationPageState();
}
class _LocationPageState extends State<LocationPage> {
  //获取数据
  // Map<String, Object> _locationResult;
  //
  String _latitude=""; //纬度
  String _longitude=""; //经度
  //监听定位
  late StreamSubscription<Map<String, Object>> _locationListener;
  //实例化插件
  final AMapFlutterLocation _locationPlugin = AMapFlutterLocation();
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    //私权政策是否弹窗展示告知用户
    AMapFlutterLocation.updatePrivacyShow(true, true);
    // [hasAgree] 隐私权政策是否已经取得用户同意
    AMapFlutterLocation.updatePrivacyAgree(true);
    /// 动态申请定位权限
    requestPermission();
    AMapFlutterLocation.setApiKey(
      "8d75a9a37463f51c864b8af2a735f3be", "ios ApiKey");
    ///注册定位结果监听
    _locationListener = _locationPlugin
      .onLocationChanged()
      .listen((Map<String, Object> result) {
        setState(() {
          print(result);
          print("-----");
          print(result is Map);
          // _locationResult = result;
          _latitude=result["latitude"].toString();
          _longitude=result["longitude"].toString();
        });
      });
  }
  @override
  void dispose() {
    super.dispose();
    ///移除定位监听
    if (null != _locationListener) {
      _locationListener.cancel();
    }
    ///销毁定位
    if (null != _locationPlugin) {
      _locationPlugin.destroy();
    }
  }
  ///设置定位参数
  void _setLocationOption() {
    if (null != _locationPlugin) {
      AMapLocationOption locationOption = new AMapLocationOption();
      ///是否单次定位
      locationOption.onceLocation = false;
      ///是否需要返回逆地理信息
      locationOption.needAddress = true;
      ///逆地理信息的语言类型
      locationOption.geoLanguage = GeoLanguage.DEFAULT;
      locationOption.desiredLocationAccuracyAuthorizationMode =
        AMapLocationAccuracyAuthorizationMode.ReduceAccuracy;
      locationOption.fullAccuracyPurposeKey = "AMapLocationScene";
      ///设置Android 端连续定位的定位间隔
      locationOption.locationInterval = 2000;
      ///设置Android 端的定位模式<br>
      ///可选值:<br>
      ///<li>[AMapLocationMode.Battery_Saving]</li>
      ///<li>[AMapLocationMode.Device_Sensors]</li>
      ///<li>[AMapLocationMode.Hight_Accuracy]</li>
      locationOption.locationMode = AMapLocationMode.Hight_Accuracy;
      ///设置iOS 端的定位最小更新距离<br>
      locationOption.distanceFilter = -1;
      ///设置iOS 端期望的定位精度
      /// 可选值:<br>
      /// <li>[DesiredAccuracy.Best] 最高精度</li>
      /// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度</li>
      /// <li>[DesiredAccuracy.NearestTenMeters] 10 米</li>
      /// <li>[DesiredAccuracy.Kilometer] 1000 米</li>
      /// <li>[DesiredAccuracy.ThreeKilometers] 3000 米</li>
      locationOption.desiredAccuracy = DesiredAccuracy.Best;
      ///设置iOS 端是否允许系统暂停定位
      locationOption.pausesLocationUpdatesAutomatically = false;
      ///将定位参数设置给定位插件
      _locationPlugin.setLocationOption(locationOption);
    }
  }
  ///开始定位
  void _startLocation() {
    if (null != _locationPlugin) {
      ///开始定位之前设置定位参数
      _setLocationOption();
      _locationPlugin.startLocation();
    }
  }
  /// 动态申请定位权限
  void requestPermission() async {
    // 申请权限
    bool hasLocationPermission = await requestLocationPermission();
    if (hasLocationPermission) {
      print("定位权限申请通过");
    } else {
      print("定位权限申请不通过");
    }
  }
  /// 申请定位权限授予定位权限返回true, 否则返回false
  Future<bool> requestLocationPermission() async {
    //获取当前的权限
    var status = await Permission.location.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("纬度:$_latitude"),
            Text("经度:$_longitude"),
            const SizedBox(height: 20),
            ElevatedButton(
              child: const Text('开始定位'),
              onPressed: () {
                _startLocation();
              },
            ),
          ],
        ),
      ),
    );
  }
}

results matching ""

    No results matching ""