实现Android的不同精度的定位(基于网络和GPS) 您所在的位置:网站首页 谷歌定位怎么设置 实现Android的不同精度的定位(基于网络和GPS)

实现Android的不同精度的定位(基于网络和GPS)

2023-09-12 15:23| 来源: 网络整理| 查看: 265

在本文中,我会分别讲述如何开启位置服务的监听,如何停止监听,如何获得不同精度的定位,以及如何判断定位是否更精确。

Android中的定位服务的相关类基本上都在android.location包中,下面会按编写的顺序依次讲解。

1.获取位置服务管理器LocationManager

//变量定义 private LocationManager locationManager; //onCreate()方法中得到LocationManager locationManager = (LocationManager) this .getSystemService(Context.LOCATION_SERVICE) 2.开启位置服务的监听

有了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个变量,用于记录当前的位置

private class MyLocationListener implements LocationListener { Location currentLocation; @Override public void onLocationChanged(Location location) { if (currentLocation != null) { if (isBetterLocation(location, currentLocation)) { currentLocation = location; showLocation(location); } else { Toast.makeText(getApplicationContext(), "not very good", Toast.LENGTH_SHORT).show(); } } else { currentLocation = location; showLocation(location); } //移除基于LocationManager.NETWORK_PROVIDER的监听器 if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) { if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. return; } locationManager.removeUpdates(this); } } @Override public void onStatusChanged(String s, int i, Bundle bundle) { } @Override public void onProviderEnabled(String s) { } @Override public void onProviderDisabled(String s) { } private void showLocation(Location location) { Toast.makeText(getApplication(), "经度:" + location.getLongitude() + ",纬度:" + location.getLatitude() + ",精确度:" + location.getAccuracy(), Toast.LENGTH_SHORT).show(); } }

3.添加开始监听的代码

首先声明两个全局变量,并定义监听方法registerLocationListener()

private LocationListener gpsListener = null; private MyLocationListener networkListener = null; private void registerLocationListener() { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. return; } networkListener = new MyLocationListener(); gpsListener = new MyLocationListener(); locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 0, networkListener); 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米,基于这个属性我们可以对精度进行判断,以决定是否采用这个精度。

4.增加判断获取的位置是否更好的方法isBetterLocation()

你可能已经注意到上面的代码中有1个isBetterLocation方法,这是用来判断获取的位置是否更好,事实上这个方法来自于Dev Guide。我们看下这个方法的内容:

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()),还使用了时间进行判断。事实上除了在导航应用,其它的时候均可以直接使用上面的这个方法来对位置更新信息进行过滤,以减少不断更新界面而带来的性能损失。

5.结束监听

只需要调用LocationManager对象的removeUpdates(LocationListener listener)方法就可以停止监听。事实上,在之前的代码中你已经看到我们移除了基于移动网络的监听器,下面的代码片段用于移除GPS监听器。

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来得到更准确的位置。 概括起来就是2句话:“快速反应,渐进式精确”。在实际的使用中也要根据自己的情况画1个时间线,好决定何时开始监听,何时结束监听。

参考源码

http://yunpan.cn/cuIsvHhdfYSkS  访问密码 1a90



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有