由於眾所周知的原因,國內無法使用location提供的谷歌定位服務,所以只能使用百度地圖或者高德地圖提供的定位服務。
所幸雙方都已經實現了對flutter的支持。百度地圖的api和配置比高德要簡單那么一丟丟,不過包好像很久沒更新,以至於錯誤很多。最終還是選了高德地圖來實現。
官方文檔地址
https://lbs.amap.com/api/flutter/gettingstarted
1. 獲取高德Key
在控制台創建新的應用獲取key
創建新應用
應用名稱自定義,可以隨便寫。類型選擇相符的就可以,這個不會嚴格審查的。
應用下面可以有好幾個key,key的名稱可以自定義,平台選擇對應的平台。
調試版安全碼SHA1
進入當前用戶文件夾下的.android目錄,通常是 C:\Users\**\.android,運行命令
keytool -list -v -keystore debug.keystore
輸入密鑰口令,默認是 android,即可獲得SHA1安全碼
發布版安全碼SHA1
同樣的方法,找到發布過程中生成的upload-keystore.jks文件,在文件目錄下運行
keytool -list -v -keystore upload-keystore.jks
即可得到發布版安全碼。
PackageName
在 android/app/build.gradle 中獲取包名
提交保存后即可獲得Key。
集成SDK
在 android/build.gradle 文件中,添加mavenCentral()或者 jcenter()
allprojects { repositories { jcenter() // 或者 mavenCentral() } }
在 android/app/build.gradle 中,配置依賴:
dependencies {
...
implementation 'com.amap.api:location:latest.integration'
}
添加高德 Key
在 android/app/src/main/AndroidManifest.xml 文件中,添加剛剛獲取到的key,並配置定位服務。
<application android:label="****" android:icon="@mipmap/ic_launcher"
android:networkSecurityConfig="@xml/network_security_config">
<!-- 配置高德地圖ApiKey -->
<meta-data android:name="com.amap.api.v2.apikey" android:value="****"/>
<!-- 配置定位Service -->
<service android:name="com.amap.api.location.APSService"/>
聲明定位權限
在 android/app/src/main/AndroidManifest.xml 文件中,聲明權限
點擊查看代碼
<!--允許訪問網絡,必選權限-->
<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"/>
引入高德定位Flutter插件
# 高德地圖
amap_flutter_location: ^3.0.0
獲取定位
點擊查看代碼
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';
class LocationService {
StreamSubscription<Map<String, Object>>? _locationListener;
final AMapFlutterLocation _locationPlugin = AMapFlutterLocation();
PermissionStatus? status;
/// 動態申請定位權限
Future<bool> _requestPermission() async {
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;
}
}
}
Future<void> run() async {
/// 設置是否已經包含高德隱私政策並彈窗展示顯示用戶查看,如果未包含或者沒有彈窗展示,高德定位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);
bool isPermitted = await _requestPermission();
if(isPermitted){
///注冊定位結果監聽
_locationListener = _locationPlugin.onLocationChanged().listen((Map<String, Object> result) {
if (result['adCode'] != null) {
String adCode = result['adCode'].toString();
print("當前位置:$adCode");
_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(); // 停止定位
}
}
}
在main.dart中使用
點擊查看代碼
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final LocationService _locationService = LocationService();
@override
void initState() {
super.initState();
_locationService.run();
}
@override
void dispose() {
_locationService.cancel();
super.dispose();
}
}