それほど難しいことではありません。コードが行うことは、見つかった場所の継続的な更新を受信することです。複数のリスナーが異なるプロバイダーをリッスンすることができるため、それらの更新はプロバイダーに応じて多かれ少なかれ正確になる可能性があります(たとえば、GPSはネットワークよりも正確である可能性があります)。isBetterLocation(...)
リスナーによって検出された場所が実際にあなたがすでに知っている場所よりも優れているかどうかを評価します(そしてコード内に参照があるはずです)。isBetterLocation(...)コードは十分に文書化されているため、理解するのは難しいことではありませんが、最初のパラメーターの場所はプロバイダーによって検出された新しい場所であり、currentBestLocationは既に知っている場所です。
私が使用するコードは、私が最高のプロバイダーを採用しているだけではないことを除いて、あなたのコードとほぼ同じです。ハンドラーの問題は、継続的な更新を望まないためです。最大2分の時間枠内で十分に正確な可能な限り最良の場所を見つけてください(GPSには少し時間がかかる場合があります)。
private Location currentBestLocation = null;
private ServiceLocationListener gpsLocationListener;
private ServiceLocationListener networkLocationListener;
private ServiceLocationListener passiveLocationListener;
private LocationManager locationManager;
private Handler handler = new Handler();
public void fetchLocation() {
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
try {
LocationProvider gpsProvider = locationManager.getProvider(LocationManager.GPS_PROVIDER);
LocationProvider networkProvider = locationManager.getProvider(LocationManager.NETWORK_PROVIDER);
LocationProvider passiveProvider = locationManager.getProvider(LocationManager.PASSIVE_PROVIDER);
//Figure out if we have a location somewhere that we can use as a current best location
if( gpsProvider != null ) {
Location lastKnownGPSLocation = locationManager.getLastKnownLocation(gpsProvider.getName());
if( isBetterLocation(lastKnownGPSLocation, currentBestLocation) )
currentBestLocation = lastKnownGPSLocation;
}
if( networkProvider != null ) {
Location lastKnownNetworkLocation = locationManager.getLastKnownLocation(networkProvider.getName());
if( isBetterLocation(lastKnownNetworkLocation, currentBestLocation) )
currentBestLocation = lastKnownNetworkLocation;
}
if( passiveProvider != null) {
Location lastKnownPassiveLocation = locationManager.getLastKnownLocation(passiveProvider.getName());
if( isBetterLocation(lastKnownPassiveLocation, currentBestLocation)) {
currentBestLocation = lastKnownPassiveLocation;
}
}
gpsLocationListener = new ServiceLocationListener();
networkLocationListener = new ServiceLocationListener();
passiveLocationListener = new ServiceLocationListener();
if(gpsProvider != null) {
locationManager.requestLocationUpdates(gpsProvider.getName(), 0l, 0.0f, gpsLocationListener);
}
if(networkProvider != null) {
locationManager.requestLocationUpdates(networkProvider.getName(), 0l, 0.0f, networkLocationListener);
}
if(passiveProvider != null) {
locationManager.requestLocationUpdates(passiveProvider.getName(), 0l, 0.0f, passiveLocationListener);
}
if(gpsProvider != null || networkProvider != null || passiveProvider != null) {
handler.postDelayed(timerRunnable, 2 * 60 * 1000);
} else {
handler.post(timerRunnable);
}
} catch (SecurityException se) {
finish();
}
}
private class ServiceLocationListener implements android.location.LocationListener {
@Override
public void onLocationChanged(Location newLocation) {
synchronized ( this ) {
if(isBetterLocation(newLocation, currentBestLocation)) {
currentBestLocation = newLocation;
if(currentBestLocation.hasAccuracy() && currentBestLocation.getAccuracy() <= 100) {
finish();
}
}
}
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {}
@Override
public void onProviderEnabled(String s) {}
@Override
public void onProviderDisabled(String s) {}
}
private synchronized void finish() {
handler.removeCallbacks(timerRunnable);
handler.post(timerRunnable);
}
/** 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) {
//etc
}
private Runnable timerRunnable = new Runnable() {
@Override
public void run() {
Intent intent = new Intent(LocationService.this.getPackageName() + ".action.LOCATION_FOUND");
if(currentBestLocation != null) {
intent.putExtra(LocationManager.KEY_LOCATION_CHANGED, currentBestLocation);
locationManager.removeUpdates(gpsLocationListener);
locationManager.removeUpdates(networkLocationListener);
locationManager.removeUpdates(passiveLocationListener);
}
}
};