irpas技术客

Flutter集成百度地图-Android集成_Yumito_flutter 百度地图

网络 641

版本:flutter 2.10.4

百度地图3.2.0

IDE:Android Studio

最近公司项目需要集成地图,看着百度地图有flutter插件就开始忙活了,踩了一脑门子的坑,现在分享给大家。

2022-08-01 更新关于在调用poi搜索等功能时,提示鉴权失败的问题

引入的base包在as不提示时,建议手动添加引用

鉴权初始化后才可以使用搜索

import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart' import 'dart:io' show Platform; // 百度地图sdk初始化鉴权 if (Platform.isIOS) { _locationPlugin.authAK('请在此输入您在开放平台上申请的API_KEY'); BMFMapSDK.setApiKeyAndCoordType( '请在此输入您在开放平台上申请的API_KEY', BMF_COORD_TYPE.BD09LL); } else if (Platform.isAndroid) { // Android 目前不支持接口设置Apikey, // 请在主工程的Manifest文件里设置,详细配置方法请参考官网(https://lbsyun.baidu.com/)demo BMFMapSDK.setCoordType(BMF_COORD_TYPE.BD09LL); }

目录

1.申请AK、SHA1值

2.集成地图插件

3.Android端配置BmfMapApplication

4.flutter中使用地图widget?

?5.使用定位获取坐标,居中显示


1.申请AK、SHA1值

在百度开发者后台申请Android所需的AK值,这个网上很多教程不细说

2.集成地图插件

在flutter项目的pubspec.yami中,dependencies下添加如下插件

dependencies: #https://lbsyun.baidu.com/index.php?title=flutter/loc/create-project/note #注意第三个插件在百度教程中是fflutter开头,实际为flutter开头 flutter_baidu_mapapi_map: ^3.2.0 flutter_baidu_mapapi_search: ^3.2.0 flutter_baidu_mapapi_utils: ^3.2.0 flutter_bmflocation: ^3.1.0

注意

第一个坑来了,

百度的地图教程多打了一个f,实际为?flutter_baidu_mapapi_utils: ^3.2.0

导致我第一次集成死活找不到插件。

之后使用pub get获取插件包即可

#如果获取不到插件,可能是百度地图的插件又更新了,建议使用any版本号重新在pubspec.lock中重新获取一下

例如flutter_baidu_mapapi_map: ^3.2.0修改为flutter_baidu_mapapi_map: any,然后pub get,打开项目下pubspec.lock翻到这个插件名,看看对应version版本修改一下

3.Android端配置BmfMapApplication

右击找到flutter菜单,用as打开android文件夹。

如果没有,直接用open打开android文件夹也行?

菜单置灰解决方案:新建一个xxx_android.imi文件与local.properties同级,xxx为项目名

内容为

<?xml version="1.0" encoding="UTF-8"?> <module type="JAVA_MODULE" version="4"> <component name="FacetManager"> <facet type="android" name="Android"> <configuration> <option name="ALLOW_USER_CONFIGURATION" value="false" /> <option name="GEN_FOLDER_RELATIVE_PATH_APT" value="/gen" /> <option name="GEN_FOLDER_RELATIVE_PATH_AIDL" value="/gen" /> <option name="MANIFEST_FILE_RELATIVE_PATH" value="/app/src/main/AndroidManifest.xml" /> <option name="RES_FOLDER_RELATIVE_PATH" value="/app/src/main/res" /> <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/app/src/main/assets" /> <option name="LIBS_FOLDER_RELATIVE_PATH" value="/app/src/main/libs" /> <option name="PROGUARD_LOGS_FOLDER_RELATIVE_PATH" value="/app/src/main/proguard_logs" /> </configuration> </facet> </component> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> <content url="file://$MODULE_DIR$"> <sourceFolder url="file://$MODULE_DIR$/app/src/main/java" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" /> </content> <orderEntry type="jdk" jdkName="Android API 30 Platform" jdkType="Android SDK" /> <orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="library" name="Flutter for Android" level="project" /> </component> </module>

?如果新建后还是不能在菜单中打开,可以试试

?还是不能打开,建议新建一个项目,找到imi文件,复制粘贴修改

文件类型为intelliJ.. 这个文件类型我没在Androidstudio找到

理论上可以用这个修改?

打开后在MainActivity同级下新建BaseApplication

import com.baidu.mapapi.base.BmfMapApplication; public class BaseApplication extends BmfMapApplication { @Override public void onCreate() { super.onCreate(); } }

?可能会涉及到个别model中使用了min16版本,手动在build.gradle修改为19即可

如果BmfMapApplication不存在,重新在flutter中pubget几次,flutter clean几次

如果还是不存在,大概提供一下BmfMapApplication路径提供参考,是否是model没有编译进来,或者包没引入到

之后按教程修改application的name值为BaseApplication,添加权限

添加AK值

<application> <meta-data android:name="com.baidu.lbsapi.API_KEY" android:value="请输入百度开放平台申请的Android端API KEY" /> </application>

?按教程还需要添加混淆

打开android 目录app下的build.gradle文件,在release代码块中添加如下内容。(默认情况下 flutter不会开启 Android 的混?淆)

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.debug minifyEnabled true useProguard true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }

?新建混淆文件

-keep class com.baidu.** {*;} -keep class vi.com.** {*;} -keep class com.baidu.vi.** {*;} -dontwarn com.baidu.** 4.flutter中使用地图widget? 百度地图的widget为BMFMapWidget BMFMapWidget( onBMFMapCreated: (controller) { //自定义onBMFMapCreated方法,用于获取controller onBMFMapCreated(controller); }, mapOptions: BMFMapOptions( center: BMFCoordinate(39.917215, 116.380341), zoomLevel: 12, mapPadding: BMFEdgeInsets(left: 30, top: 0, right: 30, bottom: 0)), ) late BMFMapController _controller; void onBMFMapCreated(BMFMapController controller) { _controller = controller; _controller.showUserLocation(true); }

如果在widget中报错,找不到BMFMapOptions、BMFEdgeInsets等类,路径为

使用引入强行添加。可能原因是在android的BmfMapApplication没有正常引入,也可能是pubget获取的百度地图版本问题,更新最新的版本可能解决。

import 'package:flutter_baidu_mapapi_map/src/models/bmf_map_options.dart'; ?5.使用定位获取坐标,居中显示

声明所需的几个变量

late LocationFlutterPlugin _locationPlugin; BaiduLocationIOSOption iosOption = BaiduLocationIOSOption(coordType: BMFLocationCoordType.gcj02); BaiduLocationAndroidOption androidOption = BaiduLocationAndroidOption(coordType: BMFLocationCoordType.gcj02); late BMFMapController _controller; late BaiduLocation _location;

?在initState中初始化。

注意

_locationPlugin.setAgreePrivacy(true);

这句话在百度教程没有,是否同意隐私协议的东西,不加上不会加载地图,神奇的玩意坑了我一下午

@override void initState() { _locationPlugin = LocationFlutterPlugin(); _locationPlugin.setAgreePrivacy(true); _location = BaiduLocation(); _locationPlugin.seriesLocationCallback(callback: (BaiduLocation result) { _location = result; _stopLocation(); updatePosition(); }); _startLocation(); }

Android权限建议在androidmanifest配置单多添加一份。存储涉及的storage权限可能有坑,建议加上

// 申请权限 Future<bool> requestPermission() async { // 申请权限 final status = await Permission.location.request(); //获取存储权限,可能涉及到地图的shareprefences读写问题,建议加上并进行判断 //await Permission.storage.status; if (status.isGranted) { print("定位权限申请通过"); return true; } else { print("定位权限申请不通过"); return false; } } /// 停止定位 void _stopLocation() { if (null != _locationPlugin) { _locationPlugin.stopLocation(); } } // 开始定位 void _startLocation() { if (null != _locationPlugin) { //申请定位权限 requestPermission().then((value) => { if (value) {_setLocOption(), _locationPlugin.startLocation()} else { EasyLoading.showToast("需要定位权限", toastPosition:EasyLoadingToastPosition.bottom) } }); } } // 设置定位参数 void _setLocOption() { androidOption.setCoorType("bd09ll"); // 设置返回的位置坐标系类型 androidOption.setIsNeedAltitude(true); // 设置是否需要返回海拔高度信息 androidOption.setIsNeedAddress(true); // 设置是否需要返回地址信息 androidOption.setIsNeedLocationPoiList(true); // 设置是否需要返回周边poi信息 androidOption.setIsNeedNewVersionRgc(true); // 设置是否需要返回最新版本rgc信息 androidOption.setIsNeedLocationDescribe(true); // 设置是否需要返回位置描述 androidOption.setOpenGps(true); // 设置是否需要使用gps androidOption.setLocationMode(BMFLocationMode.hightAccuracy); // 设置定位模式 androidOption.setScanspan(1000); // 设置发起定位请求时间间隔 Map androidMap = androidOption.getMap(); Map iosdMap = iosOption.getMap(); _locationPlugin.prepareLoc(androidMap, iosdMap); //ios和安卓定位设置 } //更新地点 void updatePosition() { BMFCoordinate coordinate = BMFCoordinate( _location.latitude ?? 39.917215, _location.longitude ?? 116.380341); BMFMapOptions options = BMFMapOptions( center: coordinate, zoomLevel: 17, mapPadding: BMFEdgeInsets(left: 30, top: 0, right: 30, bottom: 0)); BMFLocation location = BMFLocation( coordinate: coordinate, altitude: 0, horizontalAccuracy: 5, verticalAccuracy: -1.0, speed: -1.0, course: -1.0); BMFUserLocation userLocation = BMFUserLocation( location: location, ); _controller.updateLocationData(userLocation); _controller.updateMapOptions(options); }

申请权限、Toast等插件使用了如下插件。

dependencies: #Tost flutter_easyloading: ^3.0.3 #动态权限申请 permission_handler : ^6.0.2

分割线。大概踩坑结束,能够显示地图并且定位在附近地点,居中显示?

最后贴一下全部代码作为参考

import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart'; import 'package:flutter_baidu_mapapi_base/src/map/bmf_models.dart'; import 'package:flutter_baidu_mapapi_search/flutter_baidu_mapapi_search.dart'; import 'package:flutter_bmflocation/flutter_bmflocation.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:permission_handler/permission_handler.dart'; class MapRoute extends StatefulWidget { const MapRoute({Key? key}) : super(key: key); @override State<StatefulWidget> createState() { // TODO: implement createState return MapRouteState(); } } class MapRouteState extends State<MapRoute> { late TextEditingController positionController; late LocationFlutterPlugin _locationPlugin; BaiduLocationIOSOption iosOption = BaiduLocationIOSOption(coordType: BMFLocationCoordType.gcj02); BaiduLocationAndroidOption androidOption = BaiduLocationAndroidOption(coordType: BMFLocationCoordType.gcj02); late BMFMapController _controller; late BaiduLocation _location; @override void initState() { positionController = TextEditingController(); _locationPlugin = LocationFlutterPlugin(); _locationPlugin.setAgreePrivacy(true); _location = BaiduLocation(); _locationPlugin.seriesLocationCallback(callback: (BaiduLocation result) { _location = result; _stopLocation(); updatePosition(); }); _startLocation(); } @override Widget build(BuildContext context) { // TODO: implement build return Scaffold( resizeToAvoidBottomInset: false, appBar: AppBar( title: const Text( "选取地点", style: TextStyle(color: Colors.black), ), centerTitle: true, backgroundColor: Colors.white, actions: <Widget>[ MaterialButton( child: const Text("确定", style: TextStyle(fontSize: 15)), onPressed: () {}, ) ], leading: IconButton( onPressed: () { Navigator.pop(context); }, icon: const Icon(Icons.arrow_back_ios, color: Colors.black)), ), body: _map(), ); } Widget _map() { return Container( child: Column( children: [ Container( child: TextField( controller: positionController, style: const TextStyle(color: Colors.black), decoration: InputDecoration( border: InputBorder.none, hintText: "请输入地点", hintStyle: const TextStyle(color: Colors.grey, fontSize: 14), suffix: Container( child: MaterialButton( child: const Text("确认"), onPressed: () { serchPosition(positionController.text); }, ), ))), ), Expanded( child: BMFMapWidget( onBMFMapCreated: (controller) { //自定义onBMFMapCreated方法,用于获取controller onBMFMapCreated(controller); }, mapOptions: BMFMapOptions( center: BMFCoordinate(39.917215, 116.380341), zoomLevel: 12, mapPadding: BMFEdgeInsets(left: 30, top: 0, right: 30, bottom: 0)), )) ], )); } void onBMFMapCreated(BMFMapController controller) { _controller = controller; _controller.showUserLocation(true); } // 申请权限 Future<bool> requestPermission() async { // 申请权限 final status = await Permission.location.request(); if (status.isGranted) { print("定位权限申请通过"); return true; } else { print("定位权限申请不通过"); return false; } } /// 停止定位 void _stopLocation() { if (null != _locationPlugin) { _locationPlugin.stopLocation(); } } // 开始定位 void _startLocation() { if (null != _locationPlugin) { //申请定位权限 requestPermission().then((value) => { if (value) {_setLocOption(), _locationPlugin.startLocation()} else { EasyLoading.showToast("需要定位权限", toastPosition:EasyLoadingToastPosition.bottom) } }); } } // 设置定位参数 void _setLocOption() { androidOption.setCoorType("bd09ll"); // 设置返回的位置坐标系类型 androidOption.setIsNeedAltitude(true); // 设置是否需要返回海拔高度信息 androidOption.setIsNeedAddress(true); // 设置是否需要返回地址信息 androidOption.setIsNeedLocationPoiList(true); // 设置是否需要返回周边poi信息 androidOption.setIsNeedNewVersionRgc(true); // 设置是否需要返回最新版本rgc信息 androidOption.setIsNeedLocationDescribe(true); // 设置是否需要返回位置描述 androidOption.setOpenGps(true); // 设置是否需要使用gps androidOption.setLocationMode(BMFLocationMode.hightAccuracy); // 设置定位模式 androidOption.setScanspan(1000); // 设置发起定位请求时间间隔 Map androidMap = androidOption.getMap(); Map iosdMap = iosOption.getMap(); _locationPlugin.prepareLoc(androidMap, iosdMap); //ios和安卓定位设置 } Future<void> serchPosition(String text) async { // 构造检索参数 BMFSuggestionSearchOption suggestionSearchOption = BMFSuggestionSearchOption( keyword: text, cityname: _location.city ?? "北京"); // 检索实例 BMFSuggestionSearch suggestionSearch = BMFSuggestionSearch(); // 检索回调 suggestionSearch.onGetSuggestSearchResult(callback: (BMFSuggestionSearchResult result, BMFSearchErrorCode errorCode) { print('sug检索回调 result = ${result.toMap()} \n errorCode = ${errorCode}'); // 解析reslut,具体参考demo }); // 发起检索 bool flag = await suggestionSearch.suggestionSearch(suggestionSearchOption); } void updatePosition() { BMFCoordinate coordinate = BMFCoordinate( _location.latitude ?? 39.917215, _location.longitude ?? 116.380341); BMFMapOptions options = BMFMapOptions( center: coordinate, zoomLevel: 17, mapPadding: BMFEdgeInsets(left: 30, top: 0, right: 30, bottom: 0)); BMFLocation location = BMFLocation( coordinate: coordinate, altitude: 0, horizontalAccuracy: 5, verticalAccuracy: -1.0, speed: -1.0, course: -1.0); BMFUserLocation userLocation = BMFUserLocation( location: location, ); _controller.updateLocationData(userLocation); _controller.updateMapOptions(options); } }

————————————2022.7.7——————————————————————————


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #Flutter #百度地图 #Android #集成百度地图 #踩坑攻略