Edit: После просмотра вашего полного кода, я вижу несколько фундаментальных недостатков дизайна, поэтому я собираюсь показать вам, как я это сделал, и вы можете адаптировать его к потоку вашей программы. Пожалуйста, имейте в виду, что этот пример значительно упрощен от моего оригинала, но этого должно быть достаточно, чтобы вы начали.
Сначала файл CurrentLocation.java
. Мое дизайнерское решение обернуть это в Future было таким, чтобы я мог повторно использовать его в нескольких действиях с дополнительным бонусом , убившим его при необходимости.
public class CurrentLocation implements Callable<Location> {
private static final String TAG = "CurrentLocation";
private Context context;
private LocationManager lm;
private Criteria criteria;
private Location bestResult;
private boolean locationListenerWorking;
public CurrentLocation(Context context) {
lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
this.context = context;
criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
bestResult = null;
locationListenerWorking = false;
}
public Location call() {
return getLoc();
}
private Location getLoc() {
String provider = lm.getBestProvider(criteria, true);
if (provider != null) {
Log.d(TAG, "Using provider: " +provider);
locationListenerWorking = true;
lm.requestLocationUpdates(provider,
0,
0,
singeUpdateListener,
context.getMainLooper());
} else {
Log.w(TAG, "Couldn't find a location provider");
return null;
}
while (locationListenerWorking) {
// Check for the interrupt signal - terminate if necessary
if (Thread.currentThread().isInterrupted()) {
Log.i(TAG, "User initiated interrupt (cancel signal)");
cleanup();
break;
}
try {
// ghetto implementation of a busy wait...
Thread.sleep(500); // Sleep for half a second
} catch (Exception e) {
Log.d(TAG, "Thread interrupted..");
cleanup();
break;
}
}
return bestResult;
}
private void cleanup() {
if (lm != null) {
Log.d(TAG, "Location manager not null - cleaning up");
lm.removeUpdates(singeUpdateListener);
} else {
Log.d(TAG, "Location manager was NULL - no cleanup necessary");
}
}
/**
* This one-off {@link LocationListener} simply listens for a single location
* update before unregistering itself. The one-off location update is
* returned via the {@link LocationListener} specified in {@link
* setChangedLocationListener}.
*/
private LocationListener singeUpdateListener = new LocationListener() {
public void onLocationChanged(Location location) {
Log.d(TAG, "Got a location update");
if (location == null) {
Log.d(TAG, "Seems as if we got a null location");
} else {
bestResult = location;
}
cleanup();
locationListenerWorking = false;
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
}
Затем в вашем вызове класса (то есть, где вам нужны координаты широты / долготы - вы хотите сделать это из Activity
):
private class GetLocationTask extends AsyncTask <Void, Void, Location> {
private Future<Location> future;
private ExecutorService executor = new ScheduledThreadPoolExecutor(5);
private boolean cancelTriggered = false;
protected void onPreExecute() {
Log.d(TAG, "Starting location get...");
}
public Location doInBackground(Void... arg) {
CurrentLocation currLoc = new CurrentLocation(getApplicationContext());
future = executor.submit(currLoc);
long LOCATION_TIMEOUT = 20000; // ms = 20 sec
try {
// return future.get(Constants.LOCATION_TIMEOUT, TimeUnit.MILLISECONDS);
return future.get(LOCATION_TIMEOUT, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Log.w(TAG, "Location get timed out");
future.cancel(true);
return null;
}
}
public boolean killTask() {
cancelTriggered = true;
boolean futureCancelRes = future.cancel(true);
this.cancel(true);
Log.d(TAG, "Result of cancelling task: " +futureCancelRes);
return futureCancelRes;
}
protected void onPostExecute(Location res) {
if (cancelTriggered) {
Log.d(TAG, "User initiated cancel - this is okay");
cancelTriggered = false;
} else if (res == null) {
Log.d(TAG, "Could not get a location result");
} else {
double lat = res.getLatitude();
double lon = res.getLongitude();
Log.d(TAG, "Latitude: " +lat);
Log.d(TAG, "Longitude: " +lon);
}
}
}
Наконец, чтобы обернуть вещи, вот как вы это называете:
GetLocationTask t = new GetLocationTask();
t.execute();
И если по какой-либо причине вам нужно убить обновление местоположения (если ваш пользователь отключается от вашей активности и т. Д.), Это убьет AsyncTask
, а также связанную задачу Future.
t.killTask();
P.S. Возможно, вы захотите изменить свои ключи API и отредактировать их из своего поста.