专题类的网站,网站建设新的技术方案,哪里找做网站的客户,北京微信网站搭建多少钱Location Strategies 定位的实现 在Android系统上实现定位主要是通过GPS或者是基于网络的定位方法。 GPS是精度最高的#xff0c;但是它只在户外有用#xff0c;并且很耗电#xff0c;并且首次定位花费时间较长。 基于网络的定位利用通信网络蜂窝基站和Wi-Fi信号#xff0c…Location Strategies 定位的实现 在Android系统上实现定位主要是通过GPS或者是基于网络的定位方法。 GPS是精度最高的但是它只在户外有用并且很耗电并且首次定位花费时间较长。 基于网络的定位利用通信网络蜂窝基站和Wi-Fi信号这种定位方式在室内室外都能用响应时间较短耗电较少但是精度较差。 为了在应用中获得用户的信息你的location provider可以是GPS或者基于网络也可以两者都用。 决定用户位置面临的挑战 从手机上获取用户的位置是个比较复杂的问题无论采取的数据源是什么总是有一些因素会导致位置信息包含误差从而不准确。 误差来源如下 多种位置信息源 GPS, Cell-ID, 和Wi-Fi都能为用户位置提供一定的线索。决定信任和采用哪些数据是一个需要权衡的过程权衡时要考虑精度、速度、电池效率等。 用户移动 因为用户的位置会改变所以应该考虑每隔一段时间重新估计用户位置。 变化的精度 每一个位置信息源的精度不是恒定的。也就是说位置估计即便是同一个信息源提供的它的精确度也是不断在变化的。 请求位置更新 在Android中获取位置主要是通过回调函数。 首先通过 LocationManager的 requestLocationUpdates()方法注册监听器向其中传入一个实现了 LocationListener接口的对象。 你的 LocationListener对象中必须实现一些回调函数当用户位置改变或者当服务状态改变时Location Manager就会调用这些回调函数。 比如下面的代码就展示了如何定义一个 LocationListener然后请求位置更新 // Acquire a reference to the system Location Manager
LocationManager locationManager (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);// Define a listener that responds to location updates
LocationListener locationListener new LocationListener()
{public void onLocationChanged(Location location) {// Called when a new location is found by the network location provider.makeUseOfNewLocation(location);}public void onStatusChanged(String provider, int status, Bundle extras) {}public void onProviderEnabled(String provider) {}public void onProviderDisabled(String provider) {}};// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener); requestLocationUpdates() 中的第一个参数指明了location provider的类型第二个参数是通知的最小时间间隔第三个参数是通知的最小的改变距离。 如果第二个和第三个参数都设置成0就表示要尽可能频繁地请求位置通知。 最后一个参数是用户自己定义的实现了LocationListener接口的对象它接收位置更新的回调。 如果想要同时利用GPS和网络定位可以调用 requestLocationUpdates()两次第一个参数分别是 GPS_PROVIDER和 NETWORK_PROVIDER 。 权限设置 如果没有权限设置程序在请求位置更新时将会失败。 manifest ... uses-permission android:nameandroid.permission.ACCESS_FINE_LOCATION /...
/manifest 如果用NETWROK_PROVIDER, 那么需要声明 ACCESS_COARSE_LOCATION和INTERNET 如果用GPS_PROVIDER, 那么需要声明 ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION是包含了ACCESS_COARSE_LOCATION的所以两者都用时可以只声明ACCESS_FINE_LOCATION。 建立一个最佳性能的模型 为了克服获取用户位置时的种种困难定义一个模型具体化你的应用如何取得用户位置。 这个模型包含了你何时开始和何时终止位置更新的监听也包含了什么时候使用缓存的位置数据。 获取用户位置的流程 获取用户位置的典型流程如下 1.首先开始应用。 2.在某一个点开始监听位置更新。 3.维持一个当前位置的“最佳估计”。 4.停止对位置更新的监听。 5.利用最后一次的最佳位置估计。 这个模型是一个窗口窗口从开始监听开始从停止监听结束。 决定何时开始监听更新 可以从应用一开始就启动监听也可以在用户触发某个特性后开始。 要清楚如果长时间监听位置会消耗很多电量但是短时间的监听可能达不到足够的精度。 调用requestLocationUpdates()开始监听 LocationProvider locationProvider LocationManager.NETWORK_PROVIDER;
// Or, use GPS location data:
// LocationProvider locationProvider LocationManager.GPS_PROVIDER;locationManager.requestLocationUpdates(locationProvider, 0, 0, locationListener); 用上次定位的结果获取快速定位 初次获得位置信息可能会花费较长时间。在获得一个比较精确的定位之前可以利用一个缓存的位置调用getLastKnownLocation(String)方法实现。 LocationProvider locationProvider LocationManager.NETWORK_PROVIDER;
// Or use LocationManager.GPS_PROVIDERLocation lastKnownLocation locationManager.getLastKnownLocation(locationProvider); 决定何时停止监听 位置获取和位置使用之间的时间间隔越小对估计精度的改善越有利。 永远记住长时间的监听位置更新将会非常费电所以一旦你得到你需要的信息就应该停止监听位置更新调用removeUpdates(PendingIntent)方法实现 // Remove the listener you previously added
locationManager.removeUpdates(locationListener); 维护一个当前最佳估计 因为定位精度是实时变化的所以很可能最新的位置并不是最准确的。 你应该制定一些标准并包含一套逻辑判断来选择出最佳估计。 这套标准也是随着使用情景而变化的。 下面是你验证一个location fix的精确度时可以采取的步骤 1.检查是否当期位置数据比之前的估计数据要新很多 2.检查当前数据和之前数据的精度谁更好 3.检查当前数据是从哪个provider处获得的然后决定是否更加信任它 一个例子如下 选择最佳位置估计的一个例子 private static final int TWO_MINUTES 1000 * 60 * 2;/** Determines whether one Location reading is better than the current Location fix* param location The new Location that you want to evaluate* param currentBestLocation The current Location fix, to which you want to compare the new one*/
protected boolean isBetterLocation(Location location, Location currentBestLocation)
{if (currentBestLocation null) {// A new location is always better than no locationreturn true;}// Check whether the new location fix is newer or olderlong timeDelta location.getTime() - currentBestLocation.getTime();boolean isSignificantlyNewer timeDelta TWO_MINUTES;boolean isSignificantlyOlder timeDelta -TWO_MINUTES;boolean isNewer timeDelta 0;// If its been more than two minutes since the current location, use the new location// because the user has likely movedif (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 accurateint 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 providerboolean isFromSameProvider isSameProvider(location.getProvider(),currentBestLocation.getProvider());// Determine location quality using a combination of timeliness and accuracyif (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);
} 调整模型以节约电量和进行数据交换 当你测试模型的时候可能发现你的模型需要做一些调整以平衡它的准确度和性能。下面是一些你可以改变的地方 减小流程的窗口尺寸 窗口尺寸减小意味着与GPS和网络的交互减少这样就可以节约电量。但是这样也就减少了获得最佳位置估计可以利用的位置数。 降低location provider返回更新的频率 在窗口中降低更新频率也可以改善电池效率但是会导致精度的丢失。requestLocationUpdates() 通过其中两个参数就可以设定更新的时间和空间间隔从而设定频率。 限制provider 根据应用的特定环境或者目标精度等级可以选择只利用基于网络的定位或者只利用GPS定位而不是同时利用两者。只与其中的一者交互将减少电量使用但是会有潜在的精度丢失。 参考资料 API GuidesLocation Strategies http://developer.android.com/guide/topics/location/strategies.html 转载于:https://www.cnblogs.com/mengdd/archive/2013/01/12/2857859.html