• Android LBS系列02 获取当前位置


      Obtaining the Current Location

     

    设置Location监听器

      LocationManager 中有很多方法,使得应用可以获取位置更新。

      典型的观察者模式:注册一个事件监听器,说明location manager想从哪里接收位置更新,并且设定接收位置更新的最小时间间隔和距离间隔, onLocationChanged()回调方法就会在时间和位置间隔相应的频率下被激发。

      LocationListener是一个接口,用于接收LocationManager关于位置变化的通知。

      需要通过requestLocationUpdates(String, long, float, LocationListener)进行监听器的注册。

      LocationListener其中的onLocationChanged(Location location)方法每当位置变化就会被调用。

      比如下面的代码例子,每隔至少10秒,或者距离变化大于10米时接收一次位置信息。

    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);

     

    处理多源位置更新

      一般来说,更高精确度的定位方法(如GPS定位)比低精确度的定位方法(如基于网络的定位)花费更多的定位时间。

      如果你想要尽快展示位置数据并且在有更好精度的信息可用的时候更新它,一个通常的做法是注册一个位置监听器,同时监听GPS和网络位置提供者。

      在 onLocationChanged()回调函数中,你可以接收多个location 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 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;
    }
    
    /** Checks whether two providers are the same */
    private boolean isSameProvider(String provider1, String provider2) 
    {
        if (provider1 == null) 
        {
          return provider2 == null;
        }
        return provider1.equals(provider2);
    }

     

      可以看到在这个实现中,判断位置信息是否是一个更好的结果,首先判断获取的位置的时间信息,是不是更新;然后检查精度、是否是同一个provider提供等信息。

     

    明智地使用getLastKnownLocation()

      一些特定应用下,获取位置的首次建立时间如果过长可能难以使用户接受。可以考虑调用 getLastKnownLocation()方法,这个方法返回上一次的定位结果。

      当然这个结果很有可能是过期的,因为中间设备可能被关闭然后移动到了一个其他的地方。可以检查返回位置的时间戳和精度,然后决定这个位置是否有用。

      如果丢弃了getLastKnownLocation()方法返回的位置,等待新的位置更新时,最好考虑显示一个合适的信息给用户。

     

    关闭位置更新

      当你不再需要位置数据时,可以关闭位置更新,以减少多余的能量消耗和网络带宽。

      比如,当用户已经离开了位置更新显示的界面,就可以通过在onStop()中调用 removeUpdates() 方法来停止位置更新。如下:

     

    protected void onStop() 
    {
        super.onStop();
        mLocationManager.removeUpdates(listener);
    }

     

      当然也有一些应用需要持续地更新和处理位置数据,这时候最好将位置更新逻辑放在后台service中,用系统的notification bar让用户看到位置数据。

     

    参考资料

      Training: Obtaining the Current Location

      http://developer.android.com/training/basics/location/currentlocation.html

      LocationManager类:

      http://developer.android.com/reference/android/location/LocationManager.html

      LocationListener接口:

      http://developer.android.com/reference/android/location/LocationListener.html

      Location类:

      http://developer.android.com/reference/android/location/Location.html

     

  • 相关阅读:
    第七章之main函数和启动例程
    第一章之系统调用、库函数、内核函数区别
    unp第七章补充之socket tcp 产生 rst响应的情况
    unp第七章补充之TCP半开连接与半闭连接
    Qt 布局管理器
    Qt setMargin()和setSpacing() 的含义
    工作感悟
    关于数组数据常用的技巧
    正则表达式练习
    call/apply应用-对象使用原型链上的方法
  • 原文地址:https://www.cnblogs.com/mengdd/p/2857448.html
Copyright © 2020-2023  润新知