Reputation: 42806
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
.
Worker
to call ContextCompat.startForegroundService
, for starting an IntentService
.Worker
will then return Result.success()
immediately.onHandleIntent
on IntentService
, it will execute startForeground
, 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.
IntentService
's user thread.Worker
's user thread.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?
Upvotes: 4
Views: 5306
Reputation: 6496
Behind the scene setForegroundAsync()
starts a foreground service for you when you're on API >= 26, or on a normal service when running on older Android releases. This is documented in the reference:
Under the hood, WorkManager manages and runs a foreground service on your behalf to execute this WorkRequest, showing the notification provided in ForegroundInfo.
I think that the relevant source is in Processor.java
.
Talking about vital's metric Excessive Mobile Network Usage in Background, I don't see how this would change in this case given that, also using WorkManager setForegroundAsync()
will move your worker to a ForegroundService on Android Oreo+.
For additional information on how this vital's metric is measured, please, take a look at Play Console's guide.
Upvotes: 3