Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android WorkManager: Cannot get output data from PeriodicWorkRequest

For some reasons I cannot get output data from PeriodicWorkRequest of Android WorkManager. The worker runs periodically as expected, it just doesn't return any data.

My MainActivity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    schedulePeriodicRequests();
}

public void schedulePeriodicRequests() {
    PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(ServerRequestsWorker.class, 15, TimeUnit.MINUTES)
            .build();

    WorkManager workManager = WorkManager.getInstance(MainActivity.this);
    workManager.enqueue(workRequest);
    workManager.getWorkInfoByIdLiveData(workRequest.getId())
            .observe(this, new Observer<WorkInfo>() {
                @Override
                public void onChanged(@Nullable WorkInfo workInfo) {
                    if (workInfo != null) {
                        Log.d(LOG_TAG, "WorkInfo received: state: " + workInfo.getState());
                        String message = workInfo.getOutputData().getString(ServerRequestsWorker.KEY_MESSAGE);
                        Log.d(LOG_TAG, "message: " + message);
                    }
                }
            });
}

My ServerRequestsWorker:

public static final String KEY_MESSAGE = "message";

@NonNull
@Override
public Result doWork() {
    Log.d(LOG_TAG, "Worker works");

    Data outputData = new Data.Builder()
            .putString(KEY_MESSAGE, "This is output message")
            .build();

    return Result.success(outputData);
}

The value from workInfo.getOutputData().getString is always null. Here's what I get in the log:

MainActivity: WorkInfo received: state: ENQUEUED
MainActivity: message: null
ServerRequestsWorker: Worker works
WM-WorkerWrapper: Worker result SUCCESS for Work [ id=5f2beba8-c8bf-4f07-b4ee-e876e95d3cdb, tags={ com.anshmidt.pricemonitor.ServerRequestsWorker } ]
MainActivity: WorkInfo received: state: RUNNING
MainActivity: message: null
MainActivity: WorkInfo received: state: ENQUEUED
MainActivity: message: null

It's interesting that getting output data from OneTimeWorkRequest is working fine. If I switch from PeriodicWorkRequest to OneTimeWorkRequest:

    OneTimeWorkRequest serverScraperWorkRequest = new OneTimeWorkRequest.Builder(ServerRequestsWorker.class)
            .build();

    WorkManager workManager = WorkManager.getInstance(MainActivity.this);
    workManager.enqueue(serverScraperWorkRequest);
    workManager.getWorkInfoByIdLiveData(serverScraperWorkRequest.getId())
            .observe(this, new Observer<WorkInfo>() {
                @Override
                public void onChanged(@Nullable WorkInfo workInfo) {
                    if (workInfo != null) {
                        Log.d(LOG_TAG, "WorkInfo received: state: " + workInfo.getState());
                        String message = workInfo.getOutputData().getString(ServerRequestsWorker.KEY_MESSAGE);
                        Log.d(LOG_TAG, "message: " + message);
                    }
                }
            });

, then I successfully receive the value from output data:

MainActivity: message: This is output message

I've tried enqueueing unique work and enqueueing by tag, but no luck. Have tried WorkManager 2.2.0 and 1.x, result is the same.

Am I missing something? Is it even possible to get output data from PeriodicWorkRequest? What do I wrong?

like image 534
Target Avatar asked Sep 08 '19 20:09

Target


1 Answers

As per the WorkInfo documentation:

Note that output is only available for the terminal states (WorkInfo.State.SUCCEEDED and WorkInfo.State.FAILED).

For Periodic work, the same ID is reused for each run, meaning that the work never gets to SUCCEEDED - instead, the work transitions immediately back to ENQUEUED, waiting for the next periodic run. Therefore, what you're experiencing seems to be the expected behavior.

As you've seen, using one time work does not have this behavior, since the work actually gets to SUCCEEDED and each subsequent run (if your one time work were to reschedule the same type work) would have a new ID. The other alternative is to not use output data, but instead store the result of your periodic work in your own database.

like image 191
ianhanniballake Avatar answered Oct 21 '22 13:10

ianhanniballake