Flutter 中集成高德定位获取地理位置
Flutter 中使用高德定位准备工作获取key
- 申请成为开发者
- 创建应用配置获取Key (参考教程演示)
Flutter 高德定位配置
官方文档:https://developer.amap.com/api/flutter/gettingstarted
https://pub.dev/packages/amap_flutter_location
配置安装依赖
dependencies: amap_flutter_location: ^3.0.0
修改你的/app/build.gradle 文件配置签名文件以及配置implementation
配置签名文件找到android /app/build.gradle 配置下面代码
signingConfigs { release {//发布版本的签名配置 storeFile file('jdshop.jks') keyAlias "仿京东商城" storePassword "123456" keyPassword "123456" } debug {//调试版本的签名配置 storeFile file('jdshop.jks') keyAlias "仿京东商城" storePassword "123456" keyPassword "123456" } } 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.release } debug { // 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 } }配置:implementation
dependencies { implementation('com.amap.api:location:5.2.0') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" }
修改你的android/app/src/main/AndroidManifest.xml
增加权限
<!--访问网络--> <uses-permission android:name="android.permission.INTERNET" /> <!--粗略定位--> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!--精确定位--> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!--申请调用A-GPS 模块--> <uses-permissionandroid:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> <!--用于获取运营商信息,用于支持提供运营商信息相关的接口--> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!--用于访问wifi 网络信息,wifi 信息会用于进行网络定位--> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!--用于获取wifi 的获取权限,wifi 信息会用来进行网络定位--> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!--用于读取手机当前的状态--> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!--用于写入缓存数据到扩展存储卡--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />配置定位Service
<application ...... <!-- 配置定位Service --> <service android:name="com.amap.api.location.APSService"/> ...... </application>注意:如果参考教程配置完毕提示下面错误
ix this issue by adding the following to \android\app\build.gradle: android { compileSdkVersion 33 ... }打开android\app\build.gradle 配置下面代码
android { compileSdkVersion 33 ... }
Flutter 高德定位源码
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
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';
void main() {
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
Map<String, Object> _locationResult;
StreamSubscription<Map<String, Object>> _locationListener;
AMapFlutterLocation _locationPlugin = new AMapFlutterLocation();
@override
void initState() {
super.initState();
//私权政策是否弹窗展示告知用户
AMapFlutterLocation.updatePrivacyShow(true, true);
// [hasAgree] 隐私权政策是否已经取得用户同意
AMapFlutterLocation.updatePrivacyAgree(true);
/// 动态申请定位权限
requestPermission();
///设置Android 和iOS 的apiKey<br>
///
/// 定位Flutter 插件提供了单独的设置ApiKey 的接口,
/// 使用接口的优先级高于通过Native 配置ApiKey 的优先级(通过Api 接口配置后,
///通过Native 配置文件设置的key 将不生效),
/// 使用时可根据实际情况决定使用哪种方式
///
///key 的申请请参考高德开放平台官网说明<br>
///
///Android:https://lbs.amap.com/api/android-location-sdk/guide/create-project/get-key
///iOS: https://lbs.amap.com/api/ios-location-sdk/guide/create-project/get-key
AMapFlutterLocation.setApiKey(
"a8879945e00xxxxxe427f4929cdc", "ios ApiKey");
///iOS 获取native 精度类型
if (Platform.isIOS) {
requestAccuracyAuthorization();
}
///注册定位结果监听
_locationListener = _locationPlugin
.onLocationChanged()
.listen((Map<String, Object> result) {
setState(() {
_locationResult = result;
});
});
}
@override
void dispose() {
super.dispose();
///移除定位监听
if (null != _locationListener) {
_locationListener.cancel();
}
///销毁定位
if (null != _locationPlugin) {
_locationPlugin.destroy();
}
}
///设置定位参数
void _setLocationOption() {
if (null != _locationPlugin) {
AMapLocationOption locationOption = new AMapLocationOption();
///是否单次定位
locationOption.onceLocation = false;
///是否需要返回逆地理信息
locationOption.needAddress = true;
///逆地理信息的语言类型
locationOption.geoLanguage = GeoLanguage.DEFAULT;
locationOption.desiredLocationAccuracyAuthorizationMode =
AMapLocationAccuracyAuthorizationMode.ReduceAccuracy;
locationOption.fullAccuracyPurposeKey = "AMapLocationScene";
///设置Android 端连续定位的定位间隔
locationOption.locationInterval = 2000;
///设置Android 端的定位模式<br>
///可选值:<br>
///<li>[AMapLocationMode.Battery_Saving]</li>
///<li>[AMapLocationMode.Device_Sensors]</li>
///<li>[AMapLocationMode.Hight_Accuracy]</li>
locationOption.locationMode = AMapLocationMode.Hight_Accuracy;
///设置iOS 端的定位最小更新距离<br>
locationOption.distanceFilter = -1;
///设置iOS 端期望的定位精度
/// 可选值:<br>
/// <li>[DesiredAccuracy.Best] 最高精度</li>
/// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度</li>
/// <li>[DesiredAccuracy.NearestTenMeters] 10 米</li>
/// <li>[DesiredAccuracy.Kilometer] 1000 米</li>
/// <li>[DesiredAccuracy.ThreeKilometers] 3000 米</li>
locationOption.desiredAccuracy = DesiredAccuracy.Best;
///设置iOS 端是否允许系统暂停定位
locationOption.pausesLocationUpdatesAutomatically = false;
///将定位参数设置给定位插件
_locationPlugin.setLocationOption(locationOption);
}
}
///开始定位
void _startLocation() {
if (null != _locationPlugin) {
///开始定位之前设置定位参数
_setLocationOption();
_locationPlugin.startLocation();
}
}
///停止定位
void _stopLocation() {
if (null != _locationPlugin) {
_locationPlugin.stopLocation();
}
}
Container _createButtonContainer() {
return new Container(
alignment: Alignment.center,
child: new Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new RaisedButton(
onPressed: _startLocation,
child: new Text('开始定位'),
color: Colors.blue,
textColor: Colors.white,
),
new Container(width: 20.0),
new RaisedButton(
onPressed: _stopLocation,
child: new Text('停止定位'),
color: Colors.blue,
textColor: Colors.white,
)
],
));
}
Widget _resultWidget(key, value) {
return new Container(
child: new Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new Container(
alignment: Alignment.centerRight,
width: 100.0,
child: new Text('$key :'),
),
new Container(width: 5.0),
new Flexible(child: new Text('$value', softWrap: true)),
],
),
);
}
@override
Widget build(BuildContext context) {
List<Widget> widgets = new List();
widgets.add(_createButtonContainer());
if (_locationResult != null) {
_locationResult.forEach((key, value) {
widgets.add(_resultWidget(key, value));
});
}
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text('AMap Location plugin example app'),
),
body: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: widgets,
),
));
}
///获取iOS native 的accuracyAuthorization 类型
void requestAccuracyAuthorization() async {
AMapAccuracyAuthorization currentAccuracyAuthorization =
await _locationPlugin.getSystemAccuracyAuthorization();
if (currentAccuracyAuthorization ==
AMapAccuracyAuthorization.AMapAccuracyAuthorizationFullAccuracy) {
print("精确定位类型");
} else if (currentAccuracyAuthorization ==
AMapAccuracyAuthorization.AMapAccuracyAuthorizationReducedAccuracy) {
print("模糊定位类型");
} else {
print("未知定位类型");
}
}
/// 动态申请定位权限
void requestPermission() async {
// 申请权限
bool hasLocationPermission = await requestLocationPermission();
if (hasLocationPermission) {
print("定位权限申请通过");
} else {
print("定位权限申请不通过");
}
}
/// 申请定位权限
/// 授予定位权限返回true, 否则返回false
Future<bool> requestLocationPermission() async {
//获取当前的权限
var 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;
}
}
}
}
Flutter Ios 项目中配置定位权限
https://lbs.amap.com/api/ios-location-sdk/guide/create-project/permission-description
配置权限
<key>UIBackgroundModes</key> <array> <string>location</string> </array> <key>NSLocationDefaultAccuracyReduced</key> <true/> <key>NSLocationWhenInUseUsageDescription</key> <string>应用需要访问定位</string> <key>NSLocationAlwaysAndWhenInUseUsageDescription</key> <string>应用需要访问定位</string> <key>allowsBackgroundLocationUpdates</key> <string>应用需要访问后台定位</string>ios 配置permission_handler 权限申请
在flutter 项目中集成了高德定位flutter SDK,在iOS 上运行第一次安装不会弹出定位请求弹窗。
解决办法:
参考:http://bbs.itying.com/topic/631987c16275cc0bec05aaa1
在iOS 项目的Podfile 中, 替换一段内容, 然后根据情况进行开启, 定位为
PERMISSION_LOCATION=1 如下:
post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) end end 替换为 post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| flutter_additional_ios_build_settings(target) # 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_h andler/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 end end
Flutter 高德定位源码
import 'package:flutter/material.dart';
import 'dart:async';
// import 'dart:io';
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 LocationPage extends StatefulWidget {
const LocationPage({Key? key}) : super(key: key);
@override
State<LocationPage> createState() => _LocationPageState();
}
class _LocationPageState extends State<LocationPage> {
//获取数据
// Map<String, Object> _locationResult;
//
String _latitude=""; //纬度
String _longitude=""; //经度
//监听定位
late StreamSubscription<Map<String, Object>> _locationListener;
//实例化插件
final AMapFlutterLocation _locationPlugin = AMapFlutterLocation();
@override
void initState() {
// TODO: implement initState
super.initState();
//私权政策是否弹窗展示告知用户
AMapFlutterLocation.updatePrivacyShow(true, true);
// [hasAgree] 隐私权政策是否已经取得用户同意
AMapFlutterLocation.updatePrivacyAgree(true);
/// 动态申请定位权限
requestPermission();
AMapFlutterLocation.setApiKey(
"8d75a9a37463f51c864b8af2a735f3be", "ios ApiKey");
///注册定位结果监听
_locationListener = _locationPlugin
.onLocationChanged()
.listen((Map<String, Object> result) {
setState(() {
print(result);
print("-----");
print(result is Map);
// _locationResult = result;
_latitude=result["latitude"].toString();
_longitude=result["longitude"].toString();
});
});
}
@override
void dispose() {
super.dispose();
///移除定位监听
if (null != _locationListener) {
_locationListener.cancel();
}
///销毁定位
if (null != _locationPlugin) {
_locationPlugin.destroy();
}
}
///设置定位参数
void _setLocationOption() {
if (null != _locationPlugin) {
AMapLocationOption locationOption = new AMapLocationOption();
///是否单次定位
locationOption.onceLocation = false;
///是否需要返回逆地理信息
locationOption.needAddress = true;
///逆地理信息的语言类型
locationOption.geoLanguage = GeoLanguage.DEFAULT;
locationOption.desiredLocationAccuracyAuthorizationMode =
AMapLocationAccuracyAuthorizationMode.ReduceAccuracy;
locationOption.fullAccuracyPurposeKey = "AMapLocationScene";
///设置Android 端连续定位的定位间隔
locationOption.locationInterval = 2000;
///设置Android 端的定位模式<br>
///可选值:<br>
///<li>[AMapLocationMode.Battery_Saving]</li>
///<li>[AMapLocationMode.Device_Sensors]</li>
///<li>[AMapLocationMode.Hight_Accuracy]</li>
locationOption.locationMode = AMapLocationMode.Hight_Accuracy;
///设置iOS 端的定位最小更新距离<br>
locationOption.distanceFilter = -1;
///设置iOS 端期望的定位精度
/// 可选值:<br>
/// <li>[DesiredAccuracy.Best] 最高精度</li>
/// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度</li>
/// <li>[DesiredAccuracy.NearestTenMeters] 10 米</li>
/// <li>[DesiredAccuracy.Kilometer] 1000 米</li>
/// <li>[DesiredAccuracy.ThreeKilometers] 3000 米</li>
locationOption.desiredAccuracy = DesiredAccuracy.Best;
///设置iOS 端是否允许系统暂停定位
locationOption.pausesLocationUpdatesAutomatically = false;
///将定位参数设置给定位插件
_locationPlugin.setLocationOption(locationOption);
}
}
///开始定位
void _startLocation() {
if (null != _locationPlugin) {
///开始定位之前设置定位参数
_setLocationOption();
_locationPlugin.startLocation();
}
}
/// 动态申请定位权限
void requestPermission() async {
// 申请权限
bool hasLocationPermission = await requestLocationPermission();
if (hasLocationPermission) {
print("定位权限申请通过");
} else {
print("定位权限申请不通过");
}
}
/// 申请定位权限授予定位权限返回true, 否则返回false
Future<bool> requestLocationPermission() async {
//获取当前的权限
var 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;
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("地理定位演示"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// latitude: 36.570091461155336, longitude: 109.5080830206976
//
Text("纬度:$_latitude"),
Text("经度:$_longitude"),
const SizedBox(height: 20),
ElevatedButton(
child: const Text('开始定位'),
onPressed: () {
_startLocation();
},
),
],
),
),
);
}
}