由于众所周知的原因,国内无法使用location提供的谷歌定位服务,所以只能使用百度地图或者高德地图提供的定位服务。
所幸双方都已经实现了对flutter的支持。百度地图的api和配置比高德要简单那么一丢丢,不过包好像很久没更新,以至于错误很多。最终还是选了高德地图来实现。
官方文档地址
https://lbsyun.baidu.com/index.php?title=flutter/loc/guide/create
1. 获取Key
在控制台创建新的应用获取key
创建新应用
应用名称自定义,可以随便写。类型选择相符的就可以,这个不会严格审查的。
应用下面可以有好几个key,key的名称可以自定义,平台选择对应的平台。
申请key需要填写debug版本和release版本的keystore
安全码SHA1
我是mac,打开为项目生成的keystore文件,运行命令获取该文件sha1,我发布版和调试版都是用同一个keystore文件。
cd ~/project/flutter/xxxx
keytool -list -v -keystore xxx.keystore
PackageName
在 android/app/build.gradle 中获取包名
image提交保存后即可获得Key。
集成SDK
添加服务、声明定位权限
Android:
在 android/app/src/main/AndroidManifest.xml 文件中
1、添加服务
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="开发者申请的AK" />
2、声明权限
<!--允许访问网络,必选权限-->
<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"/>
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) {
/// 设置ios端ak, android端ak可以直接在清单文件中配置
_locationPlugin.authAK('wKcr0QantSnf00XFs9NUjelbtKKrlfOf');
}
}
/// 动态申请定位权限
Future<bool> _requestPermission() async {
status = await Permission.location.status;
if (status == PermissionStatus.granted) {
return true;
} else {
//未授权则发起一次申请
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('请在手机设置中开启“河马有有”位置权限');
}
if(isPermitted){
///注册定位结果监听
_locationPlugin.seriesLocationCallback(callback: (BaiduLocation baiduresult) {
Map result = {};
result['longitude'] = baiduresult.longitude;
result['latitude'] = baiduresult.latitude;
print("当前位置:$result");
//返回结果
onLocationChanged(result);
if (result['longitude'] != null) {
//print("当前位置:$result");
if(once) _stopLocation();
}
});
_startLocation();
}
}
///设置定位参数
void _setLocationOption() {
BaiduLocationIOSOption iosOptions =
BaiduLocationIOSOption(
// 坐标系
coordType: BMFLocationCoordType.gcj02,
// 位置获取超时时间
locationTimeout: 10,
// 获取地址信息超时时间
reGeocodeTimeout: 10,
// 应用位置类型 默认为automotiveNavigation
activityType: BMFActivityType.automotiveNavigation,
// 设置预期精度参数 默认为best
desiredAccuracy: BMFDesiredAccuracy.best,
// 是否需要最新版本rgc数据
isNeedNewVersionRgc: true,
// 指定定位是否会被系统自动暂停
pausesLocationUpdatesAutomatically: false,
// 指定是否允许后台定位,
// 允许的话是可以进行后台定位的,但需要项目
//配置允许后台定位,否则会报错,具体参考开发文档
allowsBackgroundLocationUpdates: true,
// 设定定位的最小更新距离
distanceFilter: 10,
);
BaiduLocationAndroidOption androidOptions =
BaiduLocationAndroidOption(
// 坐标系
coordType: BMFLocationCoordType.gcj02,
// 定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式
locationMode: BMFLocationMode.hightAccuracy,
// 是否需要返回地址信息
isNeedAddress: true,
// 是否需要返回海拔高度信息
isNeedAltitude: true,
// 是否需要返回周边poi信息
isNeedLocationPoiList: true,
// 是否需要返回新版本rgc信息
isNeedNewVersionRgc: true,
// 是否需要返回位置描述信息
isNeedLocationDescribe: true,
// 是否使用gps
openGps: true,
// 可选,设置场景定位参数,包括签到场景、运动场景、出行场景
//locationPurpose: BMFLocationPurpose.signIn,
// 设置发起定位请求的间隔,int类型,单位ms
// 如果设置为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中调用,以免占用内存
void destroy(){
}
}
网友评论