Periodic Work Request not executing doWork in Work Manager
Asked Answered
O

1

6

I'm trying to get data from a remote url periodically using PeriodicWorkRequest in WorkManager. I have implemented the logic, the issue here is that i don't get any response from the Worker.

However it seems to call doWork() at first launch, but it doesn't get data from the network call. I am surprised that when i use OneTimeWorkRequest i get a success result from doWork() and the data from server as well.

what could i be doing wrong?

code below:

Worker Class

public class WorkerClass extends Worker {

private Context context;
public static final String EXTRA_WORKER_CLASS = "extra_tag";

public SpecialOffer(@NonNull Context context, @NonNull WorkerParameters workerParams) {
    super(context, workerParams);
    this.context = context;
}

@NonNull
@Override
public Result doWork() {
    Log.d("WORKER_PERIOD", "started");
    String url = "https://sampleurl/get.php";
    //Volley synchronous call
    RequestFuture<String> future = RequestFuture.newFuture();
    StringRequest request = new StringRequest(url, future, future);
    MySingleton.getInstance(context).addToRequestQueue(request);

    try {
        String response = future.get();
        Data data = new Data.Builder()
                .putString(EXTRA_SPECIAL_CARS, response)
                .build();
        setOutputData(data);
        Log.d("WORKER_RESPONSE", response);
        return Result.SUCCESS;
    } catch (InterruptedException | ExecutionException e) {
        return Result.FAILURE;
    }
}
}

Method to call task

public void callTask(){
     PeriodicWorkRequest periodicRequest =
                new PeriodicWorkRequest.Builder(WorkerClass.class, 15, TimeUnit.MINUTES)
                        .setConstraints(constraints)
                        .addTag("SPECIAL_OFFER")
                        .build();

        workManager.enqueueUniquePeriodicWork("SPECIAL_OFFER",
                ExistingPeriodicWorkPolicy.KEEP, periodicRequest);

        workManager.getWorkInfoByIdLiveData(periodicRequest.getId())
                .observe(getActivity(), workInfo -> {
                    Log.d("WORKER_PERIOD", "observed");
                    // Do something with the status
                    if (workInfo != null && workInfo.getState().isFinished()) {
                        Log.d("WORKER_PERIOD", "observed");
                        String ava = workInfo.getOutputData().getString(SpecialOffer.EXTRA_SPECIAL_CARS);
                        if (ava.equals("available")) {
                            showSpecialOffer(true);
                        } else {
                            showSpecialOffer(true);
                        }
                    }
                });
}
Onitaonlooker answered 15/11, 2018 at 13:57 Comment(5)
You should try it with ExistingPeriodicWorkPolicy.REPLACE policy.Fetter
Not working still, and why did you suggest REPLACE policyOnitaonlooker
I thought that replace policy replace your worker if it's already exists instead of keep will simply ignore it. One more thing you can try is providing backoff criteria to your worker, so that if it failed to run again then it can try after given criteria. I had same issues but fixed by given workarounds. Let me know if it still persist. We will try something else for you.Fetter
Ok I tried out Result.RETRY so it could retry if it failed, that doesn't work too. I think the issue is with PeriodicWorkRequest not returning FINISHED status of the task. You can look up this similar issue on github github.com/googlecodelabs/android-workmanager/issues/75Onitaonlooker
Given the nature of the work you want to do (download something from the network) I would probably use a ListenableWorker and a ResolvableFuture that have been introduced in one of the last alpha of WorkManager. You can find some example in this video around minute 11. BTW, what the full video, if you plan to use WorkManager it's a treasure chest of information.Heliotherapy
F
5

According to the PeriodicWorkRequest Documentation

The normal lifecycle of a PeriodicWorkRequest is ENQUEUED -> RUNNING -> ENQUEUED. By definition, periodic work cannot terminate in a succeeded or failed state, since it must recur. It can only terminate if explicitly cancelled

So when you doworkInfo.getState().isFinished() in .observe it always returns false because .isFinished() method documentation says:

returns true for SUCCEEDED, FAILED, and * CANCELLED states

Fusible answered 15/7, 2019 at 17:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.