分享

教程:实现Android的不同精度的定位(基于网络和GPS)

 quasiceo 2016-05-24
2012-05-31 23:18 3440人阅读 评论(0) 收藏 举报
分类:

目录(?)[+]

http://www./blog/foundation/tutorial-location-service/

在之前的教程《进阶:如何编程实现开启或关闭GPS?》中,讲述了GPS开关的问题,包括了Android 2.2以及之前版本的2种不同的开关方法。虽然我说过在官方的Dev Guide中有相当详细的Location定位的说明,不过我决定还是将这个教程补齐。
在本教程中,我会分别讲述如何开启位置服务的监听,如何停止监听,如何获得不同精度的定位,以及如何判断定位是否更精确。
Android中的定位服务的相关类基本上都在android.location包中,下面会按编写的顺序依次讲解。

位置服务管理器(LocationManager)

首先,我们需要1个LocationManager,考虑到它会被多个方法使用,我们将它定义成Activity的Field。然后在onCreate方法中为它赋值。

1
2
3
4
5
  1. <span style="color:#666666; font-style:italic">//变量定义</span>  
  2. <span style="color:#000000; font-weight:bold">private</span> LocationManager locationManager<span style="color:#339933">;</span>  
  3. <span style="color:#666666; font-style:italic">//得到LocationManager</span>  
  4. locationManager <span style="color:#339933">=</span> <span style="color:#0990">(</span>LocationManager<span style="color:#0990">)</span> <span style="color:#000000; font-weight:bold">this</span>  
  5.         .<span style="color:#06633">getSystemService</span><span style="color:#0990">(</span><span style="color:#03399">Context</span>.<span style="color:#06633">LOCATION_SERVICE</span><span style="color:#0990">)</span><span style="color:#339933">;</span>  

开启位置服务的监听

有了LocationManager之后,我们就可以开始监听位置的变化了。我们使用LocationManager中的方法:
requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)
来设置监听器。
首先,我们要注意到第1个参数,这个参数的值为2选1,分别是:LocationManager.NETWORK_PROVIDER和LocationManager.GPS_PROVIDER,前者用于移动网络中获取位置精度较低但速度很快,后者使用GPS进行定位,精度很高但一般需要10-60秒时间才能开始第1次定位,如果是在室内则基本上无法定位。
这2种Provider本质上是互补的,在本教程中,我们会同时开启2个监听,但基于移动网络的监听只会执行一次就会被停止,而基于GPS的监听则会一直持续下去,直至用户自己停止监听。
代码片段如下:
首先,我们会声明1个监听器的内部类,这个类会同时用于2种模式的监听。还要声明1个变量,用于记录当前的位置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  1. <span style="color:#000000; font-weight:bold">private</span> <span style="color:#000000; font-weight:bold">class</span> MyLocationListner <span style="color:#000000; font-weight:bold">implements</span> LocationListener<span style="color:#0990">{</span>  
  2.     @Override  
  3.     <span style="color:#000000; font-weight:bold">public</span> <span style="color:#0066; font-weight:bold">void</span> onLocationChanged<span style="color:#0990">(</span>Location location<span style="color:#0990">)</span> <span style="color:#0990">{</span>  
  4.         <span style="color:#666666; font-style:italic">// Called when a new location is found by the location provider.</span>  
  5.         Log.<span style="color:#06633">v</span><span style="color:#0990">(</span><span style="color:#00ff">"GPSTEST"</span>, <span style="color:#00ff">"Got New Location of provider:"</span><span style="color:#339933">+</span>location.<span style="color:#06633">getProvider</span><span style="color:#0990">(</span><span style="color:#0990">)</span><span style="color:#0990">)</span><span style="color:#339933">;</span>  
  6.         <span style="color:#000000; font-weight:bold">if</span><span style="color:#0990">(</span>currentLocation<span style="color:#339933">!=</span><span style="color:#0066; font-weight:bold">null</span><span style="color:#0990">)</span><span style="color:#0990">{</span>  
  7.             <span style="color:#000000; font-weight:bold">if</span><span style="color:#0990">(</span>isBetterLocation<span style="color:#0990">(</span>location, currentLocation<span style="color:#0990">)</span><span style="color:#0990">)</span><span style="color:#0990">{</span>  
  8.                 Log.<span style="color:#06633">v</span><span style="color:#0990">(</span><span style="color:#00ff">"GPSTEST"</span>, <span style="color:#00ff">"It's a better location"</span><span style="color:#0990">)</span><span style="color:#339933">;</span>  
  9.                 currentLocation<span style="color:#339933">=</span>location<span style="color:#339933">;</span>  
  10.                 showLocation<span style="color:#0990">(</span>location<span style="color:#0990">)</span><span style="color:#339933">;</span>  
  11.             <span style="color:#0990">}</span>  
  12.             <span style="color:#000000; font-weight:bold">else</span><span style="color:#0990">{</span>  
  13.                 Log.<span style="color:#06633">v</span><span style="color:#0990">(</span><span style="color:#00ff">"GPSTEST"</span>, <span style="color:#00ff">"Not very good!"</span><span style="color:#0990">)</span><span style="color:#339933">;</span>  
  14.             <span style="color:#0990">}</span>  
  15.         <span style="color:#0990">}</span>  
  16.         <span style="color:#000000; font-weight:bold">else</span><span style="color:#0990">{</span>  
  17.             Log.<span style="color:#06633">v</span><span style="color:#0990">(</span><span style="color:#00ff">"GPSTEST"</span>, <span style="color:#00ff">"It's first location"</span><span style="color:#0990">)</span><span style="color:#339933">;</span>  
  18.             currentLocation<span style="color:#339933">=</span>location<span style="color:#339933">;</span>  
  19.             showLocation<span style="color:#0990">(</span>location<span style="color:#0990">)</span><span style="color:#339933">;</span>  
  20.         <span style="color:#0990">}</span>  
  21.         <span style="color:#666666; font-style:italic">//移除基于LocationManager.NETWORK_PROVIDER的监听器</span>  
  22.         <span style="color:#000000; font-weight:bold">if</span><span style="color:#0990">(</span>LocationManager.<span style="color:#06633">NETWORK_PROVIDER</span>.<span style="color:#06633">equals</span><span style="color:#0990">(</span>location.<span style="color:#06633">getProvider</span><span style="color:#0990">(</span><span style="color:#0990">)</span><span style="color:#0990">)</span><span style="color:#0990">)</span><span style="color:#0990">{</span>  
  23.             locationManager.<span style="color:#06633">removeUpdates</span><span style="color:#0990">(</span><span style="color:#000000; font-weight:bold">this</span><span style="color:#0990">)</span><span style="color:#339933">;</span>  
  24.         <span style="color:#0990">}</span>  
  25.     <span style="color:#0990">}</span>  
  26.    
  27.     <span style="color:#666666; font-style:italic">//后3个方法此处不做处理</span>  
  28.     <span style="color:#000000; font-weight:bold">public</span> <span style="color:#0066; font-weight:bold">void</span> onStatusChanged<span style="color:#0990">(</span><span style="color:#03399">String</span> provider, <span style="color:#0066; font-weight:bold">int</span> status, Bundle extras<span style="color:#0990">)</span> <span style="color:#0990">{</span>  
  29.     <span style="color:#0990">}</span>  
  30.    
  31.     <span style="color:#000000; font-weight:bold">public</span> <span style="color:#0066; font-weight:bold">void</span> onProviderEnabled<span style="color:#0990">(</span><span style="color:#03399">String</span> provider<span style="color:#0990">)</span> <span style="color:#0990">{</span>  
  32.     <span style="color:#0990">}</span>  
  33.    
  34.     <span style="color:#000000; font-weight:bold">public</span> <span style="color:#0066; font-weight:bold">void</span> onProviderDisabled<span style="color:#0990">(</span><span style="color:#03399">String</span> provider<span style="color:#0990">)</span> <span style="color:#0990">{</span>  
  35.     <span style="color:#0990">}</span>  
  36. <span style="color:#0990">}</span><span style="color:#339933">;</span>  
  37. Location currentLocation<span style="color:#339933">;</span>  
  38. <span style="color:#000000; font-weight:bold">private</span> <span style="color:#0066; font-weight:bold">void</span> showLocation<span style="color:#0990">(</span>Location location<span style="color:#0990">)</span><span style="color:#0990">{</span>  
  39.     <span style="color:#666666; font-style:italic">//纬度</span>  
  40.     Log.<span style="color:#06633">v</span><span style="color:#0990">(</span><span style="color:#00ff">"GPSTEST"</span>,<span style="color:#00ff">"Latitude:"</span><span style="color:#339933">+</span>location.<span style="color:#06633">getLatitude</span><span style="color:#0990">(</span><span style="color:#0990">)</span><span style="color:#0990">)</span><span style="color:#339933">;</span>  
  41.     <span style="color:#666666; font-style:italic">//经度</span>  
  42.     Log.<span style="color:#06633">v</span><span style="color:#0990">(</span><span style="color:#00ff">"GPSTEST"</span>,<span style="color:#00ff">"Longitude:+location.getLongitude());  
  43.     //精确度  
  44.     Log.v("</span>GPSTEST<span style="color:#00ff">","</span>Accuracy<span style="color:#339933">:</span><span style="color:#00ff">"+location.getAccuracy());  
  45.     //Location还有其它属性,请自行探索  
  46. }</span>  

开始监听的代码片段:

1
2
3
4
5
6
7
8
  1. <span style="color:#000000; font-weight:bold">private</span> LocationListener gpsListener<span style="color:#339933">=</span><span style="color:#0066; font-weight:bold">null</span><span style="color:#339933">;</span>  
  2. <span style="color:#000000; font-weight:bold">private</span> LocationListener networkListner<span style="color:#339933">=</span><span style="color:#0066; font-weight:bold">null</span><span style="color:#339933">;</span>  
  3. <span style="color:#000000; font-weight:bold">private</span> <span style="color:#0066; font-weight:bold">void</span> registerLocationListener<span style="color:#0990">(</span><span style="color:#0990">)</span><span style="color:#0990">{</span>  
  4.     networkListner<span style="color:#339933">=</span><span style="color:#000000; font-weight:bold">new</span> MyLocationListner<span style="color:#0990">(</span><span style="color:#0990">)</span><span style="color:#339933">;</span>  
  5.     locationManager.<span style="color:#06633">requestLocationUpdates</span><span style="color:#0990">(</span>LocationManager.<span style="color:#06633">NETWORK_PROVIDER</span>, <span style="color:#cc66cc">3000</span>, <span style="color:#cc66cc">0</span>, networkListner<span style="color:#0990">)</span><span style="color:#339933">;</span>  
  6.     gpsListener<span style="color:#339933">=</span><span style="color:#000000; font-weight:bold">new</span> MyLocationListner<span style="color:#0990">(</span><span style="color:#0990">)</span><span style="color:#339933">;</span>  
  7.     locationManager.<span style="color:#06633">requestLocationUpdates</span><span style="color:#0990">(</span>LocationManager.<span style="color:#06633">GPS_PROVIDER</span>, <span style="color:#cc66cc">5000</span>, <span style="color:#cc66cc">0</span>, gpsListener<span style="color:#0990">)</span><span style="color:#339933">;</span>  
  8. <span style="color:#0990">}</span>  

以上的代码还是很易懂的吧,创建1个监听器对象,然后指定1个provider,然后requestLocationUpdates。在监听器中检查如果是NETWORK_PROVIDER,则取消监听,只留GPS的监听(在你的实际应用中可以根据情况来进行,因为GPS有可能会因为建筑的阻挡而暂时不工作)。

位置精度的判断

在showLocation方法中,我们打印了location的Accuracy属性,这就是精确度,一般来说NETWORK得到的位置精度一般在500-1000米,GPS得到的精度一般在5-50米,基于这个属性我们可以对精度进行判断,以决定是否采用这个精度。
你可能已经注意到上面的代码中有1个isBetterLocation方法,这是用来判断获取的位置是否更好,事实上这个方法来自于Dev Guide。我们看下这个方法的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  1. <span style="color:#000000; font-weight:bold">private</span> <span style="color:#000000; font-weight:bold">static</span> <span style="color:#000000; font-weight:bold">final</span> <span style="color:#0066; font-weight:bold">int</span> CHECK_INTERVAL <span style="color:#339933">=</span> <span style="color:#cc66cc">1000</span> <span style="color:#339933">*</span> <span style="color:#cc66cc">30</span><span style="color:#339933">;</span>  
  2. <span style="color:#000000; font-weight:bold">protected</span> <span style="color:#0066; font-weight:bold">boolean</span> isBetterLocation<span style="color:#0990">(</span>Location location,  
  3.         Location currentBestLocation<span style="color:#0990">)</span> <span style="color:#0990">{</span>  
  4.     <span style="color:#000000; font-weight:bold">if</span> <span style="color:#0990">(</span>currentBestLocation <span style="color:#339933">==</span> <span style="color:#0066; font-weight:bold">null</span><span style="color:#0990">)</span> <span style="color:#0990">{</span>  
  5.         <span style="color:#666666; font-style:italic">// A new location is always better than no location</span>  
  6.         <span style="color:#000000; font-weight:bold">return</span> <span style="color:#0066; font-weight:bold">true</span><span style="color:#339933">;</span>  
  7.     <span style="color:#0990">}</span>  
  8.   
  9.     <span style="color:#666666; font-style:italic">// Check whether the new location fix is newer or older</span>  
  10.     <span style="color:#0066; font-weight:bold">long</span> timeDelta <span style="color:#339933">=</span> location.<span style="color:#06633">getTime</span><span style="color:#0990">(</span><span style="color:#0990">)</span> <span style="color:#339933">-</span> currentBestLocation.<span style="color:#06633">getTime</span><span style="color:#0990">(</span><span style="color:#0990">)</span><span style="color:#339933">;</span>  
  11.     <span style="color:#0066; font-weight:bold">boolean</span> isSignificantlyNewer <span style="color:#339933">=</span> timeDelta <span style="color:#339933">></span> CHECK_INTERVAL<span style="color:#339933">;</span>  
  12.     <span style="color:#0066; font-weight:bold">boolean</span> isSignificantlyOlder <span style="color:#339933">=</span> timeDelta <span style="color:#339933"><</span> <span style="color:#339933">-</span>CHECK_INTERVAL<span style="color:#339933">;</span>  
  13.     <span style="color:#0066; font-weight:bold">boolean</span> isNewer <span style="color:#339933">=</span> timeDelta <span style="color:#339933">></span> <span style="color:#cc66cc">0</span><span style="color:#339933">;</span>  
  14.   
  15.     <span style="color:#666666; font-style:italic">// If it's been more than two minutes since the current location,</span>  
  16.     <span style="color:#666666; font-style:italic">// use the new location</span>  
  17.     <span style="color:#666666; font-style:italic">// because the user has likely moved</span>  
  18.     <span style="color:#000000; font-weight:bold">if</span> <span style="color:#0990">(</span>isSignificantlyNewer<span style="color:#0990">)</span> <span style="color:#0990">{</span>  
  19.         <span style="color:#000000; font-weight:bold">return</span> <span style="color:#0066; font-weight:bold">true</span><span style="color:#339933">;</span>  
  20.         <span style="color:#666666; font-style:italic">// If the new location is more than two minutes older, it must</span>  
  21.         <span style="color:#666666; font-style:italic">// be worse</span>  
  22.     <span style="color:#0990">}</span> <span style="color:#000000; font-weight:bold">else</span> <span style="color:#000000; font-weight:bold">if</span> <span style="color:#0990">(</span>isSignificantlyOlder<span style="color:#0990">)</span> <span style="color:#0990">{</span>  
  23.         <span style="color:#000000; font-weight:bold">return</span> <span style="color:#0066; font-weight:bold">false</span><span style="color:#339933">;</span>  
  24.     <span style="color:#0990">}</span>  
  25.   
  26.     <span style="color:#666666; font-style:italic">// Check whether the new location fix is more or less accurate</span>  
  27.     <span style="color:#0066; font-weight:bold">int</span> accuracyDelta <span style="color:#339933">=</span> <span style="color:#0990">(</span><span style="color:#0066; font-weight:bold">int</span><span style="color:#0990">)</span> <span style="color:#0990">(</span>location.<span style="color:#06633">getAccuracy</span><span style="color:#0990">(</span><span style="color:#0990">)</span> <span style="color:#339933">-</span> currentBestLocation  
  28.             .<span style="color:#06633">getAccuracy</span><span style="color:#0990">(</span><span style="color:#0990">)</span><span style="color:#0990">)</span><span style="color:#339933">;</span>  
  29.     <span style="color:#0066; font-weight:bold">boolean</span> isLessAccurate <span style="color:#339933">=</span> accuracyDelta <span style="color:#339933">></span> <span style="color:#cc66cc">0</span><span style="color:#339933">;</span>  
  30.     <span style="color:#0066; font-weight:bold">boolean</span> isMoreAccurate <span style="color:#339933">=</span> accuracyDelta <span style="color:#339933"><</span> <span style="color:#cc66cc">0</span><span style="color:#339933">;</span>  
  31.     <span style="color:#0066; font-weight:bold">boolean</span> isSignificantlyLessAccurate <span style="color:#339933">=</span> accuracyDelta <span style="color:#339933">></span> <span style="color:#cc66cc">200</span><span style="color:#339933">;</span>  
  32.   
  33.     <span style="color:#666666; font-style:italic">// Check if the old and new location are from the same provider</span>  
  34.     <span style="color:#0066; font-weight:bold">boolean</span> isFromSameProvider <span style="color:#339933">=</span> isSameProvider<span style="color:#0990">(</span>location.<span style="color:#06633">getProvider</span><span style="color:#0990">(</span><span style="color:#0990">)</span>,  
  35.             currentBestLocation.<span style="color:#06633">getProvider</span><span style="color:#0990">(</span><span style="color:#0990">)</span><span style="color:#0990">)</span><span style="color:#339933">;</span>  
  36.   
  37.     <span style="color:#666666; font-style:italic">// Determine location quality using a combination of timeliness and</span>  
  38.     <span style="color:#666666; font-style:italic">// accuracy</span>  
  39.     <span style="color:#000000; font-weight:bold">if</span> <span style="color:#0990">(</span>isMoreAccurate<span style="color:#0990">)</span> <span style="color:#0990">{</span>  
  40.         <span style="color:#000000; font-weight:bold">return</span> <span style="color:#0066; font-weight:bold">true</span><span style="color:#339933">;</span>  
  41.     <span style="color:#0990">}</span> <span style="color:#000000; font-weight:bold">else</span> <span style="color:#000000; font-weight:bold">if</span> <span style="color:#0990">(</span>isNewer <span style="color:#339933">&&</span> <span style="color:#339933">!</span>isLessAccurate<span style="color:#0990">)</span> <span style="color:#0990">{</span>  
  42.         <span style="color:#000000; font-weight:bold">return</span> <span style="color:#0066; font-weight:bold">true</span><span style="color:#339933">;</span>  
  43.     <span style="color:#0990">}</span> <span style="color:#000000; font-weight:bold">else</span> <span style="color:#000000; font-weight:bold">if</span> <span style="color:#0990">(</span>isNewer <span style="color:#339933">&&</span> <span style="color:#339933">!</span>isSignificantlyLessAccurate  
  44.             <span style="color:#339933">&&</span> isFromSameProvider<span style="color:#0990">)</span> <span style="color:#0990">{</span>  
  45.         <span style="color:#000000; font-weight:bold">return</span> <span style="color:#0066; font-weight:bold">true</span><span style="color:#339933">;</span>  
  46.     <span style="color:#0990">}</span>  
  47.     <span style="color:#000000; font-weight:bold">return</span> <span style="color:#0066; font-weight:bold">false</span><span style="color:#339933">;</span>  
  48. <span style="color:#0990">}</span>  
  49.   
  50. <span style="color:#0800; font-style:italic; font-weight:bold">/** Checks whether two providers are the same */</span>  
  51. <span style="color:#000000; font-weight:bold">private</span> <span style="color:#0066; font-weight:bold">boolean</span> isSameProvider<span style="color:#0990">(</span><span style="color:#03399">String</span> provider1, <span style="color:#03399">String</span> provider2<span style="color:#0990">)</span> <span style="color:#0990">{</span>  
  52.     <span style="color:#000000; font-weight:bold">if</span> <span style="color:#0990">(</span>provider1 <span style="color:#339933">==</span> <span style="color:#0066; font-weight:bold">null</span><span style="color:#0990">)</span> <span style="color:#0990">{</span>  
  53.         <span style="color:#000000; font-weight:bold">return</span> provider2 <span style="color:#339933">==</span> <span style="color:#0066; font-weight:bold">null</span><span style="color:#339933">;</span>  
  54.     <span style="color:#0990">}</span>  
  55.     <span style="color:#000000; font-weight:bold">return</span> provider1.<span style="color:#06633">equals</span><span style="color:#0990">(</span>provider2<span style="color:#0990">)</span><span style="color:#339933">;</span>  
  56. <span style="color:#0990">}</span>  

从代码中可以很清楚的看出判断位置是否“更好”的准则,不仅使用了精度(getAccuracy()),还使用了时间进行判断。事实上除了在导航应用,其它的时候均可以直接使用上面的这个方法来对位置更新信息进行过滤,以减少不断更新界面而带来的性能损失。

结束监听

只需要调用LocationManager对象的removeUpdates(LocationListener listener)方法就可以停止监听。事实上,在之前的代码中你已经看到我们移除了基于移动网络的监听器,下面的代码片段用于移除GPS监听器。

1
2
3
4
  1. <span style="color:#000000; font-weight:bold">if</span><span style="color:#0990">(</span>gpsListener<span style="color:#339933">!=</span><span style="color:#0066; font-weight:bold">null</span><span style="color:#0990">)</span><span style="color:#0990">{</span>  
  2.     locationManager.<span style="color:#06633">removeUpdates</span><span style="color:#0990">(</span>gpsListener<span style="color:#0990">)</span><span style="color:#339933">;</span>  
  3.     gpsListener<span style="color:#339933">=</span><span style="color:#0066; font-weight:bold">null</span><span style="color:#339933">;</span>  
  4. <span style="color:#0990">}</span>  

LocationManager的其它使用

这里还要介绍LocationManager中的几个方法:
getLastKnownLocation(String provider),用于得到上次定位时的最后位置,通常在应用刚启动时立刻得到1个位置,这样应用看上去会比较快。
getBestProvider(Criteria criteria, boolean enabledOnly),根据条件(精度的高低,是否能够得到海拔等)以及当前是否开启,得到1个最好的位置Provider。看上去很美,但现在的Android系统中只有2个Provider,而大多数用户的GPS都是开启的,在仅仅是2选1的情况我想像不出这个方法的用途。而即便用户关闭了GPS,我们也有能力帮他开启,用完了之后再关掉它。开启的方法见《进阶:如何编程实现开启或关闭GPS?》

总结

2个Provider提供了不同精度的定位服务,我们可以根据情况来使用。
一般来说,先使用NETWORK来得到1个精度较差的位置,再使用GPS来得到更准确的位置。
在Android官方提供的Dev Guide中,提供了一个关于GPS使用的时间线,我们来看一下
定位服务的一般时间线
概括起来就是2句话:“快速反应,渐进式精确”。在实际的使用中也要根据自己的情况画1个时间线,好决定何时开始监听,何时结束监听。

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约