天天看点

重拾百度定位之踩坑篇(下)

接上文

实现bdlocationlistener接口

/***** 

     * 定位结果回调,重写onreceivelocation方法 

     * 

     */ 

    private bdlocationlistener mlistener = new bdlocationlistener() { 

        @override 

        public void onreceivelocation(bdlocation location) { 

            // todo auto-generated method stub 

            if (null != location ) { 

                stringbuffer sb = new stringbuffer(256); 

                sb.append("time : "); 

                /** 

                 * 时间也可以使用systemclock.elapsedrealtime()方法 获取的是自从开机以来,每次回调的时间; 

                 * location.gettime() 是指服务端出本次结果的时间,如果位置不发生变化,则时间不变 

                 */ 

                sb.append(location.gettime()); 

                sb.append("\nloctype : ");// 定位类型 

                sb.append(location.getloctype()); 

                sb.append("\nloctype description : ");// *****对应的定位类型说明***** 

                //sb.append(location.getloctypedescription()); 

                sb.append("\nlatitude : ");// 纬度 

                sb.append(location.getlatitude()); 

                sb.append("\nlontitude : ");// 经度 

                sb.append(location.getlongitude()); 

                sb.append("\nradius : ");// 半径 

                sb.append(location.getradius()); 

                sb.append("\ncountrycode : ");// 国家码 

                sb.append(location.getcountrycode()); 

                sb.append("\ncountry : ");// 国家名称 

                sb.append(location.getcountry()); 

                sb.append("\ncitycode : ");// 城市编码 

                sb.append(location.getcitycode()); 

                sb.append("\ncity : ");// 城市 

                sb.append(location.getcity()); 

                sb.append("\ndistrict : ");// 区 

                sb.append(location.getdistrict()); 

                sb.append("\nstreet : ");// 街道 

                sb.append(location.getstreet()); 

                sb.append("\naddr : ");// 地址信息 

                sb.append(location.getaddrstr()); 

                sb.append("\nuserindoorstate: ");// *****返回用户室内外判断结果***** 

                //sb.append(location.getuserindoorstate()); 

                sb.append("\ndirection(not all devices have value): "); 

                sb.append(location.getdirection());// 方向 

                sb.append("\nlocationdescribe: "); 

                sb.append(location.getlocationdescribe());// 位置语义化信息 

                sb.append("\npoi: ");// poi信息 

                if (location.getpoilist() != null && !location.getpoilist().isempty()) { 

                    for (int i = 0; i append(poi.getname() + ";"); 

                    } 

   } 

                if (location.getloctype() == bdlocation.typegpslocation) {// gps定位结果 

                    sb.append("\nspeed : "); 

                    sb.append(location.getspeed());// 速度 单位:km/h 

                    sb.append("\nsatellite : "); 

                    sb.append(location.getsatellitenumber());// 卫星数目 

                    sb.append("\nheight : "); 

                    sb.append(location.getaltitude());// 海拔高度 单位:米 

                    sb.append("\ngps status : "); 

                    //sb.append(location.getgpsaccuracystatus());// *****gps质量判断***** 

                    sb.append("\ndescribe : "); 

                    sb.append("gps定位成功"); 

                } else if (location.getloctype() == bdlocation.typenetworklocation) {// 网络定位结果 

                    // 运营商信息 

                    if (location.hasaltitude()) {// *****如果有海拔高度***** 

                        sb.append("\nheight : "); 

                        sb.append(location.getaltitude());// 单位:米 

                    sb.append("\noperationers : ");// 运营商信息 

                    sb.append(location.getoperators()); 

                    sb.append("网络定位成功"); 

                } else if (location.getloctype() == bdlocation.typeofflinelocation) {// 离线定位结果 

                    sb.append("离线定位成功,离线定位结果也是有效的"); 

                } else if (location.getloctype() == bdlocation.typeservererror) { 

                    sb.append("服务端网络定位失败,可以反馈imei号和大体定位时间到[email protected],会有人追查原因"); 

                } else if (location.getloctype() == bdlocation.typenetworkexception) { 

                    sb.append("网络不同导致定位失败,请检查网络是否通畅"); 

                } else if (location.getloctype() == bdlocation.typecriteriaexception) { 

                    sb.append("无法获取有效定位依据导致定位失败,一般是由于手机的原因,处于飞行模式下一般会造成这种结果,可以试着重启手机"); 

                } 

                tv_location.settext(sb+"\n定位结束"); 

                locationservice.stop(); 

            }else{ 

                tv_location.settext("\n定位失败"); 

            } 

        } 

    };  

通过上面的实现后,我们在想要定位的地方注册下回调,并调用start()方法即可以获取位置了,我对注册开始暂停做了下简单封装,具体代码参考locationservice。如果要写的项目里也要把回调接口封装,自定义一个接口回调返回定位后的详细位置信息。到这里即可成功定位了,下面就开始介绍下这个过程会出现的问题。

定位问题分析

在分析之前我们先看下百度定位返回的错误码,分析定位的问题也就是分析出现错误码的原因。

获取定位返回错误码:: 

public int getloctype ( ) 

返回值: 

61 : gps定位结果,gps定位成功。 

62 : 无法获取有效定位依据,定位失败,请检查运营商网络或者wifi网络是否正常开启,尝试重新请求定位。 

63 : 网络异常,没有成功向服务器发起请求,请确认当前测试手机网络是否通畅,尝试重新请求定位。 

65 : 定位缓存的结果。 

66 : 离线定位结果。通过requestofflinelocaiton调用时对应的返回结果。 

67 : 离线定位失败。通过requestofflinelocaiton调用时对应的返回结果。 

68 : 网络连接失败时,查找本地离线定位时对应的返回结果。 

161: 网络定位结果,网络定位成功。 

162: 请求串密文解析失败,一般是由于客户端so文件加载失败造成,请严格参照开发指南或demo开发,放入对应so文件。 

167: 服务端定位失败,请您检查是否禁用获取位置信息权限,尝试重新请求定位。 

502: ak参数错误,请按照说明文档重新申请ak。 

505:ak不存在或者非法,请按照说明文档重新申请ak。 

601: ak服务被开发者自己禁用,请按照说明文档重新申请ak。 

602: key mcode不匹配,您的ak配置过程中安全码设置有问题,请确保:sha1正确,“;”分号是英文状态;且包名是您当前运行应用的包名,请按照说明文档重新申请ak。 

501~700:ak验证失败,请按照说明文档重新申请ak。  

其实知道上面错误码代表的含义后,我们就很快速的定位问题出现地方。当然有些时候不如此,可能需要走一些弯路。

505错误

在我升级定位sdk版本后遇到得到就是这个问题,没有更改任何代码但是就是一直返回错误码是505.通过上面错误码表我们看到时ak不存在或者非法,但是依然很纠结,因为代码时点儿也没有改,只是替换了jar和.so文件为最新版就不能用了。定位一直返回505,最后在官网更新日志看到v7.0版本有一条记录 是优化、完善ak校验机制,充分保证开发者合法权益,保证开发者应用的安全性。具体怎么优化并没有说明。不过也能猜测应该是sha1的值问题。我先将demo用的定位sdk用v6.2.2(项目中用的此版本),然后更改sha1的值,不管怎么改依然能成功定位。但是更改为了v7.0版本发现sha1的值并不能随便改,只能是运行程序用的key文件的sha1的值,否则就出现505错误。至此问题解决。在v7.0之前版本虽说让填写sha1的值,但是并没有什么有效作用,在v7.0版本开始加入了严格的校验。在这里提供一个软件可以校验apk的sha1值,他提供了sha1的和ak的校验功能。

重拾百度定位之踩坑篇(下)

如上图,这上面显示的sha1的值应该和你开发版或者发布版中至少其中的一个相同。否则v7.0定位就不会成功。校验工具百度网盘下载链接,提取码:je4r。

162错误

162错误一般是.so文件加载失败引起的。在androidstudio中.so文件的位置和eclipse中的是不一样的。默认情况下,androidstudio中.so文件放在main目录下,在该文件夹下创建jnilibs,然后将不同内核的.so文件放到该文件夹下就可以了。当然一些人延续了eclipse位置,将.so文件放置在libs目录下,如果此时没有其他一些配置.so文件是不能加载的。此时再gradle文件加入下面代码即可

sourcesets { 

        main { 

            jnilibs.srcdirs = ['libs'] 

    }  

重拾百度定位之踩坑篇(下)

其实最多出现的问题也就是这两种情况。正常情况下百度定位成功返回的是161也就是网络定位结果(如上图),但是有时候无网络会返回66机离线定位结果,离线定位是小区定位,需要手机手机中有sim卡,否则不会返回66,你可以尝试下,把手机调到飞行模式,发现离线定位会失败。百度定位默认gps定位是关闭的,如果想用gps定位可以通过下面代码打开,

locationclientoption.setopengps(true); 

bdlocationlistener只回调一次

对于很多刚接触定位的人可能还会遇到一个问题就是,为何多次调用start()方法但是bdlocationlistener回调只执行一次。每次只要程序刚启动时才能定位成功。之后再定位就没有反应了。如果你第一次遇到这个问题,确实很棘手,不管怎么改定位相关的代码,并不能解决问题。其实此时只需要在清单文件加入下面代码既可以解决bdlocationlistener只会回调一次的问题

<service 

            android:name="com.baidu.location.f" 

            android:enabled="true" 

            android:process=":remote" > 

        </service>  

好了,到此,本篇文章真的结束了,若文章有不足或者错误的地方,欢迎指正,以防止给其他读者错误引导

本文作者:佚名

来源:51cto

继续阅读