天天看點

Android 成功 使用GPS擷取目前地理位置(解決getLastKnownLocation 傳回 null)

轉自:http://blog.sina.com.cn/s/blog_74c22b210100sfix.html

Android 成功 使用GPS擷取目前地理位置(解決getLastKnownLocation 傳回 null)

轉載▼     自本篇部落格釋出以來,收到了很多同行的郵件,大部分都是給我要MapUtils.java檔案,或者要關于定位的Demo。以後也省的大家麻煩了,我直接把Demo挂到我的QQ雲盤上去,大家可以去那裡下載下傳。(注意該Demo無法直接運作,因為我是從項目中抽出來的,但我能保證,該Demo包含了我所有的定位代碼,自己調試吧,你懂的)...    QQ雲盤位址:http://url.cn/PU7vxq

這兩天可憋壞我了,一直愁沒什麼題材可以充實我的部落格,正巧最近遇到一個比較棘手的問題: 使用GPS定位無法擷取目前的地理位置,即getLastKnownLocation方法始終傳回null。

後來一篇博文 getLastKnownLocation()傳回null的解決 幫了我大忙,在此對該部落格作者表示感謝,但是有幾點需要注意的,我覺得有必要補充一下,否則看了這篇博文也還是得不到目前的地理位置。

第一:當使用GPS定位時,最好不要使用getLastKnownLocation方法獲得目前位置對象Location,因為該對 象可以在onLocationChanged的參數中由系統給予(根據文檔,getLastKnownLocation有2方面功能:1. 擷取目前地理位置 2.如果目前位置定位不成功,則可以用此方法擷取緩存中的上一次打開地圖時定位的地理位置)。這樣就避免了空指針異常。而且更重要的是GPS定位不是一下子就能定位成功的,在90%以上的情況下,getLastKnownLocation傳回null

第二:LocationListener 最好在Activity的onCreate()方法中進行執行個體化       實作系統的回調方法:         onLocationChanged(final Location loc)         onProviderDisabled(final String s)         onProviderEnabled(final String s)         onStatusChanged(final String s, final int i, final Bundle b)

第三:requestLocationUpdates 必須要在onResume()中進行注冊監聽. 且在onPause()中進行反注   冊。

第四:測試GPS是否定位成功,去一個空曠的地方去,不要有遮擋。這點非常重要,不然,你永遠也不知道自己GPS定位是否成功。

以下是我用GPS成功擷取目前地理位置的例子。希望能夠幫助大家擺脫GPS定位的陰霾。

@Override public void onCreate(final Bundle icicle) {          super.onCreate(icicle);          this.setContentView(R.layout.activity_mapview);

         mBtnDone =(Button) findViewById(R.id.btn_done);          mBtnDone.setOnClickListener(this);

         mapView = (MapView) findViewById(R.id.map_view);          mapView.setBuiltInZoomControls(true);          mapController = mapView.getController();          mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        mDefaultMarker = getResources().getDrawable(R.drawable.map_redpin);         mDefaultMarker.setBounds(0, 0, mDefaultMarker.getIntrinsicWidth(),         mDefaultMarker.getIntrinsicHeight());

         mBuoyOverlay = new BuoyItemizedOverlay(mDefaultMarker, this);          initDensityDpi();          mZoomLevel = mapView.getMaxZoomLevel() - 1; //  LocationListener 最好在Activity的onCreate()方法中進行執行個體化,當GPS獲得Location時,會自       動調用onLocationChanged方法.

         mLocationListener = new LocationListener() {                @Override                public void onLocationChanged(final Location loc) {                LogHelper.i(TAG, "onLocationChanged. loc: " + loc);                if (loc != null) {                              LogHelper.i(TAG, "onLocationChanged. latitude: "                                           + loc.getLatitude() + " , longtitude: ".getLongitude());                              GeoPoint geoPoint = MapUtils.getGeoPoint(loc);                              mapController.animateTo(geoPoint);                              initBuoyOverlayItems(loc);               } else {                     Toast(  MapViewActivity.this,  "Your current location is temporarily unavailable.",                           Toast.LENGTH_SHORT).show();               }          }

           // 當系統Setting -> Location & Security -> Use wireless networks取消勾選,Use GPS                             satellites取消勾選時調用            public void onProviderDisabled(final String s) {                           LogHelper.i(TAG, "onProviderDisabled. ");            }                                                  // 當系統Setting -> Location & Security -> Use wireless networks勾選,Use GPS satellites勾                選時調用             public void onProviderEnabled(final String s) {                      LogHelper.i(TAG, "onProviderEnabled. ");             }

            public void onStatusChanged(final String s, final int i, final Bundle b) {                      LogHelper.i(TAG, "onStatusChanged. ");             }            };         }

           @Override            public void onStart() {                  super.onStart();

                  mapController.setZoom(mZoomLevel);                   if (!DoSomeGoodUtils.isNetworkAvailable(this)) {                           mBtnDone.setEnabled(false);                           showDialog(DIALOG_NO_NETWORK);                  } else {                           // 判斷Use GPS satellites.是否勾選                           boolean isGpsEnabled = MapUtils.isGPSProviderAvaliable(this);                           // 判斷Use wireless networks 是否勾選                           boolean isWIFIEnabled = MapUtils.isWIFIProviderAvaliable(this);                           if (!isGpsEnabled && !isWIFIEnabled) {                                    如果都沒有勾選,則彈出對話框,提示使用者勾選。                         }                         else {                                  Location lastKnownLocation = null;                                  // 如果隻是Use GPS satellites勾選,即指允許使用GPS定位                                    if (isGpsEnabled && !isWIFIEnabled) {                                lastKnownLocation=mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);                                  mProviderName = LocationManager.GPS_PROVIDER;

                                 // 如果隻是Use wireless networks勾選,即隻允許使用網絡定位。                                 } else if(!isGpsEnabled && isWIFIEnabled){                                    lastKnownLocation =      mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);                                    mProviderName = LocationManager.NETWORK_PROVIDER;

                                   // 如果二者都勾選,優先使用GPS,因為GPS定位更精确。                               } else if (isGpsEnabled && isWIFIEnabled) {                    lastKnownLocation=mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);                              mProviderName = LocationManager.GPS_PROVIDER;                              if (lastKnownLocation == null) {                   lastKnownLocation =mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);                        mProviderName = LocationManager.NETWORK_PROVIDER;                              }             }                if (!TextUtils.isEmpty(mProviderName)) {                         mLocationManager.requestLocationUpdates(                                 mProviderName, 1000, 1, mLocationListener);                   }

               // 如果一下子就能定位成功,則執行以下代碼,當用網絡定位時,大都能一次性定位成功,當用GPS時,該代碼不會起太大作用。               if (lastKnownLocation != null) {                        mBtnDone.setEnabled(true);                      // 擷取目前地理位置                     GeoPoint lastKnownPoint = getLastKnownPoint(lastKnownLocation);                      // 以動畫方式移動到該地理位置                      mapController.animateTo(lastKnownPoint);                      // 更新浮标。該方法在這裡就不公開了。知道它的含義就行                        initBuoyOverlayItems(lastKnownLocation);               }            }          }         }

        @Override          protected void onResume() {                   super.onResume();                   LogHelper.i(TAG, "onResume. Provider Name: " + mProviderName);                if (!TextUtils.isEmpty(mProviderName)) {                  // 當GPS定位時,在這裡注冊requestLocationUpdates監聽就非常重要而且必要。 沒有這句話,定位不能成功。                     mLocationManager.requestLocationUpdates(mProviderName, 1000, 1,                              mLocationListener);                  }               }

              @Override               protected void onPause() {                  super.onPause();                  // 取消注冊監聽                  if (mLocationManager != null) {                        mLocationManager.removeUpdates(mLocationListener);                  }          } }

對于定位方式:有些同行,更傾向于使用getBestProvider方法,但是我認為這種方式有他的弊端,不是所有的手機都支援  “使用getBestProvider擷取最适合的Location” ,最好就是使用網絡定位和GPS定位....