我需要完成的工作:我的应用程序应该请求用户的当前位置,每15分钟重复一次,即使在后台,甚至在应用程序终止时也要重复一次。
我做了什么:我正在使用在定期WorkManager中调用的FusedLocationProviderAPI,扩展了ListenableWorker,因为该API是异步的。每次系统提供新的位置更新(最多每十五分钟)一次,就会调用LocationCallback。
由于ResolvableFuture似乎不建议在ListenableWorker的startWork-Method中使用,因此我使用CallbackToFutureAdapter。在此适配器中,我初始化LocationCallback并调用doWork-Method,该方法包括用于请求信息的所有逻辑。
我的问题:当屏幕处于活动状态时,一切正常。但是一旦应用程序在后台运行或被终止,LocationCallback不会被触发。(最后一个日志:“等待回调”)。请注意,我在下面删除了大量代码(例如异常处理和详细信息)。
这是我在MyWorker中的代码扩展了ListenableWorkerstartWork-Method:
public ListenableFuture<Result> startWork() {
return CallbackToFutureAdapter.getFuture(completer -> {
mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
// Storing data to different repositories.
completer.set(Result.success());
}
};
doWork();
return "startSomeAsyncStuff";
});
}
doWork():
public Result doWork() {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(mContext);
mSettingsClient = LocationServices.getSettingsClient(mContext);
createLocationCallback();
createLocationRequest();
buildLocationSettingsRequest();
startLocationUpdates();
return Result.success();
}
startLocationUpdates():
private void startLocationUpdates() {
// Begin by checking if the device has the necessary location settings.
mSettingsClient.checkLocationSettings(mLocationSettingsRequest)
.addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
Log.i(TAG, "All location settings are satisfied.");
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.getMainLooper());
Log.i(TAG, "Location updated requested - Waiting for Callback");
}
})
[相关文章:How do I return a ListenableFuture<Result> with work manager 2.0?和WorkManager: ResolvableFuture can only be called from within the same library group prefix
因此,经过数小时的反复试验,这是最终适用于我的解决方案:
技巧是添加一个前台服务,以确保在从系统收到新的位置更新之前,不取消该工作人员。但是,您无法避免在该时间段内显示通知。在请求位置更新之前,我还将LocationCallback移到了doWork-Method中(因为您需要将Callback传递给该方法。)
此解决方案基于https://developer.android.com/topic/libraries/architecture/workmanager/advanced/long-running,为了避免让我感到沮丧,我应该一开始就考虑一下;)
这里是startWork()-方法:
public ListenableFuture<Result> startWork() {
return CallbackToFutureAdapter.getFuture(completer -> {
setForegroundAsync(createForegroundInfo());
doWork(completer);
// This value is used only for debug purposes: it will be used
// in toString() of returned future or error cases.
return "Location Worker";
});
}