3

Before API 31, we are using the following guideline, to implement a delayed started long running task, when user "quit" the app.

https://developer.android.com/topic/libraries/architecture/workmanager/advanced/long-running#long-running-java

public class XXXApplication extends MultiDexApplication implements DefaultLifecycleObserver {
    @Override
    public void onPause(LifecycleOwner owner) {
        startCloudWorker();
    }
}

public static void startCloudWorker() {
    OneTimeWorkRequest oneTimeWorkRequest =
            new OneTimeWorkRequest.Builder(CloudWorker.class)
                    .setInitialDelay(..., TimeUnit.MILLISECONDS)
                    ...
                    .build();

    WorkManager workManager = getWorkManager();
    workManager.enqueue(oneTimeWorkRequest);
}

public class CloudWorker extends Worker {
    public CloudWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    @NonNull
    @Override
    public Result doWork() {
        final ForegroundInfo foregroundInfo = createForegroundInfo(...)

        setForegroundAsync(foregroundInfo);
        
        // Some busy job here...

        return Result.success();
    }
}

Due to restriction imposed by new API 31

Apps that target Android 12 (API level 31) or higher can't start foreground services while running in the background, except for a few special cases. If an app tries to start a foreground service while the app is running in the background, and the foreground service doesn't satisfy one of the exceptional cases, the system throws a ForegroundServiceStartNotAllowedException.

https://developer.android.com/guide/components/foreground-services#background-start-restrictions

I thought using setExpedited might be a good workaround to overcome such limitation.

How does setExpedited work and is it as good&reliable as a foreground service?

However, when I start to adopt the new requirement

public static void startCloudWorker() {
    OneTimeWorkRequest oneTimeWorkRequest =
            new OneTimeWorkRequest.Builder(CloudWorker.class)
                    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
                    .setInitialDelay(..., TimeUnit.MILLISECONDS)
                    ...
                    .build();

    WorkManager workManager = getWorkManager();
    workManager.enqueue(oneTimeWorkRequest);
}

I am getting

java.lang.IllegalArgumentException: Expedited jobs cannot be delayed

I was wondering, what is the right way, to have a delayed started long running task when app is in background for API 31?

Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875

0 Answers0