Currently, after quit the app, to complete a long running task in foreground (So that it will not be killed by OS), this is what I did by using WorkManager.
- Use
Workerto callContextCompat.startForegroundService, for starting anIntentService. Workerwill then returnResult.success()immediately.- In
onHandleIntentonIntentService, it will executestartForeground, before performing long running task.
Here's the code snippet.
public class SyncWorker extends Worker {
@NonNull
@Override
public Result doWork() {
final Intent intent = new Intent(WeNoteApplication.instance(), SyncForegroundIntentService.class);
ContextCompat.startForegroundService(
WeNoteApplication.instance(),
intent
);
return Result.success();
}
}
public class SyncForegroundIntentService extends IntentService {
private static final String TAG = "com.yocto.wenote.sync.SyncIntentService";
public SyncForegroundIntentService() {
super(TAG);
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
final Context context = WeNoteApplication.instance();
NotificationCompat.Builder builder = new NotificationCompat.Builder(...
startForeground(SYNC_FOREGROUND_INTENT_SERVICE_ID, builder.build());
// Perform networking operation within foreground service.
stopForeground(true);
I have strong intention to migrate the code, to make use of setForegroundAsync in WorkManager. The reason is that, under certain rare circumstance, I will get the following crash
Context.startForegroundService() did not then call Service.startForeground()
So, I thought migrating to setForegroundAsync might help eliminating this problem.
However, it isn't clear how setForegroundAsync work behind the scene, by looking at WorkForegroundUpdater souce code.
Here's the code snippet of setForegroundAsync code example from https://developer.android.com/topic/libraries/architecture/workmanager/advanced/long-running
public class DownloadWorker extends Worker {
public DownloadWorker(
@NonNull Context context,
@NonNull WorkerParameters parameters) {
...
}
@NonNull
@Override
public Result doWork() {
...
// What happens behind the scene?!
setForegroundAsync(createForegroundInfo(progress));
// The long running task is still executed in Worker thread.
download(inputUrl, outputFile);
return Result.success();
}
However, it isn't clear whether such migration will achieve equivalent outcome. As, here are their differences.
Before migration to setForegroundAsync
- The long running task is executed by
IntentService's user thread. - Before long running task is completed, Worker will return immediately.
After migration to setForegroundAsync
- The long running task is executed by
Worker's user thread. - Worker will only return after long running task is finished executing.
Currently, with my current implementation, I will able to avoid Excessive network usage (background) issue. I am not sure whether with setForegroundAsync, will I still able to avoid Excessive network usage (background) issue?
In short, does anyone has idea how Worker.setForegroundAsync work behind the scene?