Flutter使用百度定位经纬度数据正常,详细地址为null
更新至2021.09.07
一、问题:
(1)使用百度定位,插件返回的数据中经纬度有正常值,其他地址信息都为null
二、分析原因:
(1)在wifi或移动网络没有/不好的情况下,会出现地址返回null
https://blog.csdn.net/u013571833/article/details/56281899
(2)在设置为一次定位,获取到地址信息后停止定位,等下次点击时再重新开始定位时,偶尔会出现返回null的情况
androidOption.setScanspan(0); // 设置发起定位请求时间间隔
三、具体情况:
1、用百度定位提供的demo,雷电模拟器来测试
https://lbsyun.baidu.com/index.php?title=flutter/loc/download
2、代码
/// 设置android端和ios端定位参数
void _setLocOption() {
/// android 端设置定位参数
BaiduLocationAndroidOption androidOption = new BaiduLocationAndroidOption();
//...安卓端设置
androidOption.setScanspan(0); // 设置发起定位请求时间间隔(一次定位)
//... ios端设置
_locationPlugin.prepareLoc(androidMap, iosMap);
}
/// 启动定位 (每次点击按钮时都会触发开始定位)
void _startLocation() {
if (null != _locationPlugin) {
_setLocOption();
print('111111111111111');
_locationPlugin.startLocation();
}
}
/// 停止定位
void _stopLocation() {
if (null != _locationPlugin) {
print('333333333333333333333333');
_locationPlugin.stopLocation();
}
}
//获取定位信息
_locationListener = _locationPlugin
.onResultCallback()
.listen((Map<String, Object> result) {
print('22222222222222222222222');
print(result);
print(result['address']);
_stopLocation(); //在获取到数据之后停止定位
setState(() {
_loationResult = result;
try {
_baiduLocation = BaiduLocation.fromMap(result); // 将原生端返回的定位结果信息存储在定位结果类中
// print(_baiduLocation);
} catch (e) {
print(e);
}
});
});
3、模拟器配置
四、解决方案:
1、目前这种情况只在安卓端进行过测试,不清楚ios端是否也有同样的问题
此方案没有完全解决问题,只是做了优化。开启定时定位,在数据返回2次后获取返回给页面,手动停止定位
百度web API服务(逆地理编码) https://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding-abroad
//安卓端
//设置定时定位
androidOption.setScanspan(1000);
locationStreamSubscription =
_locationPlugin.onResultCallback().listen((event) async{
//监听到第2次数据返回时停止定位
if(count >0 || !Platform.isAndroid){
count = 0;
if(event != null && (event['errorCode'] != null || event['errorInfo'] != null)){
Toast.show('手机定位异常,麻烦检查一下手机系统或者应用的定位权限是否正常开启!定位错误码:${event['errorCode']}', context);
await Future.delayed(Duration(seconds: 2));
}else{
if(event != null && event['latitude'] != null && event['longitude'] != null){
//如果监听返回的详细地址为null,则通过百度webApi再次逆地址解析,但这种情况在无网络时无法请求
if(event['address'] == null || event['address'].toString().indexOf('null')>-1){
try{
//mcode参数,这个参数里面的内容是"SHA1;包名"
var baiduData = await Http().fetchBaiduWepApi(
'http://api.map.baidu.com/reverse_geocoding/v3/?ak=xx==ak码==&output=json&coordtype=bd09ll&location=${event['latitude']},${event['longitude']}&mcode=xxxx;xxxxx',{
"isBaiduWepApi":true,
});
if(baiduData != null && baiduData.data != null){
if(baiduData.data.runtimeType == String){
var pageData = json.decode(baiduData.data);
if(pageData != null){
if(pageData['status'] != null && pageData['status'].toString() == '0'){
if(pageData['result'] != null && pageData['result']['formatted_address'] != null){
//todo 每个属性都要复制,其他地址信息也可能为null
Map<dynamic, dynamic> addressInfo = pageData['result']['addressComponent']??{};
event['address'] = (addressInfo['formatted_address'] != null && addressInfo['formatted_address']!='')?addressInfo['formatted_address']:event['address'];
}
}
}
}else{}
}
}on ApiError catch (e){
Toast.show(e.message, context);
}catch(e){
print(e);
}
}
}
//定位第2次返回数据时,停止定位
_locationPlugin.stopLocation();
islocating = false;
}
}else{
count = 1;
}
});
2021.09.07更新
在第四点中提供的解决方案,在部分安卓机上出现bug,无法将获取到定位数据返回给对应的监听函数。暂未找出引起数据返回失败的原因,现提供另一种解决方案
//定义安卓定位时可以将请求的间隔时间弄大一点,减少返回次数,减轻手机负担
androidOption.setScanspan(1000*150);
//在监听到数据时,ios端需要立即停止
if(Platform.isIOS){
_locationPlugin.stopLocation();
}
//在重新触发开启定位时,先关闭定位,再重新开启定位
_locationPlugin.stopLocation();
startLocation();
//在页面dispose时在关闭定位
@override
void dispose() {
_locationPlugin.stopLocation();
super.dispose();
}