最后更新时间:2019年6月17日
功能介绍
定位功能应用非常广泛,Google已经为Android开发者提供了原生的定位功能,开发者可直接使用Android SDK中的接口即可实现。原生定位由Android官方提供,不依赖其他任何第三方开发库。
Android原生定位提供GPS定位和网络定位两种模式。GPS定位,是通过设备中的GPS定位模块接收卫星信号,从而实现定位。Network定位(网络定位),则包括WiFi定位和基站定位两个模块:WiFi定位,是连接公共WiFi网络,可获取其固定的Mac地址,访问Google提供的定位服务查询到WiFi路由器的位置,从而获取手机的定位信息;基站定位,是在手机插入SIM卡并可用情况下,会搜索接收周围基站的信号,可利用周围三个基站的位置进行三角定位,从而获取设备的位置,或者获取基站的信息,然后访问网络,通过网络定位服务获取当前位置。两种定位模式都有各自的优缺点,在实际应用中根据需求选择。
(1)GPS定位特点:
(2)网络定位特点:
功能接口
Android原生定位提供了几个核心接口,可从Android官网提供的API中学习(网址为:https://developer.android.google.cn/reference/android/location/package-summary)。
接下来在MapGIS Mobile地图显示的基础上,详细介绍如何基于上述Android原生定位核心接口实现室外定位功能,重点讲解具体实现方法,也可查看官方API等资源深入学习。
实现步骤
接下来在MapGIS Mobile地图显示的基础上,详细介绍如何基于上述Android原生定位核心接口实现室外定位功能,重点讲解具体实现方法,也可查看官方API等资源深入学习。
1
打开Android Studio,创建一个新工程,然后根据需求设计界面布局。
实现定位功能,要为应用配置定位权限,在AndroidManifest.xml清单文件中添加权限标签,根据需要的定位方式(GPS定位、网络定位)申请对应的权限:
<!-- 允许应用程序访问精确位置,通过GPS进行定位 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <!-- 允许应用程序访问近似位置,通过网络进行定位 --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
如果设置程序的Android运行目标版本和真实运行设备的Android版本都大于6.0,则需要动态申请权限,是由于定位权限属于危险权限的范畴。
2
采用MapGIS Mobile 10.3 for Android SDK实现地图显示,以天地图显示为例。可参考开发指南-地图SDK > 地图显示 > 在线地图显示部分文档,并可在界面中加入定位功能按钮与定位信息展示框,实现简单的展示界面。
//获取服务地图对象,其中天地图的默认地图服务类型为MapServer.MAPSERVER_TYPE_TIANDITU MapServer mapServer = ServerLayer.createMapServer(MapServer.MAPSERVER_TYPE_TIANDITU); //设置地图类型 mapServer.setName("Tianditu_vec"); mapServer.setAuthentication("tk", "ad6c6a0bd9b1fa421dfd77ba49e70ecf"); //设置在线url地址 mapServer.setURL("http://t0.tianditu.gov.cn/vec_c/wmts"; ServerLayer mServerLayer = new ServerLayer(); mServerLayer.setMapServer(mapServer); //将服务图层添加到地图对象中 mMap.append(mServerLayer); mapView.setMapAsync(mMap, new MapViewFinishCallback() { @Override public void onDidFinish(boolean success) { if (success) { //地图加载完成 } else { //地图加载失败 } } });
3
LocationManager,定位管理器,是定位模块的核心接口。要获取定位信息,首先必须获取一个LocationManager对象,采用Context上下文的getSystemService获取实例。原生Android SDK已经提供了定位的服务。
//获取定位管理器对象 LocationManager mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
4
Criteria,用于选择位置提供者LocationProvider的应用标准的类,也即是作为定位的条件。根据实际的需求,可以对精度、海拔、方位、运营商收费、速度、电量等信息进行设置,来选择合适的定位提供者。然后调用LocationManager的getBestProvider方法获取最佳的定位提供者的名称。
Criteria criteria = new Criteria(); //设置定位精确度,Criteria.ACCURACY_FINE:较精确,Criteria.ACCURACY_COARSE:较粗略 criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setAltitudeRequired(true); //设置是否需要海拔信息 criteria.setBearingRequired(true); //设置是否需要方位信息 criteria.setCostAllowed(false); //设置是否允许运营商收费 criteria.setSpeedRequired(true); //设置是否需要速度信息 //设置对电量消耗的限制,POWER_LOW:低电耗;POWER_HIGH:高电耗;POWER_MEDIUM:耗电中 criteria.setPowerRequirement(Criteria.POWER_LOW); //第一个参数:标准;第二个参数:是否只返回当前可用的定位提供者 String bestProvider=mLocationManager.getBestProvider(getCriteria(), true);
5
获取了定位提供者之后,就可获取定位了,利用LocationManager的getLastKnownLocation获取上次定位的缓存定位位置。GPS的原理决定了首次定位会比较耗时,所以,为避免用户等待时间过长,一般在初次定位时调用此方法。
//获取最近一次定位,通过返回值Location可以获取时间、经纬度、海拔等位置信息 Location location=mLocationManager.getLastKnownLocation(bestProvider);
以上方法作用范围有限,适用在初次定位时采用,如果间隔上一次定位时间较久,得到的Location对象可能经常为Null,并且如果上一次定位在其他位置,对于此次定位也不适用。所以,还需注册定位监听,不断获取最新的位置。
调用requestLocationUpdates方法设置定位提供者、位置更新时间间隔、位置更新最小距离、定位监听器。可以设置定位方式,采用GPS定位,或者网络定位,或者使用指定的定位提供者进行定位。LocationListener是定位监听器,其中有四个回调方法,能够监听到位置提供者的开启、禁用、状态变化、定位位置变化的事件,返回信息。在位置变化回调函数中发送消息,在主线程中绘制标注、修改文本控件内容。
private LocationListener locationListener = new LocationListener() { @Override public void onLocationChanged(Location location) { //位置改变时触发 //绘制定位点标注 updateUIView(location); //获取定位点信息 double longitude = location.getLongitude(); double latitude = location.getLatitude(); double altitude = location.getAltitude(); float speed = location.getSpeed(); float accuracy = location.getAccuracy(); String provider = location.getProvider(); long time = location.getTime(); //串接为字符串 StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("经度:" + longitude); stringBuilder.append("\n纬度:" + latitude); stringBuilder.append("\n高程:" + altitude); stringBuilder.append("\n速度:" + speed); stringBuilder.append("\n精度:" + accuracy); stringBuilder.append("\n位置提供者:" + provider); //时间格式转换类 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //定位完成的时间 stringBuilder.append("\n定位时间:" + simpleDateFormat.format(time) + "\n"); //得到定位信息字符串 locationResult = stringBuilder.toString(); //发送消息,在主线程修改UI handler.sendEmptyMessage(1); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { //位置提供者状态变化时触发,provider为位置提供者的名称,status为状态信息,extras为额外信息,例如卫星Satellites的信息 switch (status) { case LocationProvider.AVAILABLE: Log.i(TAG, "当前位置提供者可用"); break; case LocationProvider.OUT_OF_SERVICE: Log.i(TAG, "当前位置提供者失效,不可用"); break; case LocationProvider.TEMPORARILY_UNAVAILABLE: Log.i(TAG, "当前位置提供者暂不可用"); break; default: break; } } @Override public void onProviderEnabled(String provider) { //位置提供者开启时触发 } @Override public void onProviderDisabled(String provider) { //位置提供者禁用时触发 } };
6
获取到定位信息之后,可利用MapGIS Mobile提供的地图标注功能展示当前位置。
//绘制定位点标注 private void updateUIView (Location location){ //得到定位点 Dot locationDot = new Dot(location.getLongitude(), location.getLatitude()); //绘制标注 if (locationAnnotation == null) { Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.location1); locationAnnotation = new Annotation("当前位置", "位置", locationDot, bitmap); mapView.getAnnotationsOverlay().addAnnotation(locationAnnotation); } else { locationAnnotation.setPoint(locationDot); } mapView.zoomToCenter(locationDot, 0.00001, true); mapView.refresh(); }
7
如果采用GPS定位模式,可监听到GPS的状态。
//为定位管理对象添加GPS状态监听器 mLocationManager.addGpsStatusListener(listener); /** * GPS状态侦听器,用于GPS状态更改时接收通知 */ GpsStatus.Listener listener = new GpsStatus.Listener() { @Override public void onGpsStatusChanged(int event) { switch (event) { //第一次定位 case GpsStatus.GPS_EVENT_FIRST_FIX: Log.i(TAG, "第一次定位"); break; //卫星状态改变 case GpsStatus.GPS_EVENT_SATELLITE_STATUS: Log.i(TAG, "卫星状态改变"); //可通过更多方法获取卫星信息:如卫星颗数等 break; // 定位启动 case GpsStatus.GPS_EVENT_STARTED: Log.i(TAG, "定位启动"); break; // 定位结束 case GpsStatus.GPS_EVENT_STOPPED: Log.i(TAG, "定位结束"); break; } } };
8
在不需要定位或者停止定位时,需要移除定位监听,释放资源,可在Activity的onDestroy生命周期方法中执行此操作。
@Override protected void onDestroy () { super.onDestroy(); //移除定位监听,停止更新位置 mLocationManager.removeUpdates(locationListener); }
9
代码编写完成后,即可调试运行程序。使用USB线连接手机和电脑,然后保证设备的GPS功能和网络(包括WiFi和移动网络)开启,效果如下图所示: