У меня есть FusedLocationProviderClient
, который запрашивает местоположения каждые 2 минуты.У нас возникла проблема целую вечность, когда в определенных обстоятельствах пользователи не получали обновления местоположения, и из-за того, как мы обрабатывали его в приложении, мы фактически блокировали пользователя из основной части приложения.
После повторного изучения темы, я обнаружил, что согласно руководству разработчика , кэш местоположений очищается при отключении GPS.
Отлично, так что в следующий раз, когда пользователь заходит в приложение, вы ожидаете, что кэш будет очищен, клиенту потребуется немного больше времени, чтобы получить обновление, и вы можете вернуться снова.К сожалению, это не так.Я отключил GPS в 15:55, оставил его до 16:00, снова включил его в 16:00 и до сих пор не получил обновление в 16: 40
Я подумал, что где-то получаю исключениевнутри задачи запроса, поэтому я добавил все 4 обратных вызова (onFailure, onCanceled, onSuccess, onComplete) и получил onSuccess
и onComplete
, сигнализирующих мне, что ничего не случилось.
Я использую play-services-base 16.0.1
иplay-services-location 16.0.0
.Я предоставил разрешение ACCESS_FINE_LOCATION
, и я определенно начал свой запрос на обновление местоположения, используя FusedLocationProviderClient::requestLocationUpdates
, вот мой код
public class LocationHandler extends LocationCallback {
private static final String APPSTART_LOCATION = "APPSTART_LOCATION";
private static final String MOST_RECENT_LOCATION = "MOST_RECENT_LOCATION";
private final static int GPS_TIMEOUT = 3000;
private final Context context;
private final PreferencesHandler preferences;
private final Bus eventBus;
private BehaviorRelay<Location> subject;
private FusedLocationProviderClient client;
private boolean isRequestingLocations = false;
private Disposable timerDisposable;
public LocationHandler(Context context, PreferencesHandler preferences, Bus eventBus) {
this.context = context;
this.preferences = preferences;
this.eventBus = eventBus;
subject = BehaviorRelay.create();
client = new FusedLocationProviderClient(context);
}
@SuppressLint("MissingPermission")
public void connect() {
if (!isRequestingLocations && hasRequiredPermissions()) {
client.requestLocationUpdates(createLocationRequest(), this, null)
.addOnFailureListener(e -> Timber.e(e, "onFailure"))
.addOnCanceledListener(() -> Timber.d("onCanceled"))
.addOnSuccessListener(aVoid -> Timber.d("onSuccess"))
.addOnCompleteListener(task -> Timber.d("onComplete"));
isRequestingLocations = true;
//start a timer so the client will act like nothing's amiss if he didn't receive a location-update within the given timeout
timerDisposable = Observable.timer(GPS_TIMEOUT, TimeUnit.MILLISECONDS).subscribe(ignored -> {
//the reason why this happens is because the provider just uses cached locations. When the user deactivates GPS, the cache is cleared
//once you reactivate gps it should technically work, but it takes a long time nonetheless
ReportingUtil.trackFbEvent(new GPS_NO_LOCATION_RECEIVED((int) TimeUnit.MILLISECONDS.toSeconds(GPS_TIMEOUT)));
preferences.setHasGeolocation(true);
eventBus.post(new NoLocationReceivedEvent());
eventBus.post(new FirstLocationArrivedEvent());
});
}
}
private LocationRequest createLocationRequest() {
LocationRequest request = new LocationRequest();
long interval = TimeUnit.MINUTES.toMillis(Constants.GPSINTERVAL);
request.setInterval(interval);
request.setFastestInterval(interval);
request.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
return request;
}
public void disconnect() {
if (isRequestingLocations) {
timerDisposable.dispose();
client.removeLocationUpdates(this);
isRequestingLocations = false;
}
}
public Observable<Location> getAllLocations() {
return subject;
}
@Override
public void onLocationResult(LocationResult result) {
Timber.d("onLocationResult: %s", result);
if (result != null && result.getLocations().size() != 0) {
Location location = result.getLocations().get(0);
if (location != null) {
if (timerDisposable != null) {
timerDisposable.dispose();
}
subject.accept(new Location(location));
}
}
}
private boolean hasRequiredPermissions() {
return ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
public void restart() {
disconnect();
connect();
}
}