如何可靠地获得Glass上的最后位置?

时间:2014-01-26 14:34:38

标签: google-glass google-gdk

来自getLastLocation()的方法LocationManager经常返回null,选择最佳提供程序非常棘手。文档说:

  

警告:请勿使用LocationManager.getBestProvider()方法或常量GPS_PROVIDER或NETWORK_PROVIDER来侦听位置更新。 Glass使用一组动态提供程序,只监听单个提供程序可能会导致您的应用程序错过位置更新。

如何获得最佳位置?

3 个答案:

答案 0 :(得分:8)

由于Glass使用动态的提供程序集,您需要从所有提供程序获取位置并选择最准确的位置:

 public static Location getLastLocation(Context context) {
      LocationManager manager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
      Criteria criteria = new Criteria();
      criteria.setAccuracy(Criteria.NO_REQUIREMENT);
      List<String> providers = manager.getProviders(criteria, true);
      List<Location> locations = new ArrayList<Location>();
      for (String provider : providers) {
           Location location = manager.getLastKnownLocation(provider);
           if (location != null && location.getAccuracy()!=0.0) {
               locations.add(location);
           }
      }
      Collections.sort(locations, new Comparator<Location>() {
          @Override
          public int compare(Location location, Location location2) {
              return (int) (location.getAccuracy() - location2.getAccuracy());
          }
      });
      if (locations.size() > 0) {
          return locations.get(0);
      }
      return null;
 }

答案 1 :(得分:4)

上面的Destil的答案正确处理了至少一个提供商返回getLastKnownLocation()的有效位置的情况。

但是,我也看到Glass为所有提供商返回null getLastKnownLocation()(特别是在XE16中)。

在这种情况下,您唯一的选择是注册LocationListener并等待新的位置更新。

例如,在创建新Activity时获取位置的上下文中,它将如下所示:

public class MyActivity extends Activity implements LocationListener {
...
LocationManager mLocationManager;
Location mLastKnownLocation;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // Activity setup
    ...
    // Use Destil's answer to get last known location, using all providers
    mLastKnownLocation = getLastLocation(this);

    if (mLastKnownLocation != null) {
        // Do something with location
        doSomethingWithLocation(mLastKnownLocation);
    } else {
        // All providers returned null - start a LocationListener to force a refresh of location
        mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        List<String> providers = mLocationManager.getProviders(true);
        for (Iterator<String> i = providers.iterator(); i.hasNext(); ) {
            mLocationManager.requestLocationUpdates(i.next(), 0, 0, this);
        }
    }
    ...
}
...
}

然后您需要处理LocationListener回调:

@Override
public void onLocationChanged(Location location) {
    if (mLastKnownLocation == null) {
        // At least one location should be available now
        // Use Destil's answer to get last known location again, using all providers
        mLastKnownLocation = getLastLocation(this);

        if (mLastKnownLocation == null) {
            // This shouldn't happen if LocationManager is saving locations correctly, but if it does, use the location that was just passed in
            mLastKnownLocation = location;
        }

        // Stop listening for updates
        mLocationManager.removeUpdates(this);

        // Do something with location
        doSomethingWithLocation(mLastKnownLocation);
    }
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}

@Override
public void onProviderEnabled(String provider) {}

@Override
public void onProviderDisabled(String provider) {}

更改为异步模型以避免在等待更新时阻止UI线程可能有点棘手,并且可能需要移动一些应用程序逻辑。

答案 2 :(得分:1)

应该调整答案中的代码以处理“0.0”的准确度,这表示“NO Accuracy”已知!

以下是包含此调整的替代方案

public static Location getLastLocation(Context context) {
    Location result = null;
    LocationManager locationManager;
    Criteria locationCriteria;
    List<String> providers;

    locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    locationCriteria = new Criteria();
    locationCriteria.setAccuracy(Criteria.NO_REQUIREMENT);
    providers = locationManager.getProviders(locationCriteria, true);

    // Note that providers = locatoinManager.getAllProviders(); is not used because the
    // list might contain disabled providers or providers that are not allowed to be called.

    //Note that getAccuracy can return 0, indicating that there is no known accuracy.

    for (String provider : providers) {
        Location location = locationManager.getLastKnownLocation(provider);
        if (result == null) {
            result = location;
        } 
        else if (result.getAccuracy() == 0.0) {
            if (location.getAccuracy() != 0.0) {
                result = location;
                break;
            } else {
                if (result.getAccuracy() > location.getAccuracy()) {
                    result = location;
                }
            }
        }
    }

    return result;
}