Android上的LocationManager API似乎对一个只需要偶尔粗略估计用户位置的应用程序来说有点麻烦。
我正在开发的应用程序本身并不是一个定位应用程序,但它确实需要获取用户的位置,以便显示附近企业的列表。它不需要担心用户是否在移动或类似的事情。
以下是我想做的:
向用户显示附近位置的列表。预加载用户的位置,以便在“活动X”中需要它时,它将可用。我并不特别关心更新的准确性或频率。只要不太远,只要抓住一个位置就足够了。也许如果我想变得更漂亮,我会每隔几分钟左右更新一次位置,但这不是一个很大的优先事项。适用于任何具有GPS或网络位置提供商的设备。
这似乎并不难,但在我看来,我必须组建两个不同的位置提供商(GPS和NETWORK),并管理每个提供商的生命周期。不仅如此,我还必须在多个活动中复制相同的代码以满足#2。过去,我曾尝试使用getBestProvider()将解决方案简化为仅使用一个位置提供程序,但这似乎只提供了最好的“理论”提供程序,而不是实际会为您提供最佳结果的提供程序。
有没有更简单的方法来实现这一点?
你可以一直使用LocationManager.getLastKnownLocation(),但就像它说的那样,它可能已经过时了。
获取一般位置的一个简单方法是注册网络(通常很快)。
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 1000, 1000, this);
然后做
locationManager.removeUpdates(this);
在侦听器的onLocationChanged()方法中。
你可以一直使用LocationManager.getLastKnownLocation(),但就像它说的那样,它可能已经过时了。
获取一般位置的一个简单方法是注册网络(通常很快)。
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 1000, 1000, this);
然后做
locationManager.removeUpdates(this);
在侦听器的onLocationChanged()方法中。
在搜索了如何获得最佳精确用户位置的最佳实现后,我成功地结合了所有最佳方法,并提出了以下类:
/**
* Retrieve accurate location from GPS or network services.
*
*
* Class usage example:
*
* public void onCreate(Bundle savedInstanceState) {
* ...
* my_location = new MyLocation();
* my_location.init(main.this, locationResult);
* }
*
*
* public LocationResult locationResult = new LocationResult(){
* @Override
* public void gotLocation(final Location location){
* // do something
* location.getLongitude();
* location.getLatitude();
* }
* };
*/
class MyLocation{
/**
* If GPS is enabled.
* Use minimal connected satellites count.
*/
private static final int min_gps_sat_count = 5;
/**
* Iteration step time.
*/
private static final int iteration_timeout_step = 500;
LocationResult locationResult;
private Location bestLocation = null;
private Handler handler = new Handler();
private LocationManager myLocationManager;
public Context context;
private boolean gps_enabled = false;
private int counts = 0;
private int sat_count = 0;
private Runnable showTime = new Runnable() {
public void run() {
boolean stop = false;
counts++;
System.println("counts=" + counts);
//if timeout (1 min) exceeded, stop tying
if(counts > 120){
stop = true;
}
//update last best location
bestLocation = getLocation(context);
//if location is not ready or don`t exists, try again
if(bestLocation == null && gps_enabled){
System.println("BestLocation not ready, continue to wait");
handler.postDelayed(this, iteration_timeout_step);
}else{
//if best location is known, calculate if we need to continue to look for better location
//if gps is enabled and min satellites count has not been connected or min check count is smaller then 4 (2 sec)
if(stop == false && !needToStop()){
System.println("Connected " + sat_count + " sattelites. continue waiting..");
handler.postDelayed(this, iteration_timeout_step);
}else{
System.println("#########################################");
System.println("BestLocation found return result to main. sat_count=" + sat_count);
System.println("#########################################");
// removing all updates and listeners
myLocationManager.removeUpdates(gpsLocationListener);
myLocationManager.removeUpdates(networkLocationListener);
myLocationManager.removeGpsStatusListener(gpsStatusListener);
sat_count = 0;
// send best location to locationResult
locationResult.gotLocation(bestLocation);
}
}
}
};
/**
* Determine if continue to try to find best location
*/
private Boolean needToStop(){
if(!gps_enabled){
return true;
}
else if(counts <= 4){
return false;
}
if(sat_count < min_gps_sat_count){
//if 20-25 sec and 3 satellites found then stop
if(counts >= 40 && sat_count >= 3){
return true;
}
return false;
}
}
return true;
}
/**
* Best location abstract result class
*/
public static abstract class LocationResult{
public abstract void gotLocation(Location location);
}
/**
* Initialize starting values and starting best location listeners
*
* @param Context ctx
* @param LocationResult result
*/
public void init(Context ctx, LocationResult result){
context = ctx;
locationResult = result;
myLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
gps_enabled = (Boolean) myLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
bestLocation = null;
counts = 0;
// turning on location updates
myLocationManager.requestLocationUpdates("network", 0, 0, networkLocationListener);
myLocationManager.requestLocationUpdates("gps", 0, 0, gpsLocationListener);
myLocationManager.addGpsStatusListener(gpsStatusListener);
// starting best location finder loop
handler.postDelayed(showTime, iteration_timeout_step);
}
/**
* GpsStatus listener. OnChainged counts connected satellites count.
*/
public final GpsStatus.Listener gpsStatusListener = new GpsStatus.Listener() {
public void onGpsStatusChanged(int event) {
if(event == GpsStatus.GPS_EVENT_SATELLITE_STATUS){
try {
// Check number of satellites in list to determine fix state
GpsStatus status = myLocationManager.getGpsStatus(null);
Iterable<GpsSatellite>satellites = status.getSatellites();
sat_count = 0;
Iterator<GpsSatellite>satI = satellites.iterator();
while(satI.hasNext()) {
GpsSatellite satellite = satI.next();
System.println("Satellite: snr=" + satellite.getSnr() + ", elevation=" + satellite.getElevation());
sat_count++;
}
} catch (Exception e) {
e.printStackTrace();
sat_count = min_gps_sat_count + 1;
}
System.println("#### sat_count = " + sat_count);
}
}
};
/**
* Gps location listener.
*/
public final LocationListener gpsLocationListener = new LocationListener(){
@Override
public void onLocationChanged(Location location){
}
public void onProviderDisabled(String provider){}
public void onProviderEnabled(String provider){}
public void onStatusChanged(String provider, int status, Bundle extras){}
};
/**
* Network location listener.
*/
public final LocationListener networkLocationListener = new LocationListener(){
@Override
public void onLocationChanged(Location location){
}
public void onProviderDisabled(String provider){}
public void onProviderEnabled(String provider){}
public void onStatusChanged(String provider, int status, Bundle extras){}
};
/**
* Returns best location using LocationManager.getBestProvider()
*
* @param context
* @return Location|null
*/
public static Location getLocation(Context context){
System.println("getLocation()");
// fetch last known location and update it
try {
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
String strLocationProvider = lm.getBestProvider(criteria, true);
System.println("strLocationProvider=" + strLocationProvider);
Location location = lm.getLastKnownLocation(strLocationProvider);
if(location != null){
return location;
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
如果启用gps,此类将尝试连接到min_gps_sat_count卫星。Else返回LocationManager.getBestProvider()位置。检查代码!
要获取并显示用户的当前位置,还可以使用MyLocationOverlay。假设您的活动中有一个mapView字段。要显示用户位置,只需执行以下操作:
myLocationOverlay = new MyLocationOverlay(this, mapView);
myLocationOverlay.enableMyLocation();
mapView.getOverlays().add(myLocationOverlay);
这将从GPS或网络获取当前位置。如果两者都失败,enableMyLocation()将返回false。
至于该区域周围事物的位置,ItemizedOverlay应该可以做到这一点。
我希望我没有误解你的问题。祝你好运