原文:http://blog.sina.com.cn/s/blog_74c22b210100sfix.html
这两天可憋坏我了,一直愁没什么题材可以充实我的博客,正巧最近遇到一个比较棘手的问题:
这两天可憋坏我了,一直愁没什么题材可以充实我的博客,正巧最近遇到一个比较棘手的问题:
使用GPS定位无法获取当前的地理位置,即getLastKnownLocation方法始终返回null。
后来一篇博文<wbr><a href="http://blog.sina.com.cn/s/blog_74c22b210100s8hg.html" target="_blank">getLastKnownLocation()返回null的解决</a><wbr>帮了我大忙,在此对该博客作者表示感谢,但是有几点需要注意的,我觉得有必要补充一下,否则看了这篇博文也还是得不到当前的地理位置。</wbr></wbr>
第一:当使用GPS定位时,最好不要使用getLastKnownLocation方法获得当前位置对象Location,因为该对象可以在onLocationChanged的参数中由系统给予(根据文档,getLastKnownLocation有2方面功能:1. 获取当前地理位置2.如果当前位置定位不成功,则可以用此方法获取缓存中的上一次打开地图时定位的地理位置)。这样就避免了空指针异常。而且更重要的是GPS定位不是一下子就能定位成功的,在90%以上的情况下,getLastKnownLocation返回null
第二:LocationListener最好在Activity的onCreate()方法中进行实例化
<wbr><wbr><wbr>实现系统的回调方法:</wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>onLocationChanged(finalLocation loc)</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>onProviderDisabled(final Strings)</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>onProviderEnabled(final Strings)</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>onStatusChanged(final String s,final int i, final Bundle b)</wbr></wbr></wbr></wbr></wbr>
第三:requestLocationUpdates必须要在onResume()中进行注册监听. 且在onPause()中进行反注 <wbr>册。</wbr>
第四:测试GPS是否定位成功,去一个空旷的地方去,不要有遮挡。这点非常重要,不然,你永远也不知道自己GPS定位是否成功。
以下是我用GPS成功获取当前地理位置的例子。希望能够帮助大家摆脱GPS定位的阴霾。
@Override
public void onCreate(final Bundle icicle) {
<wbr><wbr><wbr>super.onCreate(icicle);</wbr></wbr></wbr>
<wbr><wbr><wbr>this.setContentView(R.layout.activity_mapview);</wbr></wbr></wbr>
<wbr><wbr><wbr>mBtnDone =(Button) findViewById(R.id.btn_done);</wbr></wbr></wbr>
<wbr><wbr><wbr>mBtnDone.setOnClickListener(this);</wbr></wbr></wbr>
<wbr><wbr><wbr>mapView = (MapView) findViewById(R.id.map_view);</wbr></wbr></wbr>
<wbr><wbr><wbr>mapView.setBuiltInZoomControls(true);</wbr></wbr></wbr>
<wbr><wbr><wbr>mapController = mapView.getController();</wbr></wbr></wbr>
<wbr><wbr><wbr>mLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);</wbr></wbr></wbr>
<wbr><wbr><wbr>mDefaultMarker =getResources().getDrawable(R.drawable.map_redpin);</wbr></wbr></wbr>
<wbr><wbr><wbr>mDefaultMarker.setBounds(0, 0,mDefaultMarker.getIntrinsicWidth(),</wbr></wbr></wbr>
<wbr><wbr><wbr>mDefaultMarker.getIntrinsicHeight());</wbr></wbr></wbr>
<wbr><wbr><wbr>mBuoyOverlay = new BuoyItemizedOverlay(mDefaultMarker, this);</wbr></wbr></wbr>
<wbr><wbr><wbr>initDensityDpi();</wbr></wbr></wbr>
<wbr><wbr><wbr>mZoomLevel = mapView.getMaxZoomLevel() - 1;</wbr></wbr></wbr>
//<wbr>LocationListener最好在Activity的onCreate()方法中进行实例化,当GPS获得Location时,会自<wbr><wbr><wbr><wbr>动调用onLocationChanged方法.</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>mLocationListener = new LocationListener() {</wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr> @Override</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr> public voidonLocationChanged(final Location loc) {</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr> LogHelper.i(TAG,"onLocationChanged. loc: " + loc);</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr> if (loc != null) {</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>LogHelper.i(TAG, "onLocationChanged. latitude:"</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> + loc.getLatitude() + " ,longtitude: ".getLongitude());</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>GeoPoint geoPoint =MapUtils.getGeoPoint(loc);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>mapController.animateTo(geoPoint);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>initBuoyOverlayItems(loc);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>} else {</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr>Toast(<wbr>MapViewActivity.this,<wbr>"Yourcurrent location is temporarily unavailable.",</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>Toast.LENGTH_SHORT).show();</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>}</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>}</wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>// 当系统Setting -> Location& Security -> Use wirelessnetworks取消勾选,Use GPS <wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>satellites取消勾选时调用</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>public void onProviderDisabled(final String s){</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>LogHelper.i(TAG, "onProviderDisabled. ");</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>}</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr> // 当系统Setting -> Location& Security -> Use wirelessnetworks勾选,Use GPS satellites勾 <wbr><wbr><wbr><wbr><wbr> 选时调用</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr> public void onProviderEnabled(final String s){</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr> LogHelper.i(TAG, "onProviderEnabled. ");</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr> }</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr> public void onStatusChanged(final String s,final int i, final Bundle b) {</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr> LogHelper.i(TAG, "onStatusChanged. ");</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr> }</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>};</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>}</wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>@Override</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>public void onStart() {</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr>super.onStart();</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr>mapController.setZoom(mZoomLevel);</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr> if(!DoSomeGoodUtils.isNetworkAvailable(this)) {</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>mBtnDone.setEnabled(false);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>showDialog(DIALOG_NO_NETWORK);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr>} else{</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>// 判断UseGPS satellites.是否勾选</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>booleanisGpsEnabled = MapUtils.isGPSProviderAvaliable(this);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>// 判断Usewireless networks 是否勾选</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>booleanisWIFIEnabled = MapUtils.isWIFIProviderAvaliable(this);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>if(!isGpsEnabled && !isWIFIEnabled){</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>如果都没有勾选,则弹出对话框,提示用户勾选。</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> }</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> else {</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> Location lastKnownLocation =null;</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> // 如果只是Use GPSsatellites勾选,即指允许使用GPS定位</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>if(isGpsEnabled && !isWIFIEnabled){<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>lastKnownLocation=mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> mProviderName =LocationManager.GPS_PROVIDER;</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> // 如果只是Use wirelessnetworks勾选,即只允许使用网络定位。</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>} else if(!isGpsEnabled&& isWIFIEnabled){</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>lastKnownLocation = <wbr><wbr>mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>mProviderName =LocationManager.NETWORK_PROVIDER;</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>//如果二者都勾选,优先使用GPS,因为GPS定位更精确。</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> } else if (isGpsEnabled&& isWIFIEnabled){<wbr><wbr><wbr><wbr><wbr><wbr><wbr>lastKnownLocation=mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>mProviderName =LocationManager.GPS_PROVIDER;</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>if (lastKnownLocation == null) {</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr>lastKnownLocation=mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>mProviderName =LocationManager.NETWORK_PROVIDER;</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr> }</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr> if(!TextUtils.isEmpty(mProviderName)) {</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>mLocationManager.requestLocationUpdates(</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>mProviderName, 1000, 1,mLocationListener);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr> }</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr> //如果一下子就能定位成功,则执行以下代码,当用网络定位时,大都能一次性定位成功,当用GPS时,该代码不会起太大作用。</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>if (lastKnownLocation != null){</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>mBtnDone.setEnabled(true);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr> // 获取当前地理位置</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr>GeoPoint lastKnownPoint =getLastKnownPoint(lastKnownLocation);</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr> // 以动画方式移动到该地理位置</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr> mapController.animateTo(lastKnownPoint);</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr> // 更新浮标。该方法在这里就不公开了。知道它的含义就行</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>initBuoyOverlayItems(lastKnownLocation);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>}</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>}</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>}</wbr></wbr></wbr>
<wbr><wbr><wbr>}</wbr></wbr></wbr>
<wbr><wbr><wbr>@Override</wbr></wbr></wbr>
<wbr><wbr><wbr>protected void onResume() {</wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr>super.onResume();</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr>LogHelper.i(TAG, "onResume. Provider Name: " +mProviderName);</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr> if(!TextUtils.isEmpty(mProviderName)) {</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr>//当GPS定位时,在这里注册requestLocationUpdates监听就非常重要而且必要。</wbr></wbr></wbr></wbr></wbr></wbr>
没有这句话,定位不能成功。
<wbr><wbr><wbr><wbr><wbr><wbr><wbr>mLocationManager.requestLocationUpdates(mProviderName,1000, 1,</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>mLocationListener);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>}</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>@Override</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>protected void onPause(){</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr>super.onPause();</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr>//取消注册监听</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr>if(mLocationManager != null) {</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>mLocationManager.removeUpdates(mLocationListener);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>}</wbr></wbr></wbr>
}
对于定位方式:有些同行,更倾向于使用getBestProvider方法,但是我认为这种方式有他的弊端,不是所有的手机都支持<wbr> “使用getBestProvider获取最适合的Location”<wbr><span style="font-family:宋体">,最好就是使用网络定位和GPS定位</span>....</wbr></wbr>