FusedLocationProvider не работает? - PullRequest
0 голосов
/ 17 октября 2018

У меня есть 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();
  }

}
...