来自getLastLocation()
的方法LocationManager
经常返回null,选择最佳提供程序非常棘手。文档说:
警告:请勿使用LocationManager.getBestProvider()方法或常量GPS_PROVIDER或NETWORK_PROVIDER来侦听位置更新。 Glass使用一组动态提供程序,只监听单个提供程序可能会导致您的应用程序错过位置更新。
如何获得最佳位置?
答案 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;
}