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();
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值