Flutter接入百度地圖

由于眾所周知的原因,國內(nèi)無法使用location提供的谷歌定位服務(wù),所以只能使用百度地圖或者高德地圖提供的定位服務(wù)。

所幸雙方都已經(jīng)實現(xiàn)了對flutter的支持。高德地圖吃相難看,選用百度地圖

官方文檔地址

https://lbsyun.baidu.com/index.php?title=flutter/loc/guide/create

1. 獲取Key

在控制臺創(chuàng)建新的應(yīng)用獲取key

創(chuàng)建新應(yīng)用

應(yīng)用名稱自定義,可以隨便寫。類型選擇相符的就可以,這個不會嚴格審查的。

應(yīng)用下面可以有好幾個key,key的名稱可以自定義,平臺選擇對應(yīng)的平臺。

申請key需要填寫debug版本和release版本的keystore

安全碼SHA1

我是mac,打開為項目生成的keystore文件,運行命令獲取該文件sha1,我發(fā)布版和調(diào)試版都是用同一個keystore文件。

cd ~/project/flutter/xxxx
keytool -list -v -keystore xxx.keystore

PackageName

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

image

提交保存后即可獲得Key。

集成SDK

添加服務(wù)、聲明定位權(quán)限

Android:
在 android/app/src/main/AndroidManifest.xml 文件中
1、添加服務(wù)

<meta-data
    android:name="com.baidu.lbsapi.API_KEY"
    android:value="開發(fā)者申請的AK" />

2、聲明權(quán)限

<!--允許訪問網(wǎng)絡(luò),必選權(quán)限-->
    <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"/>
    <!--允許獲取設(shè)備和運營商信息,用于問題排查和網(wǎng)絡(luò)定位(無gps情況下的定位),若需網(wǎng)絡(luò)定位功能則必選-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <!--允許獲取網(wǎng)絡(luò)狀態(tài),用于網(wǎng)絡(luò)定位(無gps情況下的定位),若需網(wǎng)絡(luò)定位功能則必選-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <!--允許獲取wifi網(wǎng)絡(luò)信息,用于網(wǎng)絡(luò)定位(無gps情況下的定位),若需網(wǎng)絡(luò)定位功能則必選-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <!--允許獲取wifi狀態(tài)改變,用于網(wǎng)絡(luò)定位(無gps情況下的定位),若需網(wǎng)絡(luò)定位功能則必選-->
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
    <!--后臺獲取位置信息,若需后臺定位則必選-->
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
    <!--用于申請調(diào)用A-GPS模塊,衛(wèi)星定位加速-->
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
    <!--允許寫設(shè)備緩存,用于問題排查-->
    <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
    <!--允許寫入擴展存儲,用于寫入緩存定位數(shù)據(jù)-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <!--允許讀設(shè)備等信息,用于問題排查-->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

ios:
1、ios/info.plist加入

    <key>CFBundleDisplayName</key>
        <string>美好美食</string>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>使用當前位置信息</string>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>實時使用當前的位置信息</string>
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>實時使用當前的位置信息</string>
    <!--允許后臺定位-->
    <key>UIBackgroundModes</key>
    <array>
        <string>location</string>
    </array>

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.png

引入百度定位Flutter插件

# 百度地圖
  flutter_bmflocation: ^3.1.0+1

獲取定位

代碼中填入申請好的高德apikey)

import 'dart:async';
import 'dart:io';
import 'package:flutter_bmflocation/flutter_bmflocation.dart';
import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart'
    show BMFLog, BMFMapSDK, BMF_COORD_TYPE;

import 'package:permission_handler/permission_handler.dart';

/*
//使用

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

*/


//坐標系 GCJ02
class LocationUtil {
  StreamSubscription<Map<String, Object>>? _locationListener;
  late LocationFlutterPlugin _locationPlugin;
  PermissionStatus? status;


  LocationUtil(){
    _locationPlugin = LocationFlutterPlugin();
    _locationPlugin.setAgreePrivacy(true);
    if (Platform.isIOS) {
      /// 設(shè)置ios端ak, android端ak可以直接在清單文件中配置  
      _locationPlugin.authAK('wKcr0QantSnf00XFs9NUjelbtKKrlfOf');  
    } 

  }

  /// 動態(tài)申請定位權(quán)限
  Future<bool> _requestPermission() async {
    status = await Permission.location.status;

    if (status == PermissionStatus.granted) {
      return true;
    } else {
      //未授權(quán)則發(fā)起一次申請
      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('請在手機設(shè)置中開啟“河馬有有”位置權(quán)限');
    }

    if(isPermitted){
      ///注冊定位結(jié)果監(jiān)聽
      _locationPlugin.seriesLocationCallback(callback: (BaiduLocation baiduresult) {
        Map result = {};
        result['longitude'] = baiduresult.longitude;
        result['latitude'] = baiduresult.latitude;
        print("當前位置:$result");
        //返回結(jié)果
        onLocationChanged(result);
        if (result['longitude'] != null) {
          //print("當前位置:$result");
          if(once) _stopLocation();
        }
        
      });
      _startLocation();
    }
  }

  ///設(shè)置定位參數(shù)
  void _setLocationOption() {

    BaiduLocationIOSOption iosOptions = 
    BaiduLocationIOSOption(
      // 坐標系
      coordType: BMFLocationCoordType.gcj02,
      // 位置獲取超時時間
      locationTimeout: 10,
      // 獲取地址信息超時時間
      reGeocodeTimeout: 10,
      // 應(yīng)用位置類型 默認為automotiveNavigation
      activityType:  BMFActivityType.automotiveNavigation, 
      // 設(shè)置預(yù)期精度參數(shù) 默認為best
      desiredAccuracy: BMFDesiredAccuracy.best,
      // 是否需要最新版本rgc數(shù)據(jù)
      isNeedNewVersionRgc: true,
      // 指定定位是否會被系統(tǒng)自動暫停
      pausesLocationUpdatesAutomatically: false,
      // 指定是否允許后臺定位,
      // 允許的話是可以進行后臺定位的,但需要項目 
      //配置允許后臺定位,否則會報錯,具體參考開發(fā)文檔
      allowsBackgroundLocationUpdates: true,
      // 設(shè)定定位的最小更新距離
      distanceFilter: 10,
    );

    BaiduLocationAndroidOption androidOptions = 
    BaiduLocationAndroidOption(
      // 坐標系
      coordType: BMFLocationCoordType.gcj02,
      // 定位模式,可選的模式有高精度、僅設(shè)備、僅網(wǎng)絡(luò)。默認為高精度模式
      locationMode: BMFLocationMode.hightAccuracy,
      // 是否需要返回地址信息
      isNeedAddress: true,
      // 是否需要返回海拔高度信息
      isNeedAltitude: true,
      // 是否需要返回周邊poi信息
      isNeedLocationPoiList: true,
      // 是否需要返回新版本rgc信息
      isNeedNewVersionRgc: true,
      // 是否需要返回位置描述信息
      isNeedLocationDescribe: true,
      // 是否使用gps
      openGps: true,
      // 可選,設(shè)置場景定位參數(shù),包括簽到場景、運動場景、出行場景
      //locationPurpose: BMFLocationPurpose.signIn,
      // 設(shè)置發(fā)起定位請求的間隔,int類型,單位ms
      // 如果設(shè)置為0,則代表單次定位,即僅定位一次,默認為0
      scanspan: 4000); 
  
    _locationPlugin.prepareLoc(androidOptions.getMap(), iosOptions.getMap());
  }

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

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


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

  //建議在dispose中調(diào)用,以免占用內(nèi)存
  void destroy(){

  }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容