重拾百度定位之踩坑篇(下)
接上文
實現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("\ndescribe : ");
- sb.append("網絡定位成功");
- } else if (location.getLocType() == BDLocation.TypeOffLineLocation) {// 離線定位結果
- sb.append("\ndescribe : ");
- sb.append("離線定位成功,離線定位結果也是有效的");
- } else if (location.getLocType() == BDLocation.TypeServerError) {
- sb.append("\ndescribe : ");
- sb.append("服務端網絡定位失敗,可以反饋IMEI號和大體定位時間到loc-bugs@baidu.com,會有人追查原因");
- } else if (location.getLocType() == BDLocation.TypeNetWorkException) {
- sb.append("\ndescribe : ");
- sb.append("網絡不同導致定位失敗,請檢查網絡是否通暢");
- } else if (location.getLocType() == BDLocation.TypeCriteriaException) {
- sb.append("\ndescribe : ");
- 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>
好了,到此,本篇文章真的結束了,若文章有不足或者錯誤的地方,歡迎指正,以防止給其他讀者錯誤引導