Android培训:在应用中使用定位
2013-04-18 16:59
148 查看
- 关键组件:LocationManager, LocationProvider, LocationListener,
Geocoder
- 移动设备通常随身携带
- 位置感知是移动应用独特的功能
- 获取位置信息冰善用之,可以带来更多的情境体验
使用定位管理器
- 在应用接收定位信息更新之前,有一些必要的设置步骤
声明相关权限
- 仅使用基于网络的位置信息提供者:ACCESS_COARSE_LOCATION
- 更精确的GPS定位:ACCESS_FINE_LOCATION,其中已然包含前者
获取LocationManager的引用
- LocationManager是从安卓上访问位置服务的主类
- 程序如要在前台也即活动中接收定位更新,需要在onCreate()中执行:
取一个Location Provider
- 尽管不是必须的,大多数现代安卓设备能够通过多种底层技术接收位置更新
- 这些技术抽象为LocationProvider对象
- 各种location provider在速度、精度、费用、能耗等多方面存在差异
- 通常,location provider经度越高,耗时越多(GPS)
- 根据用例选择使用哪种或哪几种LP
- 也可以预设一些标准:精度,能耗,费用等,让安卓决定一个最匹配的LP:
验证LP是否可用
- 在设置中可能将LP关闭
- 应当检查请求的LP当前是否可用:isProviderEnabled()
- 如关闭,可以提供给用户一个操作机会以开启之,发出一个携带ACTION_LOCATION_SOURCE_SETTINGS的intent
获取当前位置
建立位置侦听
- 注册一个时间侦听器,指出你想要从哪个location manager接收位置更新,并置定最小的时间、距离间隔
- onLocationChanged()方法将按照指定的频率调用
处理多个位置更新源
- 矛盾:越准越慢,越快越不准
- 用快的及时更新,等准的来了再做替换:同时为两种LP注册同一个location listener
-
在onLocationChanged()中,将接收到来自不同LP的位置更新,可能具有不同的时间戳和精确级别。需要你自行添加逻辑来避免冲突、忽略过时的或者精度差的更新:
明智的使用getLastKnownLocation()
- 此方法提供上一次定位更新的信息
- 针对取不到当前位置信息的情况,可直接调用之获取最近一次的信息
- 要通过检查时间戳和经促来确定其返回的信息是否能用
- 如果选择忽略之而等待更新数据到来,那么最好在位置更新到来之前向用户提供一条信息
中断位置更新
- 当结束使用定位数据,应当终端定位以减少无必要的能耗和带宽
显示定位地址
- 接收到的位置更新数据为经纬坐标
执行反向地理编码
- 反向地理编码就是将经纬度翻译成人类可读的地址
- Geocoder API:基于web服务。
- isPresent()方法用于检测服务是否存在
Geocoder
- 移动设备通常随身携带
- 位置感知是移动应用独特的功能
- 获取位置信息冰善用之,可以带来更多的情境体验
使用定位管理器
- 在应用接收定位信息更新之前,有一些必要的设置步骤
声明相关权限
- 仅使用基于网络的位置信息提供者:ACCESS_COARSE_LOCATION
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" />
- 更精确的GPS定位:ACCESS_FINE_LOCATION,其中已然包含前者
获取LocationManager的引用
- LocationManager是从安卓上访问位置服务的主类
- 程序如要在前台也即活动中接收定位更新,需要在onCreate()中执行:
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
取一个Location Provider
- 尽管不是必须的,大多数现代安卓设备能够通过多种底层技术接收位置更新
- 这些技术抽象为LocationProvider对象
- 各种location provider在速度、精度、费用、能耗等多方面存在差异
- 通常,location provider经度越高,耗时越多(GPS)
- 根据用例选择使用哪种或哪几种LP
LocationProvider provider = locationManager.getProvider(LocationManager.GPS_PROVIDER);
- 也可以预设一些标准:精度,能耗,费用等,让安卓决定一个最匹配的LP:
// Retrieve a list of location providers that have fine accuracy, no monetary cost, etc Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setCostAllowed(false); ... String providerName = locManager.getBestProvider(criteria, true); // If no suitable provider is found, null is returned. if (providerName != null) { ... }
验证LP是否可用
- 在设置中可能将LP关闭
- 应当检查请求的LP当前是否可用:isProviderEnabled()
- 如关闭,可以提供给用户一个操作机会以开启之,发出一个携带ACTION_LOCATION_SOURCE_SETTINGS的intent
@Override protected void onStart() { super.onStart(); // This verification should be done during onStart() because the system calls // this method when the user returns to the activity, which ensures the desired // location provider is enabled each time the activity resumes from the stopped state. LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); final boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); if (!gpsEnabled) { // Build an alert dialog here that requests that the user enable // the location services, then when the user clicks the "OK" button, // call enableLocationSettings() } } private void enableLocationSettings() { Intent settingsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(settingsIntent); }
获取当前位置
建立位置侦听
- 注册一个时间侦听器,指出你想要从哪个location manager接收位置更新,并置定最小的时间、距离间隔
- onLocationChanged()方法将按照指定的频率调用
private final LocationListener listener = new LocationListener() { @Override public void onLocationChanged(Location location) { // A new location update is received. Do something useful with it. In this case, // we're sending the update to a handler which then updates the UI with the new // location. Message.obtain(mHandler, UPDATE_LATLNG, location.getLatitude() + ", " + location.getLongitude()).sendToTarget(); ... } ... }; mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, // 10-second interval. 10, // 10 meters. listener);
处理多个位置更新源
- 矛盾:越准越慢,越快越不准
- 用快的及时更新,等准的来了再做替换:同时为两种LP注册同一个location listener
-
在onLocationChanged()中,将接收到来自不同LP的位置更新,可能具有不同的时间戳和精确级别。需要你自行添加逻辑来避免冲突、忽略过时的或者精度差的更新:
private static final int TWO_MINUTES = 1000 * 60 * 2; 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 > TWO_MINUTES; boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES; 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; } private boolean isSameProvider(String provider1, String provider2) { if (provider1 == null) { return provider2 == null; } return provider1.equals(provider2); }
明智的使用getLastKnownLocation()
- 此方法提供上一次定位更新的信息
- 针对取不到当前位置信息的情况,可直接调用之获取最近一次的信息
- 要通过检查时间戳和经促来确定其返回的信息是否能用
- 如果选择忽略之而等待更新数据到来,那么最好在位置更新到来之前向用户提供一条信息
中断位置更新
- 当结束使用定位数据,应当终端定位以减少无必要的能耗和带宽
protected void onStop() { super.onStop(); mLocationManager.removeUpdates(listener); }
显示定位地址
- 接收到的位置更新数据为经纬坐标
执行反向地理编码
- 反向地理编码就是将经纬度翻译成人类可读的地址
- Geocoder API:基于web服务。
- isPresent()方法用于检测服务是否存在
private final LocationListener listener = new LocationListener() { public void onLocationChanged(Location location) { // Bypass reverse-geocoding if the Geocoder service is not available on the // device. The isPresent() convenient method is only available on Gingerbread or above. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD && Geocoder.isPresent()) { // Since the geocoding API is synchronous and may take a while. You don't want to lock // up the UI thread. Invoking reverse geocoding in an AsyncTask. (new ReverseGeocodingTask(this)).execute(new Location[] {location}); } } ... }; // AsyncTask encapsulating the reverse-geocoding API. Since the geocoder API is blocked, // we do not want to invoke it from the UI thread. private class ReverseGeocodingTask extends AsyncTask<Location, Void, Void> { Context mContext; public ReverseGeocodingTask(Context context) { super(); mContext = context; } @Override protected Void doInBackground(Location... params) { Geocoder geocoder = new Geocoder(mContext, Locale.getDefault()); Location loc = params[0]; List<Address> addresses = null; try { // Call the synchronous getFromLocation() method by passing in the lat/long values. addresses = geocoder.getFromLocation(loc.getLatitude(), loc.getLongitude(), 1); } catch (IOException e) { e.printStackTrace(); // Update UI field with the exception. Message.obtain(mHandler, UPDATE_ADDRESS, e.toString()).sendToTarget(); } if (addresses != null && addresses.size() > 0) { Address address = addresses.get(0); // Format the first line of address (if available), city, and country name. String addressText = String.format("%s, %s, %s", address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "", address.getLocality(), address.getCountryName()); // Update the UI via a message handler. Message.obtain(mHandler, UPDATE_ADDRESS, addressText).sendToTarget(); } return null; } }
相关文章推荐
- Android应用中使用百度地图API定位自己的位置(二)
- Android应用中使用百度地图API定位自己的位置(二)
- 8月28日 XE8移动开发入门(三)XE8在Android应用中调用Java类, 使用LiveBindings(免费培训)
- Android应用中使用百度地图API定位自己的位置(二)
- Android开发培训之如何使用该框架来构建自己的应用
- Android培训翻译_使用定位管理器
- Android应用开发SharedPreferences存储数据的使用方法 以及与 getPreferences 、getDefaultSharedPreferences的区别
- Android-使用adb和aapt查看应用信息
- Android百度定位API的使用
- Android使用百度地图API实现定位app
- 使用Kotlin开发Android应用
- Android应用开发SharedPreferences存储数据的使用方法
- Android的网络应用-使用Apache HttpClient
- Android应用开发是否应避免使用枚举?
- Android应用开发学习—Toast使用方法大全
- Android 使用android-support-multidex解决Dex超出方法数的限制问题,让你的应用不再爆棚
- Android应用开发之所有动画使用详解
- Android应用引导界面-ViewPages使用
- 【Mark】Android应用开发SharedPreferences存储数据的使用方法
- Android 百度地图开发(二)--- 定位功能之MyLocationOverlay,PopupOverlay的使用