http://www.learningandroid.net/blog/foundation/tutorial-location-service/
在之前的教程《进阶:如何编程实现开启或关闭GPS?》中,讲述了GPS开关的问题,包括了Android
2.2以及之前版本的2种不同的开关方法。虽然我说过在官方的Dev Guide中有相当详细的Location定位的说明,不过我决定还是将这个教程补齐。
在本教程中,我会分别讲述如何开启位置服务的监听,如何停止监听,如何获得不同精度的定位,以及如何判断定位是否更精确。
Android中的定位服务的相关类基本上都在android.location包中,下面会按编写的顺序依次讲解。
首先,我们需要1个LocationManager,考虑到它会被多个方法使用,我们将它定义成Activity的Field。然后在onCreate方法中为它赋值。
1
2
3
4
5
|
//变量定义
private LocationManager locationManager;
//得到LocationManager
locationManager = (LocationManager) this
.getSystemService(Context.LOCATION_SERVICE);
|
开启位置服务的监听
有了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
|
private class MyLocationListner implements LocationListener{
@Override
public void onLocationChanged(Location location) {
// Called when a new location is found by the location provider.
Log.v("GPSTEST", "Got New Location of provider:"+location.getProvider());
if(currentLocation!=null){
if(isBetterLocation(location, currentLocation)){
Log.v("GPSTEST", "It's a better location");
currentLocation=location;
showLocation(location);
}
else{
Log.v("GPSTEST", "Not very good!");
}
}
else{
Log.v("GPSTEST", "It's first location");
currentLocation=location;
showLocation(location);
}
//移除基于LocationManager.NETWORK_PROVIDER的监听器
if(LocationManager.NETWORK_PROVIDER.equals(location.getProvider())){
locationManager.removeUpdates(this);
}
}
//后3个方法此处不做处理
public void onStatusChanged(String provider, int status, Bundle extras) {
}
public void onProviderEnabled(String provider) {
}
public void onProviderDisabled(String provider) {
}
};
Location currentLocation;
private void showLocation(Location location){
//纬度
Log.v("GPSTEST","Latitude:"+location.getLatitude());
//经度
Log.v("GPSTEST","Longitude:+location.getLongitude());
//精确度
Log.v("GPSTEST","Accuracy:"+location.getAccuracy());
//Location还有其它属性,请自行探索
}
|
开始监听的代码片段:
1
2
3
4
5
6
7
8
|
private LocationListener gpsListener=null;
private LocationListener networkListner=null;
private void registerLocationListener(){
networkListner=new MyLocationListner();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 0, networkListner);
gpsListener=new MyLocationListner();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 0, gpsListener);
}
|
以上的代码还是很易懂的吧,创建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
|
private static final int CHECK_INTERVAL = 1000 * 30;
protected boolean isBetterLocation(Location location,
Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > CHECK_INTERVAL;
boolean isSignificantlyOlder = timeDelta < -CHECK_INTERVAL;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location,
// use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must
// be worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation
.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and
// accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate
&& isFromSameProvider) {
return true;
}
return false;
}
/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
|
从代码中可以很清楚的看出判断位置是否“更好”的准则,不仅使用了精度(getAccuracy()),还使用了时间进行判断。事实上除了在导航应用,其它的时候均可以直接使用上面的这个方法来对位置更新信息进行过滤,以减少不断更新界面而带来的性能损失。
结束监听
只需要调用LocationManager对象的removeUpdates(LocationListener listener)方法就可以停止监听。事实上,在之前的代码中你已经看到我们移除了基于移动网络的监听器,下面的代码片段用于移除GPS监听器。
1
2
3
4
|
if(gpsListener!=null){
locationManager.removeUpdates(gpsListener);
gpsListener=null;
}
|
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个时间线,好决定何时开始监听,何时结束监听。
分享到:
相关推荐
可以判定手机是否开启GPS功能,然后实现全球定位,定位精度还是比较高的
人们在室外广泛使用目前较成熟的GPS,A-GPS等定位系统进行定位,但是在复杂的室内环境中,这些技术的定位精度不高,不能满足室内定位的需求。WIFI网络具有通信快速、部署方便的特点,它在室内场所广受欢迎.Android...
android程序的自动更新 和 基于GPS定位的轨迹存储.zip BaiduMap_AndroidSDK_v2.1.2_All.zip BaiduMap_AndroidSDK_v2.1.2_Sample.zip BMapRoutePlan.rar ContextMenu 上下文选项菜单,长按后跳出菜单.zip Fragment...
AGPS 技术是一种结合了网络基站信息和 GPS 信息对移动台进行定位的 技术,可以在 GSM/GPRS、WCDMA 和 CDMA2000 网络中使进行用。该技术 需要在手机内增加 GPS 接收机模块,并改造手机的天线,同时要在移动网络 上加建...
GPS卫星定位是主要的定位方式,它需要在相对空旷、高层建筑不密集的地方获得较准确的定位,当人们处在室内或高楼林立的市区,定位精度明显降低甚至不能定位。此时,利用无处不在的WiFi网络将能够弥补GPS定位的不足。...
的精度定位人员,以提供真实世界环境的交互体验以及计算机生成的感知信息,以增强用户体验. 1.3 SCOPE 室内导航系和教职工信息AR可视化位置共享 Future Scope 基于 AR 的游戏课程/小组出勤 快速反馈/AR 注释 新闻...
目前WLAN技术普遍应用在了家庭、旅馆、机场等各类大型及小型建筑物内,相关的研究如雨后春笋,开发了许多能实现较高精度定位的算法,使得WI-FI室内定位成为了定位领域中最引人注目的定位技术之一。 而随着传感器技术...
该系统由便携式设备与监护APP组成,便携式设备主要包括完成数据处理的8位AVR单片机Arduino NANO、实现通信功能及短信报警的SIM900A芯片、实现跌倒检测功能的ADXL345芯片与实现定位功能的WAVESHARE GPS NEO 6M芯片。...
对比性实验结果表明,测试距离206 m 后获取的GPS与PDR 分别解算的位置误差为4.1 和8.1 m,论文提出的PDR 与GPS 融合滤波解算的位置误差小于3.2 m,定位精度在使用较少传感器的情况下达到较高的水平且保证了良好定位...
GPS卫星定位是最主要的定位方式,它需要在相对空旷、高层建筑不密集的地方获得较准确的定位,当人们处在室内或高楼林立的市区,定位精度明显降低甚至不能定位。此时,利用无处不在的WiFi网络将能够弥补GPS定位的不足...
针对盲区中使用INS惯性导航系统进行定位存在误差积累的问题,提出一种基于DR航位推算、GPS全球定位系统和MM地图匹配的组合定位系统数据融合算法。该算法利用GPS和MM中得到的位置信息,一方面用于更新DR的定位信息,...
找 关键字:室内GPS,WiFi定位,室内地图,室内导航,室内定位有一个新版本 。 它对此版本进行了。关于内部导航和发现框架( FIND )允许您使用(Android)智能手机或支持WiFi的计算机(笔记本电脑或Raspberry Pi等...