美文网首页
flutter 高德地图SDK 接入

flutter 高德地图SDK 接入

作者: 简单coder | 来源:发表于2022-02-12 00:12 被阅读0次

    本篇为flutter 项目集成高德地图flutter插件,话不多说,直接上代码

    iOS 端

    创建账号

    创建高德账号流程我忘记截图,也就不放了,十分简单,我的 demo 测试是个人账号,手机号注册,然后绑定下支付宝即可,企业账号依据流程注册



    iOS 获取 key 值流程十分简单(安卓注册 key 幺蛾子就多起来了,后面再说)

    导入包

    iOS 使用 map 和定位不需要在原生端导入,直接在 flutter中 pubspec.yaml中引入即可

    # 高德地图
      amap_flutter_map: ^3.0.0
      # 定位
      amap_flutter_location: ^3.0.0
    

    但是我要注意提醒你们的是,这样安装的高德SDK 是包含 IDFA 的,不过说实话避免使用 idfa真的是太累人了,有太多SDK其实都用 idfa 了,OpenInstall,友盟,bugly,等等,我的建议是,还不如直接就声明自己的 APP 使用了 idfa,这玩意儿现在习惯了我感觉用户其实没啥反感的,因为几乎每个 APP 都会弹这个请求弹窗.


    配置权限

    Xcode 打开iOS 下Runner.xcworkspace,右键info.plist选择



    把下面的内容按自己的需求粘进去即可,文案什么的,越详细越好,说清楚自己拿这个权限想干啥,被拒过的人都懂

        <key>NSCameraUsageDescription</key>
        <string>请点击“好”以允许访问。若不允许,你将无法使用相机来拍照和视频</string>
        <key>NSLocalNetworkUsageDescription</key>
        <string>此 APP 不会连接到您所用网络上的设备,只会检测与您本地网关的连通性</string>
        <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
        <string>请点击“允许”以允许访问。 若不允许,你所在的城市将无法出现在你的动态、个人主页。</string>
        <key>NSLocationWhenInUseUsageDescription</key>
        <string>请点击“允许”以允许访问。 若不允许,你所在的城市将无法出现在你的动态、个人主页。</string>
        <key>NSLocationAlwaysUsageDescription</key>
        <string>请点击“允许”以允许访问。 若不允许,你所在的城市将无法出现在你的动态、个人主页。</string>
        <key>NSMicrophoneUsageDescription</key>
        <string>请点击“好”以允许访问。若不允许,你将无法使用麦克风录制发送语音</string>
        <key>NSPhotoLibraryAddUsageDescription</key>
        <string>请点击“好”以允许访问。若不允许,你将无法使用无法使用相册照片发送消息、上传头像和发布动态。</string>
        <key>NSPhotoLibraryUsageDescription</key>
        <string>请点击“好”以允许访问。若不允许,你将无法使用无法使用相册照片发送消息、上传头像和发布动态。</string>
        <key>UILaunchStoryboardName</key>
        <key>NSUserTrackingUsageDescription</key>
        <string>请放心, 爱泡炸无法获取你在应用内的隐私,该权限仅用于标识设备以保障服务安全与提升浏览体验</string>
    

    业务代码

    业务代码我没有进行封装,直接在作为测试 demo 展示,也没做什么动画的渐变啥的

    import 'package:amap_flutter_map/amap_flutter_map.dart';
    import 'package:amap_flutter_base/amap_flutter_base.dart';
    import 'package:amap_flutter_location/amap_flutter_location.dart';
    import 'package:amap_flutter_location/amap_location_option.dart';
    
    import 'package:flutter/material.dart';
    import 'package:flutter_psd/common/utils/psdllog.dart';
    import 'package:permission_handler/permission_handler.dart';
    
    class GaodeMapPage extends StatefulWidget {
      const GaodeMapPage({Key? key}) : super(key: key);
    
      @override
      _GaodeMapPageState createState() => _GaodeMapPageState();
    }
    
    class _GaodeMapPageState extends State<GaodeMapPage> {
      static const AMapApiKey amapApiKeys = AMapApiKey(
          iosKey: '9af9e11da0573c280a514f2f6372df5f',
          androidKey: 'eb909b4ee863e2bd0aa18098b7acc9ba');
    
      AMapController? mapController;
      AMapFlutterLocation? location;
    
      PermissionStatus? permissionStatus;
      CameraPosition? currentLocation;
    
      @override
      void initState() {
        super.initState();
        AMapFlutterLocation.setApiKey(
            "eb909b4ee863e2bd0aa18098b7acc9ba", "9af9e11da0573c280a514f2f6372df5f");
        AMapFlutterLocation.updatePrivacyAgree(true);
        AMapFlutterLocation.updatePrivacyShow(true, true);
    
        requestPermission();
      }
    
      Future<void> requestPermission() async {
        final status = await Permission.location.request();
        permissionStatus = status;
        switch (status) {
          case PermissionStatus.denied:
            psdllog("拒绝");
            break;
          case PermissionStatus.granted:
            requestLocation();
            break;
          case PermissionStatus.limited:
            psdllog("限制");
            break;
          default:
            psdllog("其他状态");
            requestLocation();
            break;
        }
      }
    
      void requestLocation() {
        location = AMapFlutterLocation()
          ..setLocationOption(AMapLocationOption())
          ..onLocationChanged().listen((event) {
            psdllog(event);
            double? latitude = double.parse(event['latitude'] as String);
            double? longitude = double.parse(event['longitude'] as String);
            if (latitude != null && longitude != null) {
              setState(() {
                currentLocation = CameraPosition(
                  target: LatLng(latitude, longitude),
                  zoom: 10,
                );
              });
            }
          })
          ..startLocation();
      }
    
      @override
      void dispose() {
        location?.destroy();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(
              "高德地图",
              style: TextStyle(),
            ),
          ),
          body: currentLocation == null
              ? Container()
              : Center(
                  child: SizedBox(
                  child: AMapWidget(
                    apiKey: amapApiKeys,
                    // 初始化地图中心店
                    initialCameraPosition: currentLocation!,
                    //定位小蓝点
                    myLocationStyleOptions: MyLocationStyleOptions(
                      true,
                    ),
                    // 普通地图normal,卫星地图satellite,夜间视图night,导航视图 navi,公交视图bus,
                    mapType: MapType.normal,
                    // 缩放级别范围
                    minMaxZoomPreference: MinMaxZoomPreference(3, 20),
                    // 隐私政策包含高德 必须填写
                    privacyStatement: AMapPrivacyStatement(
                        hasAgree: true, hasContains: true, hasShow: true),
                    // 地图创建成功时返回AMapController
                    onMapCreated: (AMapController controller) {
                      mapController = controller;
                    },
                  ),
                )),
        );
      }
    }
    
    

    代码在上面,然后我讲一些 iOS权限错误还有和Android 通用的高德错误.

    • 1.iOS双定位权限
    [MAMapKit] 要在iOS 11及以上版本使用定位服务, 需要在Info.plist中添加NSLocationAlwaysAndWhenInUseUsageDescription和NSLocationWhenInUseUsageDescription字段。
    

    这是两个权限说明必须要全部配置,顺便提一嘴,iOS 隐私权限不管你在哪用,进入APP 第一时间就要弹出,定位权限没有这个要求.

      1. permission_handler报错
    * What went wrong:
    Execution failed for task ':permission_handler:compileDebugJavaWithJavac'.
    

    一开始以为是 flutter 版本问题(今天测试 demo的时候,看到有人说2.10.0版本的 flutter 有个系统 bug),又看到有篇 stackoverflow 说升级版本就能解决这个 bug,所以升级到了2.10.1,然而还是没有解决.于是就去翻permission_handler的 issue,终于找到了,很幸运的是
    permission_handler的作者刚刚好在昨天解释了这个 bug地址戳这

    我当时使用的版本是7.* 升级后我就解决了这个问题

    代码说明

    高德 flutter 文档地址: 戳这儿
    iOSbug少,基本按照文档来即可,而且由于是中文文档,看起来一点也不费劲,这边建议先获取到定位后在展示地图,这样,直接能够显示到中心的小蓝点.

    // 隐私政策包含高德 必须填写
     privacyStatement: AMapPrivacyStatement(hasAgree: true, hasContains: true, hasShow: true),
    

    定位的隐私政策也会一样,不然直接拋异常,高德希望你在隐私网址中提到高德地图的使用,正确合规的做法是在同意隐私政策的时候设置权限为 true
    AMapFlutterLocation..updatePrivacyAgree(true)..updatePrivacyShow(true, true);

    原生里的 key优先级小于 Widget 代码中.

    定位中获取的参数map 经纬度为 string.

    {locTime: 2022-02-11 21:51:03, province: 浙江省, callbackTime: 2022-02-11 21:51:03, district: 西湖区, country: 中国, street: ****, speed: -1.0, latitude: 30.287363, city: 杭州市, streetNumber: 177-1号, bearing: -1.0, accuracy: 35.0, adCode: 330106, altitude: 11.046348571777344, locationType: 1, longitude: 120.128650, cityCode: 0571, address: 浙江省杭州市西湖区*****, description: 浙江省杭州市西湖区*****}
    

    高德的 flutterAPI 接口提供的确实很少,甚至感觉有点简陋,其实这东西如果以后有精力的话,可以尝试自己封装一下,当然安卓端我搞起来确实难度有点大,主要是要做好公共接口,做好channel 通信,剩下的就是各端的小伙伴去努力实现了,顺便可以练练插件.高德源码我也看了下,通道目前做的还不是太多,希望后面能丰富起来.


    AMapController

    效果展示

    安卓端

    安卓端配置真的是一言难尽,iOS 的过度顺利导致我以为安卓端的兼容也十分简单,我感觉周五一下午的时间全用来 碰 bug 上了,下面叙述下我的血泪史
    首先尝试安卓模拟器运行项目

    • 运行,报错



      跟着改成31

    • 再运行,再报错,kotlin gradle 插件版本有问题



      修改根build.gradle

    buildscript {
        ext.kotlin_version = '1.6.10'
        *****
    }
    

    运行正常,进入地图界面的时候拋异常

    • java.lang.NoClassDefFoundError: Failed resolution of: Lcom/amap/api/location/AMapLocationClient;

    很明显,连类都找不到,一番查询后,得知Android 需要手动导入 sdk
    在官方文档中,我采用手动拖入sdk+so


    • 再运行,再报错errorCode: 10 *******请检查AndroidManifest.xml文件是否配置了APSService定位服务
      AndroidManifest.xml增加
           <service android:name="com.amap.api.location.APSService"></service>
    
    • APSService标红
      网上查询到app/build.gradle 下增加
    dependencies {
    //    implementation files('src/libs/AMap3DMap_AMapLocation/AMap3DMap_9.0.0_AMapLocation_5.6.2_20220113.jar')
        implementation('com.amap.api:location:5.2.0')
    }
    

    这里我一开始查到是手动右键将 jar 包增加到library


    但是报了一个什么错我忘记记录了
    然后我查了下,查到下面的写法implementation('com.amap.api:location:5.2.0')目前不知道这两者的区别
    再运行,在报错
    • errorCode: 12, errorInfo: 缺少定位权限 请到http://lbs.amap.com/api/android-location-sdk/guide/utilities/errorcode/查看错误码说明,错误详细信息:定位权限被禁用,请授予应用定位权限#1201#定位权限被禁用,请授予应用定位权限#1201

    • errorInfo: WIFI信息不足 请到http://lbs.amap.com/api/android-location-sdk/guide/utilities/errorcode/查看错误码说明,错误详细信息:当前基站为伪基站,并且搜到的WIFI数量不足,请移动到WIFI比较丰富的区域#0202#当前基站为伪基站,并且搜到的WIFI数量不足,请移动到WIFI比较丰富的区域#0202}
      这两个我后面换安卓真机运行就消失了,应该是项目重启,或者 APP 卸载,或者 flutter clean , gradle clean 等等,上面的其他几个 bug 我有些有尝试过清缓存解决,也许没提到,但是大家心里要有个印象
      再运行,再报错

    • Flutter multidex handling is disabled. If you wish to let the tool configure multidex, use the --mutidex flag.
      这个我请了清缓存,重启下就好了

    • 再运行,再报错



      其实到这儿,我心理已经大概有点底了,项目可以正常运行,只是定位无法提供,这里设计到 Android key 的创建,这里的出错应该是我没配好,其实最开始应该要写下如何创建 Android 的高德 key 的,后面补上,文章先写到这,明儿再找时间调调,然后把文章更新下,应该只需要亿点点时间.(主要是 bug 太多,再不写我就忘记我遇到过哪些 bug 了)


    2022-02-12 09:57:09 更新 Android真机高德地图定位成功

    昨天有个 bug 是鉴权失败导致定位失败
    我按照昨天最后高德给出的鉴权失败流程一点点尝试,并没有解决,我怀疑我获取的 key 并不是我注册的 key,今天尝试用另外一种方法解决

    在创建 debug.storekey 成功后, 创建 key 的方法戳这,我采用高德提供的获取 key 方式获取cd ~/.android


    然后将该 SHA1更新到高德 key 中
    最后鉴权成功.

    再运行,成功获取到坐标


    然而地图黑屏了,仅显示左下角一个 logo, 控制台打印报错



    查了很多资料,最后怀疑是 so 文件导入出错,高德给了两种导入方法



    在下载 sdk 的时候,高德附带了各个平台的 so 文件

    我直接使用第一种方法,可能我导入的确实有点问题,并没有成功,于是我改成第二种方法




    顺便提一下,对于 jar 包的引入,我还是改成了本地 jar 包

    这是因为在尝试网上给出的implementation('com.amap.api:location:5.2.0')后,我发现报了一个找不到 MapView 啥的实现方法,推断出'com.amap.api:location:5.2.0'只能实现高德location库的方法,我想着还是用本地的 jar 包才对,要不然放那就是白导入了.

    运行报错如果发现



    可以尝试增加


    效果展示

    最后的最后,安卓真机地图的导入才算是结束了,最后展示下效果吧


    PS

    这次的安卓高德地图的配置,感觉基本把能踩的全踩了个遍,也是因为自己对安卓系统不太熟,平时也常用 iOS 真机或者模拟器测,也基本没啥问题,昨天也痛定思痛,以后再也不搞 iOS 模拟器了,下了个 momo,以后全部用安卓测代码,
    顺便贴个momo模拟器 配置

    system_profiler SPUSBDataType
    复制ID/Vender ID到/.android/adb_usb.ini
    adb kill-server
    adb start-server
    adb devices
    

    相关文章

      网友评论

          本文标题:flutter 高德地图SDK 接入

          本文链接:https://www.haomeiwen.com/subject/lwhakrtx.html