轉自:http://blog.sina.com.cn/s/blog_74c22b210100sfix.html
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5ycuFmc091Zz9CXu9Wbt92Yvw1cldWYtl2LcVGb5R3c3c2bsJ2Lc52YuMnah5Waz5yZtl2cvw1LcpDc0RHaiojIsJye.gif)
轉載▼ 自本篇部落格釋出以來,收到了很多同行的郵件,大部分都是給我要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定位....