android定位的实现

标签:定位AndroidlocationgetLastKnownLocationgps 30348人阅读 评论(25) 收藏 举报 分类: android(12)

基于android的定位无非就两种:network、gps。两者各有优劣。

Network:定位快,准确度低,受环境影响小。

GPS:定位慢,准确度高,受环境影响大。


本文要解决的问题:

1.locationManager.getLastKnownLocation方法返回null。

2.如何实现快速而又精确的定位。

E文好的话,直接看官网就好了http://developer.android.com/guide/topics/location/strategies.html

在你的程序里如果有这样的代码你就要注意了(现在看来这些倒是多余了)

[java] view plain copy
  1. Criteriacriteria=newCriteria();
  2. criteria.setAccuracy(Criteria.ACCURACY_FINE);//高精度
  3. criteria.setAltitudeRequired(false);//无海拔要求
  4. criteria.setBearingRequired(false);//无方位要求
  5. criteria.setCostAllowed(true);//允许产生资费
  6. criteria.setPowerRequirement(Criteria.POWER_LOW);//低功耗
  7. //获取最佳服务对象
  8. Stringprovider=locationManager.getBestProvider(criteria,true);
  9. locationManager.getLastKnownLocation(provider);

locationManager.getBestProvider(criteria,true);方法看起来很完美,但其实返回值就network、gps二选一。而且如果你要求高精度,它会优先检查GPS,如果手机开启了GPS就返回GPS,否则返回network。如果都没开启则返回null。

结合Network、GPS两种定位方式的优劣不难看出为什么getLastKnownLocation方法会返回null(这只针对第一次定位)。

当你开启GPS,provider的值为GPS。这时的定位方式为GPS,由于GPS定位慢(我测试的时间大约为50秒),所以它不可能立即返回你一个Location对象,所以就返回null了。还有人用下面的方法解决这个问题:

[java] view plain copy
  1. while(location==null){
  2. location=locationManager.getLastKnownLocation(provider);
  3. }

这绝对是个愚蠢的做法!举个例子:如果你在室内,gps无法定位到,你的程序将陷入死循环。当然使用requestLocationUpdates可以做到定位且不让程序陷入死循环,但是定位耗时长,甚至得不到定位。

如果使用网络定位呢,不得说这也是一个不错的选择。locationManager.requestLocationUpdates(

LocationManager.NETWORK_PROVIDER, 0, 0,networkListener);

网络定位耗时一般在2秒左右(网络差,时间会更长),只要你接入网络,基本上都能获得定位。唯一的缺点就是精度不高。

那能不能将两者结合,这也是本文的重点。既然结合两者,就要同时为两者添加监听

[java] view plain copy
  1. locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000*2,50,gpsListener);
  2. locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0,0,networkListener);

这样,大概2秒我们就可以得到来自网络的定位,一分钟后得到来自GPS定位。这时用GPS定位替换网络定位就好了。当然这只是个理想的情况,现实要复杂的多。

比如:

你第一次定位成功返回location,由于网络问题第二次返回null。这时会发现,更新的location没有上次的精确,甚至是null,无法使用,这时我们要判断当前的location和新获得的location那个更好。可能你获得GPS定位后,由于天气、进入隧道等原因GPS服务器丢失,无法更新location(这时一个好的做法是切换到network定位)。还有可能用户没有开启GPS和network,根本就谈不上定位(其实每次定位成功都会有个定位缓存的,可以使用getLastKnownLocation获得)。

终上所述,我们要做的就是:

1. 尝试通过getLastKnownLocation获取上次定位信息

2. 开启network和gps监听

3. 获得network定位信息location

4. 比较当前location和新获取的location哪个更好(来自network)

5. 获得gps定位信息location

6. 停掉network监听

7. 比较当前location和新获取的location哪个更好(来自gps)

8. 如果gps服务器丢失,重新开启network监听


以GPS监听为例

[java] view plain copy
  1. //GPS监听的回调函数
  2. privateclassGPSLocationListenerimplementsLocationListener{
  3. privatebooleanisRemove=false;//判断网络监听是否移除
  4. @Override
  5. publicvoidonLocationChanged(Locationlocation){
  6. //TODOAuto-generatedmethodstub
  7. booleanflag=betterLocation.isBetterLocation(location,
  8. currentBestLocation);
  9. if(flag){
  10. currentBestLocation=location;
  11. updateLocation(currentBestLocation);
  12. }
  13. //获得GPS服务后,移除network监听
  14. if(location!=null&&!isRemove){
  15. locationManager.removeUpdates(networkListener);
  16. isRemove=true;
  17. }
  18. }
  19. @Override
  20. publicvoidonProviderDisabled(Stringprovider){
  21. //TODOAuto-generatedmethodstub
  22. }
  23. @Override
  24. publicvoidonProviderEnabled(Stringprovider){
  25. //TODOAuto-generatedmethodstub
  26. }
  27. @Override
  28. publicvoidonStatusChanged(Stringprovider,intstatus,Bundleextras){
  29. //TODOAuto-generatedmethodstub
  30. if(LocationProvider.OUT_OF_SERVICE==status){
  31. Toast.makeText(MainActivity.this,"GPS服务丢失,切换至网络定位",
  32. Toast.LENGTH_SHORT).show();
  33. locationManager
  34. .requestLocationUpdates(
  35. LocationManager.NETWORK_PROVIDER,0,0,
  36. networkListener);
  37. }
  38. }
  39. }

其中isBetterLocation是用来判断哪个location更好的。这个方法来自android官网的,通过location获取的时间,精度等信息进行判断。

因为之前上传的demo,大家觉得意义不大,所以就不再提供了。

下图的‘微秒’单位错了,应该是毫秒

android定位的实现_第1张图片

后来我接触的项目中对定位的要求发现并不是那么高,只是需要简单的获取到当前位置就够了,而且只是在每次启动时获取一次。

Android简单定位的实现可以参见http://blog.csdn.net/limb99/article/details/18819925




2
0

更多相关文章

  1. Android中的几种网络请求方式详解
  2. Android锁定横竖屏、splash,全屏、去除标题的方法-网摘
  3. Android中设置控件透明度的方法
  4. Android进程so注入Hook java方法
  5. Android JNI使用方法
  6. Android 布局中的android:onClick的使用方法总结
  7. Android工程手动增加插件包方法

随机推荐

  1. Android的事件转递机制
  2. Android(安卓)- Activity 的 Launch mode
  3. Android:activity,fragment和service之我
  4. Android:使用ViewPager实现左右滑动切换图
  5. 《Android开发从零开始》――10. LinearL
  6. Android 学习笔记--android――listview
  7. Deepin Android Studio 修改默认源 提高
  8. Android UI之ImageView旋转的几种方式
  9. Android中SensorManager.getRotationMatr
  10. 关于android中的各种路径对应的方法