flutter 高德定位

flutter 高德定位

由于众所周知的原因,国内无法使用location提供的谷歌定位服务,所以只能使用百度地图或者高德地图提供的定位服务。

所幸双方都已经实现了对flutter的支持。百度地图的api和配置比高德要简单那么一丢丢,不过包好像很久没更新,以至于错误很多。最终还是选了高德地图来实现。

官方文档地址

https://lbs.amap.com/api/flutter/gettingstarted

1. 获取高德Key

在控制台创建新的应用获取key

创建新应用

应用名称自定义,可以随便写。类型选择相符的就可以,这个不会严格审查的。

应用下面可以有好几个key,key的名称可以自定义,平台选择对应的平台。

申请key需要填写debug版本和release版本的keystore

keystore和Keytool是什么

Keytool是一个Java数据证书的管理工具 ,Keytool将密钥(key)和证书(certificates)存在一个称为keystore的文件中。 在keystore里,包含两种数据:

密钥实体(Key entity)——密钥(secret key)又或者是私钥和配对公钥(采用非对称加密)
可信任的证书实体(trusted certificate entries)——只包含公钥
Keystore可以简单理解为一个存放应用签名的文件。

调试版安全码SHA1

我是mac,进入当前用户文件夹下的~/.android目录(windows在c:/user/.android),里面有debug.keystore文件,运行命令获取该文件sha1

cd ~/.android
keytool -list -v -keystore debug.keystore

如果keytool不存在则需要安装jdk。

image

如果debug.keystore不存在,则需要使用keytool -genkey命令生成一个debug.keystore

输入密钥口令,默认是 android,即可获得SHA1安全码

image

发布版安全码SHA1

如果没有过apk还没有keystore签名文件,则需要生成,

生成keystore签名文件

keytool -genkey -v -keystore mykey.keystore -alias key -keyalg RSA -keysize 2048 -validity 10000

填写好资料

image

生成后的文件在mac用户目录

image

命令行直接使用keytool进行得到mykey.keystore的sha1,在文件目录下运行

keytool -list -v -keystore mykey.keystore

image

即可得到发布版安全码,apk就用这个keystore文件进行签名,这样就没问题了。

如果需要把apk签名,具体方法请看:
https://www.jianshu.com/p/398d41128b02

PackageName

在 android/app/build.gradle 中获取包名

image

提交保存后即可获得Key。

集成SDK

在 android/build.gradle 文件中,添加mavenCentral()或者 jcenter()

allprojects { repositories { jcenter() // 或者 mavenCentral() } }

在 android/app/build.gradle 中,配置依赖:

dependencies {
    ...
    implementation 'com.amap.api:location:latest.integration'
}

添加服务、声明定位权限

Android:
在 android/app/src/main/AndroidManifest.xml 文件中
1、添加服务

    <application android:label="****" android:icon="@mipmap/ic_launcher">
        <!-- 配置定位Service -->
        <service android:name="com.amap.api.location.APSService"/>

2、声明权限

<!--允许访问网络,必选权限-->
    <uses-permission android:name="android.permission.INTERNET"/>
    <!--允许获取精确位置,精准定位必选-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <!--允许获取粗略位置,粗略定位必选-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <!--允许获取设备和运营商信息,用于问题排查和网络定位(无gps情况下的定位),若需网络定位功能则必选-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <!--允许获取网络状态,用于网络定位(无gps情况下的定位),若需网络定位功能则必选-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <!--允许获取wifi网络信息,用于网络定位(无gps情况下的定位),若需网络定位功能则必选-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <!--允许获取wifi状态改变,用于网络定位(无gps情况下的定位),若需网络定位功能则必选-->
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
    <!--后台获取位置信息,若需后台定位则必选-->
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
    <!--用于申请调用A-GPS模块,卫星定位加速-->
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
    <!--允许写设备缓存,用于问题排查-->
    <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
    <!--允许写入扩展存储,用于写入缓存定位数据-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <!--允许读设备等信息,用于问题排查-->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

ios:
1、ios/info.plist加入

    <key>NSLocationWhenInUseUsageDescription</key>
    <string>使用当前位置信息</string>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>实时使用当前的位置信息</string>
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>实时使用当前的位置信息</string>

2、ios/Padfile末尾加入

    target.build_configurations.each do |config|
    # Here are some configurations automatically generated by flutter

      # 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_handler/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

如图:

image

引入高德定位Flutter插件

# 高德地图
amap_flutter_location: ^3.0.0

获取定位

代码中填入申请好的高德apikey)

import 'dart:async';

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';

/*
//使用

    locationUtil.getCurrentLocation((Map result){
      print('接收到result:$result');
    }).catchError((err){
      Fluttertoast.showToast(msg: err);
    });

*/

class LocationUtil {
  StreamSubscription<Map<String, Object>>? _locationListener;
  final AMapFlutterLocation _locationPlugin = AMapFlutterLocation();
  PermissionStatus? status;

  LocationUtil(){
    AMapFlutterLocation.setApiKey(
      "xxxxxx",//androidkey
      "xxxxxx"//ioskey
    );

    /// 设置是否已经包含高德隐私政策并弹窗展示显示用户查看,如果未包含或者没有弹窗展示,高德定位SDK将不会工作
    ///
    /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy
    /// <b>必须保证在调用定位功能之前调用, 建议首次启动App时弹出《隐私政策》并取得用户同意</b>
    ///
    /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy
    ///
    /// [hasContains] 隐私声明中是否包含高德隐私政策说明
    ///
    /// [hasShow] 隐私权政策是否弹窗展示告知用户
    AMapFlutterLocation.updatePrivacyShow(true, true);

    /// 设置是否已经取得用户同意,如果未取得用户同意,高德定位SDK将不会工作
    ///
    /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy
    ///
    /// <b>必须保证在调用定位功能之前调用, 建议首次启动App时弹出《隐私政策》并取得用户同意</b>
    ///
    /// [hasAgree] 隐私权政策是否已经取得用户同意
    AMapFlutterLocation.updatePrivacyAgree(true);

  }

  /// 动态申请定位权限
  Future<bool> _requestPermission() async {
    status = await Permission.location.status;

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

  Future<void> getCurrentLocation(Function(Map result) onLocationChanged,{once=true}) async {

    bool isPermitted =  await _requestPermission();
    print('isPermitted=$isPermitted');
    if(!isPermitted){
      throw('请在手机设置中开启本app位置权限');
    }

    if(isPermitted){
      ///注册定位结果监听
      _locationListener = _locationPlugin.onLocationChanged().listen((Map<String, Object> result) {
        onLocationChanged(result);
        if (result['longitude'] != null) {
          //print("当前位置:$result");
          if(once) _stopLocation();
        }
      });
      _startLocation();
    }
  }

  ///设置定位参数
  void _setLocationOption() {
    AMapLocationOption locationOption = AMapLocationOption();

    ///将定位参数设置给定位插件
    _locationPlugin.setLocationOption(locationOption);
  }

  ///开始定位
  void _startLocation() {
    _setLocationOption();
    _locationPlugin.startLocation();
  }

  ///停止定位
  void _stopLocation() {
    _locationPlugin.stopLocation();
  }

  void cancel() {
    if (null != _locationListener) {
      _locationListener?.cancel(); // 停止定位
    }
  }
}

错误

Could not resolve com.amap.api:location:latest.integration.

image

如果出现这个错误,是因为build的时候,会去云端仓库请求最新的包列表,如果请求不到,则会无法build。我们可以指定包。
查看最新的包:https://lbs.amap.com/api/android-location-sdk/guide/create-project/android-studio-create-project
编辑android/app/build.gradle

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.amap.api:location:3.3.0'//指定版本高德定位插件,
    //implementation 'com.amap.api:location:latest.integration'//最新版高德定位插件
}


著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容