概述
2019独角兽企业重金招聘Python工程师标准>>>
一、概述
据专家说:人类活动80%的信息与空间位置信息有关,这还真不是专家吹牛。举个例子:你跟女神约饭,你得知道女神在哪里吧?你们选择约在哪里的餐厅最合适?你们过去分别有多远?你们怎么过去?——总结起来就是在哪里、有多远、怎么去?——技术翻译:位置 + 导航。
手机等移动设备是非常好的工具,都集成了定位模块,为用户提供位置服务。日常生活中用的比较多的:
高德、百度、腾讯、Google等手机电子地图;
美团、大众点评、滴滴、快的、uber、去哪儿、携程等O2O、生活服务;
微信、QQ、陌陌等社交工具的附近的人、位置共享等;
最近火起来的悦跑圈、咕咚等户外运动工具;
京东、淘宝等电商的物流配送,总是从最近的仓库发货,节省物流成本;
无人机、无人驾驶汽车等;
……
这些都统称为基于位置的服务(LBS)。
对于普通用户来说,android设备提供了: GPS,网络(Cell-ID和Wifi)两种方式,可以在手机中设置定位方式。作为开发者则需要更深入理解android的位置服务,在android的location包中有一个LocationManager类中有四个静态变量:GPS_PROVIDER、NETWORK_PROVIDER、PASSIVE_PROVIDER、FUSED_PROVIDER提供不同的定位模式。
这几种定位方式,各有优缺点:
(1)、GPS(GPS、AGPS):卫星定位模式、定位精度最高(10米)、能够获取海拔高度、耗电量大、室内无法定位。采用的是美国GPS卫星的民用信号,最少需4颗卫星来实现精确定位,目前正常情况的定位精度能够达到10米内,采用特殊的技术方法和芯片能够达到米级、厘米级的精度,一般专业设备才有这需求,如测绘、地质、工程建设等行业,工业级GPS芯片要比手机芯片贵N倍。在建筑密集遮挡、大面积水域、电磁干扰等区域,定位精度会大幅下降。
AGPS定位模式:GPS的初始定位可能需要点时间,几十秒、几分钟甚至十几分钟,不少手机提供AGPS定位模式(手机需要开启网络连接):首先根据网络的快速定位来获得一个大致位置,然后根据这个位置去帮助GPS模块快速地搜索到附近的卫星,能够有效改善GPS初始定位时间长的问题。室外定位精度与GPS模式相当。有些(不是所有)运营商也会在没有GPS信号的时候,如室内,通过服务器中的GPS卫星信息和网络实现低精度定位。
美国的GPS、我国北斗卫星导航系统(BeiDou Navigation Satellite System,BDS)、欧洲的伽利略GALILEO、俄罗斯格洛纳斯卫星导航系统(GLONASS)是联合国卫星导航委员会已认定的GNSS(Global Navigation Satellite System)供应商,GPS使用最广泛;我国的北斗导航发展最快,军事、政府等专业部门已经广泛使用,华为等已经推出了北斗手机,在消费电子领域北斗导航必定前途无量。
开发过程中需在AndroidMenifest.xml文件中配置权限:
android.permission.ACCESS_FINE_LOCATION
(2)、网络(CellID, WiFi MACID):网络定位模式(基站、wifi网络)、精度较低(1000米)、无海拔高度、初始定位速度快、耗电低。基于基站和wifi热点进行位置定位,这种定位方式精度取决于服务器,即取决于将基站或WIF节点信息翻译成位置信息的服务器的能力。
开发过程中需在AndroidMenifest.xml文件中配置权限:
android.permission.ACCESS_COARSE_LOCATION
(3)、passive(CellID, WiFi MACID):被动定位方式,精度取决于定位信息提供方。比较明显,就是用现成的,不主动请求位置信息,当其他应用使用定位更新了定位信息,系统会保存下来,该应用接收到消息后直接读取就可以了。比如如果系统中已经安装了百度地图,高德地图。
开发过程中需在AndroidMenifest.xml文件中配置权限:
android.permission.ACCESS_FINE_LOCATION
(4)、fusedlocation(融合定位服务):Google api,API容易使用、定位精度高、根据电量自动选择定位模式、Google的融合定位服务天朝不能用,最新消息称阿里巴巴(高德地图)与华为正在联合研发融合定位服务。不需要明确指定定位模式,由服务提供者自动判断,给出最佳的定位方式,需要Google API,Google Play Services 。
开发过程中需在AndroidMenifest.xml文件中配置权限:
android.permission.ACCESS_FINE_LOCATION
老外做的一个比较,里面有一些错误,别都当真。可能是不同的地区、不同的手机品牌的差异。
精度 | 耗电 | Technology |
20ft(6m) | High | Autonomous GPS, Provider: gps 1. uses GPS chip on the device 2. line of sight to the satellites 3. need about 7 to get a fix 4. takes a long time to get a fix 5. doesn’t work around tall buildings |
200ft (60m) | Medium – Low | Assisted GPS (AGPS), Provider: network 6. uses GPS chip on device, as well as assistance from the network (cellular network) to provide a fast initial fix 7. very low power consumption 8. very accurate 9. works without any line of sight to the sky 10. depends on carrier and phone supporting this (even if phone supports it, and network does not then this does not work) |
5300ft / 1mile (1.6km) | Low | CellID lookup/WiFi MACID lookup, Provider: network or passive 1. very fast lock, and does not require GPS chip on device to be active 2. requires no extra power at all 3. has very low accuracy; sometimes can have better accuracy in populated and well mapped areas that have a lot of WiFi access points, and people who share their location with Google |
二、开发方式
在开发的过程中有几种方式可以选择:
(1)、使用android原生API开发:相对灵活,不依赖服务提供商,开发工作量相对较大。学习android的位置服务则从这里入手能够比较深入。
(2)、使用百度地图、高德地图、腾讯地图、Google地图等API:位置服务提供商对android的定位服务进行了封装和扩展,将定位和地图进行了结合,功能强大,定位、导航、高级分析都可以实现,可以快速搭建业务系统。需要服务商的开发秘钥才能使用,同时一些服务商会左右一些限制,当系统访问量比较大的时候可能要收费。也可以使用一些开源地图的android版API。
(3)、解析GPS导航电文:android手机提供的GPS模块一般都是封装好的,可以直接使用获取GPS三维坐标信息,在一些移动应用中可能需要对GPS坐标进行更加复杂的应用,如无人机、单片机、差分GPS等,则需要自行解析GPS的导航电文,GPS芯片一般都采用国际通用的NMEA 0183电文格式(美国国家海洋电子协会弄的),
数据格式为:$信息类型,xxx,xxx,xxx,xxx,xxx,xxx,xxx,
信息类型为:GPGSV:可见卫星信息、GPGLL:地理定位信息、GPRMC:推荐最小定位信息、GPVTG:地面速度信息、GPGGA:GPS定位信息、GPGSA:当前卫星信息、……。一般情况,我们使用推荐的定位坐标GPRMC中的数据信息,获取三维坐标。
GPRMC:
推荐最小数据量的GPS信息(Recommended Minimum Specific GPS/TRANSIT Data)
$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*<13><CR><LF>
<1> UTC(Coordinated Universal Time)时间,hhmmss(时分秒)格式
<2> 定位状态,A=有效定位,V=无效定位
<3> Latitude,纬度ddmm.mmmm(度分)格式(前导位数不足则补0)
<4> 纬度半球N(北半球)或S(南半球)
<5> Longitude,经度dddmm.mmmm(度分)格式(前导位数不足则补0)
<6> 经度半球E(东经)或W(西经)
<7> 地面速率(000.0~999.9节,Knot,前导位数不足则补0)
<8> 地面航向(000.0~359.9度,以真北为基准,前导位数不足则补0)
<9> UTC日期,ddmmyy 格式
<10> Magnetic Variation,磁偏角(000.0~180.0度,前导位数不足则补0)
<11> Declination,磁偏角方向,E(东)或W(西)
<12> Mode Indicator,模式指示(仅NMEA0183 3.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)
<13> 校验和。
三、Android位置相关类库
建议阅读android关于位置服务相关的源代码。
(1)、LocationManager:位置服务管理器类
是获取位置信息的入口级类,要获取位置信息,首先需要获取一个LocationManger对象:LocationManager pLocationManager = (LocationManager) Context.getSystemService(Context.LOCATION_SERVICE);
(2)、LocationProvider:位置源提供者
用于描述位置提供者信息,可以先使用方法获取最佳提供者的名称:String providerName = LocationManger.getBestProvider(Criteria criteria, boolean enabledOnly);LocationManger.getProvider(String name)获取LocationProvider对象。
(3)、LocationListener:位置监听接口
用于监听位置(包括GPS、网络、基站等所有提供位置的)变化,监听设备开关与状态。实时动态获取位置信息,首先要实现该接口,在相关方法中添加实现功能的代码,实现该接口可以使用内部类或者匿名实现,java的基础知识。然后注册监听:LocationManger.requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)。使用完之后需要在适当的位置移除监听:LocationManager.removeUpdates(LocationListener listener)。LocationListener需要实现的方法:
onLocationChanged(Location location);当位置发生变化的时候会自动调用该方法,参数location记录了最新的位置信息。
onStatusChanged(String provider, int status, Bundle extras);当位置提供者的状态发生改变(可用到不可用、不可用到可用)时自动调用该方法;参数provider为位置提供者的名称,status为状态信息:OUT_OF_SERVICE 、AVAILABLE 、TEMPORARILY_UNAVAILABLE ,extras为附加数据:key/value,如satellites
onProviderEnabled(String provider);位置信息提供者可用时自动调用,比如用户关闭了GPS时,provider则为“gps”
onProviderDisabled(String provider);位置信息不可用时自动调用
(4)、GpsStatus.Listener:GPS状态监听的一个接口
使用方法与locationListener接口类似,先实现接口并创建对象,实现接口中的方法:onGpsStatusChanged(int event);在方法中实现对卫星状态信息变化的监听,根据event的类型编写逻辑代码。创建对象后再注册监听:LocationManager.addGpsStatusListener(GpsStatus.Listener listener);使用后在合适的位置释放监听:LocationManager.removeGpsStatusListener(GpsStatus.Listener listener)
(5)、GpsStatus.NmeaListener:监听GPS的NMEA 0183数据
这也是一个接口,用于监听串口上的GPS数据,标准的NMEA 0183格式导航电文。不过在实际android开发中基本不使用该接口对象,采用常规的方法也获取不到串口上的数据,具体原因不详。实现该接口需要实现其个方法:onNmeaReceived(long timestamp, String nmea); 然后添加监听:LocationManager.addNmeaListener(NmeaListener listener);用完后在合适的位置释放监听:LocationManager.removeNmeaListener(GpsStatus.NmeaListener listener)
(6)、Location:位置对象
描述地理位置信息的类,记录了经纬度、海拔高度、获取坐标时间、速度、方位等。可以通过LocationManager.getLastKnowLocation(provider)获取位置坐标,provider就是上文中提到的GPS_PROVIDER、NETWORK_PROVIDER、PASSIVE_PROVIDER、FUSED_PROVIDER;不过很多时候得到的Location对象为null;实时动态坐标可以在监听器locationListener的onLocationChanged(Location location)方法中来获取。
(7)、Criteria:用于选择位置信息提供者的辅助类
创建LocationProvider对象时会使用到该类,上文中内容。定位信息提供者会根据精度、电量、是否提供高度、速度、方位、服务商付费等信息进行排序选择定位提供者。 一个示例:
/** this criteria needs high accuracy, high power, and cost */
public static Criteria createFineCriteria() {
Criteria c = new Criteria();
c.setAccuracy(Criteria.ACCURACY_FINE);//高精度
c.setAltitudeRequired(true);//包含高度信息
c.setBearingRequired(true);//包含方位信息
c.setSpeedRequired(true);//包含速度信息
c.setCostAllowed(true);//允许付费
c.setPowerRequirement(Criteria.POWER_HIGH);//高耗电
return c;
}
(8)、GpsStatus:用于描述GPS当前状态的类
GpsStatus对象中的方法:getMaxSatellites()获取默认最多卫星数255,getTimeToFirstFix()用于获取首次定位时间,Iterable<GpsSatellite> getSatellites()用于获取卫星状态信息的列表,返回的是一个枚举对象。有几个用于描述GPS状态变化类型的静态变量:GPS_EVENT_STARTED、GPS_EVENT_STOPPED、GPS_EVENT_FIRST_FIX、GPS_EVENT_SATELLITE_STATUS。在GpsStatus.Listener 的onGpsStatusChanged回调方法中会使用到这几个静态变量判断卫星状态变化类型。可以使用GpsStatus gpsStatus = locationManager.getGpsStatus(null)获取最新的卫星状态信息,按照android源码中的解释getGpsStatus一般只在onGpsStatusChanged方法中使用。
(9)、GpsSatellite:卫星对象
用于描述单颗卫星的状态信息,包括卫星的方位、高度、伪随机噪声码、信噪比等信息。GpsStatus、GpsSatellite、GpsStatus.Listener会结合在一起使用。使用方法获取卫星列表枚举,并转换为一个ArrayList后使用:
Iterable<GpsSatellite> iterable=gpsStatus.getSatellites();
Iterator<GpsSatellite> itrator=iterable.iterator();
ArrayList<GpsSatellite> satelliteList=new ArrayList<GpsSatellite>();
然后就可以遍历每一颗卫星了:
while (itrator.hasNext() && count <= maxSatellites) {
GpsSatellite satellite = itrator.next();
count++;
}
四、位置服务开发流程
上面的内容有点冗长,那么在开发流程是什么样的呢?动态监听位置信息的大致流程:
(1) 配置权限: AndroidManifest.xml中配置权限: <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
(2) 获取LocationManager 类型对象: mLocationManager = (LocationManager) pContext.getSystemService (Context.LOCATION_SERVICE); pContext为Context类型的对象
(3) 获取最佳位置定位方式pProvider:mLocationManager.getBestProvider(pCriteria, true); pCriteria为Criteria类型的对象,包含精度、是否返回高度、方位、速度等信息。创建Criteria对象示例:
/** this criteria needs high accuracy, high power, and cost */
public static Criteria createFineCriteria() {
Criteria c = new Criteria();
c.setAccuracy(Criteria.ACCURACY_FINE);//高精度
c.setAltitudeRequired(true);//包含高度信息
c.setBearingRequired(true);//包含方位信息
c.setSpeedRequired(true);//包含速度信息
c.setCostAllowed(true);//允许付费
c.setPowerRequirement(Criteria.POWER_HIGH);//高耗电
return c;
}
(4) 实现LocationListener接口:可以采用内部类(MyLocationListener)或匿名类方式实现,重写接口方法,根据需要添加相应的代码:onLocationChanged(Location location);onStatusChanged(String provider, int status, Bundle extras);onProviderEnabled(String provider);onProviderDisabled(String provider);
(5) 创建MyLocationListener对象mLocationListener,并添加监听:mLocationListener = new MyLocationListener(); mLocationManager.requestLocationUpdates(pProvider, MIN_TIME_UPDATE, MIN_DISTANCE_UPDATE, mLocationListener);
(6) 使用完释放监听:mLocationManager.removeUpdates(mLocationListener);该方法执行的位置需要特别注意,如果是在Activity对象中,根据Activity的生命周期,onPause方法中比较合适,因为onStop、onDestroy两个方法在异常情况下不会被执行。
(7) 如果需要监听GPS卫星状态,则需要实现GpsStatus.Listener接口,并创建对象、添加监听、使用完后释放监听:实现接口private class MyGpsStatusListener implements GpsStatus.Listener;创建对象 mGpsStatusListener = new MyGpsStatusListener();添加监听isGpsStatusListener = mLocationManager.addGpsStatusListener (mGpsStatusListener);使用完后释放监听mLocationManager.removeGpsStatusListener(mGpsStatusListener);
五、可复用的GPS工具类
在开发的过程中,可以直接在activity中实现获取位置信息的功能,开发LBS程序。一个新的需求:需要多个activity用到实时获取的位置信息。可以在多个activity中编写重复的位置服务相关的代码逻辑也就是第四部分中的内容,重复的代码非常多,高效的开发者绝对不会做这么SB的事情。那么可以编写一个工具类class LocationUtils,将公共的功能逻辑封装好,在activity中实现差异化的内容。
等等,好像多个activity中动态获取位置信息,工具类实现有点棘手,使用计时器?可以但不是最好的方式,java基础比较好的都知道java面向接口的编程,可以完美的解决该问题。可以定义一个接口,activity实现该接口即可。
(1)定义接口:
public interface LocationHelper{
void UpdateLocation(Location location);//位置信息发生改变
void UpdateStatus(String provider, int status, Bundle extras);//位置状态发生改变
void UpdateGPSStatus(GpsStatus pGpsStatus);//GPS状态发生改变
}
(2)实现接口:java多态
public class LocationActivity extends Activity implements LocationHelper {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location);
}
@Override
public void UpdateLocation(Location location) {
// TODO Auto-generated method stub
}
@Override
public void UpdateStatus(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
@Override
public void UpdateGPSStatus(GpsStatus pGpsStatus) {
// TODO Auto-generated method stub
}
}
(3)工具类LocationUtils中调用实现了接口LocationHelper的对象
构造函数:
无参数构造函数定义为私有的private LocationUtils(),这样可以确保用户在使用的时候只能调用带参数LocationHelper的构造函数:Public LocationUtils (LocationHelper pInterface)
在上述监听器 LocationListener、GpsStatus.Listener方法中调用LocationHelper的方法,这样可以做到无论是在哪个activity中,都可以实现动态更新位置坐标信息。
//实现动态更新位置坐标信息、状态信息
private class MyLocationListener implements LocationListener {
@Override
public void onLocationChanged(Location location) {
// TODO调用接口的方法,java多态
mLocationHelper.UpdateLocation (location);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO 调用接口的方法,
mLocationHelper. UpdateStatus (provider,status,extras);
}
@Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
}
//实现动态更新GPS卫星状态信息
private class MyGpsStatusListener implements GpsStatus.Listener {
@Override
public void onGpsStatusChanged(int event) {
// TODO 调用接口方法。
GpsStatus pGpsStatus = mLocationManager.getGpsStatus (null);
mLocationHelper.UpdateGPSStatus(pGpsStatus);
}
//初始化监听
public boolean initLocationListener(Context pContext){
}
//移除监听
public void RemoveLocationListener(){
}
(3)Activity中调用工具类
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
mLocationUtils = new LocationUtils(this);//创建工具类对象
mSucceed = mLocationUtils.initLocationListener(this);//调用工具类中的初始化方法。
}
@Override
protected void onPause() {
super.onPause();
if (mSucceed == true) {
mLocationUtils.RemoveLocationListener();//使用完后移除监听
}
}
http://javapapers.com/android/android-location-fused-provider/
http://developerlife.com/tutorials/?p=1375
http://wenku.baidu.com/link?url=lfCxvthcUdLxWzcpqVdPwyQJxu4tryjsDDSK-R6kxrXXffHCnt0u80HuIuVUeS0U4vQLifbRRx4B34szgyP__--myMBwTq2Ix8wt1z8yZfO
http://baike.baidu.com/link?url=fgZOILUxFoZaimAID0Ve424sAaQRUHMb0vspeR17UJEyA0eU5ScZe9AkQGi57XkZIXzMqJ6Q_FaeJ6u8iFFDCq
转载于:https://my.oschina.net/u/2509049/blog/546170
最后
以上就是阳光丝袜为你收集整理的Android 位置服务与GPS实时定位 一、概述 二、开发方式 三、Android位置相关类库 四、位置服务开发流程 五、可复用的GPS工具类 的全部内容,希望文章能够帮你解决Android 位置服务与GPS实时定位 一、概述 二、开发方式 三、Android位置相关类库 四、位置服务开发流程 五、可复用的GPS工具类 所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复