我有一个FusedLocationProviderClient
,每2分钟请求一次定位。现在已经存在了很长时间的问题,在某些情况下用户不会收到位置更新,并且由于我们在应用程序中的处理方式,我们有效地将用户锁定在应用程序的主要部分之外。
再次访问该主题后,我发现根据developer guide,如果您禁用了GPS,则清除了位置缓存。
细腻而有趣,因此,下次用户访问该应用程序时,您希望缓存被清除,客户端获取更新所需的时间会稍长一些,因此您可以再次访问。可悲的是,事实并非如此。我在15:55禁用了gps,将其保留到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();
}
}