4

I am developing an Android app, and I used the Firebase JobDispatcher library to run a background job every time the user turns on Wi-Fi or mobile data, but unfortunately the library was deprecated and now the new WorkerManager is the way to go.

My question is how to run a job using the WorkerManager every time the internet is available only?

I have checked the WorkerManager library migration guide and documentation, but I couldn't achieve that using OneTimeWorkRequest or PeriodicWorkRequest.

Here is the code I used with the Firebase JobDispatcher library to achieve that.

FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(this));

Job networkJob = dispatcher.newJobBuilder()
        .setService(NetworkJobService.class)
        .setTag(Const.NETWORK_JOB_TAG)
        .setReplaceCurrent(true)
        .setLifetime(Lifetime.FOREVER)
        .setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
        .setRecurring(true)
        .setTrigger(Trigger.executionWindow(0, 0))
        .setConstraints(Constraint.ON_ANY_NETWORK)
        .build();

    dispatcher.schedule(networkJob);
Waxren
  • 2,002
  • 4
  • 30
  • 43
  • Hi @Waxren do you just want to trigger a listener when the internet comes in regardless using android-jobscheduler or android-workmanager ? – Zain Aug 21 '19 at 03:45
  • Yes but even when the app is closed and not running – Waxren Aug 21 '19 at 03:47

2 Answers2

3

The official WorkManager's documentation includes a migration guide for converting application from Firebase JobDispatcher to WorkManager.

The key point is that WorkManager allows, in a similar way to Firebase JobDispatcher, to set Constraints to your WorkRequest:

Constraints constraints = new Constraints.Builder()
    // The Worker needs Network connectivity
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .build();

PeriodicWorkRequest request =
    // Executes MyWorker every 15 minutes
    new PeriodicWorkRequest.Builder(MyWorker.class, 15, TimeUnit.MINUTES)
        // Sets the input data for the ListenableWorker
        .setConstraints(constraints)
        .build();

This execute your worker every 15 minutes (the minimum interval) when there's a connection. The other limit you've to consider is that a Worker cannot be run for more than 10 minutes. After that interval the OS will stop your Worker.

Both limits came from the underlying JobScheduler API in the Android Framework.

pfmaggi
  • 6,116
  • 22
  • 43
  • 1
    Consider the following example the user turned on Wi-Fi the job will execute then after that and before the 15 minutes interval finishes the user turned off then on the Wi-Fi the job will not execute – Waxren Aug 21 '19 at 09:00
  • 1
    That is the problem I need a recurring job but not a periodic one, in other words the job should run after the device is connected to network one time and the next time it runs not after 15 minutes (or any specific interval) but after the device is connected again. – Waxren Aug 21 '19 at 09:05
  • The Worker will only be executed after 15 minutes from the previous execution. If you need to execute it as soon as the connection is available, given the implicit broadcast limitations on API 26+, I would suggest you to use a foreground service with a listener for the connectivity. – pfmaggi Aug 21 '19 at 15:42
  • Thank you for the comment.I think that this a missing feature in the library instead of using a foreground service. Because many apps needs to run jobs code as soon as the connection is available. – Waxren Aug 21 '19 at 15:49
  • Im afraid that the library has no way to add this support as it simply uses what it's already available in the system (JobScheduler) and it runs from your application process, with the same limitation. If you think that this feature is important, you can open a feature request on the public issue tracker for WorkManager: https://issuetracker.google.com/issues/new?component=409906&template=1094197 – pfmaggi Aug 21 '19 at 17:50
  • "The other limit you've to consider is that a Worker cannot be run for more than 10 minutes" could you please more about this ... when this scenario occur? it is clear that work manager does not work continously Work manager just execute the job with one time request or Periodically ..its do Work method get called periodically then how a worker class can keep running for even 10 mins ? Work manager was introduced for many purpose one of them is Battery Consumption ? if a worker class can run for so long then why should not we use Service class ? – Quick learner Aug 22 '19 at 05:27
  • I am considering you want to say the TASK TIME which is to perform in work manager class in doWork() .. ?? If the the task you want to perform is time taking then why would you opt Work manager .. definitely not the good choice – Quick learner Aug 22 '19 at 05:31
  • WorkManager usues JobScheduler on API 23+ as its underlying scheduler and this brings a limit of 10 minutes for how long a task can take (in this case we're talking about what is inside your `doWork()` method). If `doWork()` does not return before this HARD limit, the OS will stop the Worker. This is mentioned in the documentation: https://developer.android.com/topic/libraries/architecture/workmanager/how-to/cancel-stop-work – pfmaggi Aug 22 '19 at 07:43
-2

Its better to initiate work manager once and set Constraint with Network Type which check is connection available in doWork() of Workmanager rather calling work manager again and again.

 setConstraints(new Constraints.Builder()
                     .setRequiredNetworkType(NetworkType.CONNECTED)

Try this solution

import work manager

https://developer.android.com/jetpack/androidx/releases/work

Then initiate Worker class

PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(WorkManagerDemo.class, 15, TimeUnit.MINUTES)
            .addTag("WorkManagerDemo").setConstraints(new Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build();
    WorkManager.getInstance().enqueueUniquePeriodicWork("WorkManagerDemo", ExistingPeriodicWorkPolicy.KEEP, periodicWorkRequest);

where WorkManagerDemo class is

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.annotation.NonNull;

import androidx.work.Worker;
import androidx.work.WorkerParameters;

public class WorkManagerDemo extends Worker {

    public WorkManagerDemo(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    @NonNull
    @Override
    public Result doWork() {
        //do your work here
        return Result.success();
    }


}
Quick learner
  • 10,632
  • 4
  • 45
  • 55
  • WorkManager includes constraints that you can use to run your worker only when a device is connected to a network. Your approach is more aggressive on the battery and doesn't take in consideration the 10 minutes execution limit that a Worker has. A Worker, after 10 minutes, is automatically stopped by the OS. – pfmaggi Aug 21 '19 at 07:22
  • I downvoted for using a very outdated version of WorkManager and using a BAD implementation of network checking (hint: you should be using constraints, don't use ConnectivityManager) – Zun Aug 21 '19 at 08:03
  • @pfmaggi FYI Minimum time of repetition is 15 Mins not 10 mins – Quick learner Aug 21 '19 at 11:12
  • 1
    Yes the minimum repetition time is 15 minutes. however the 10 minutes I wrote about here is the maximum execution time of a Worker: If your Worker is running for more than 10 minutes the OS will stop it. – pfmaggi Aug 21 '19 at 15:32
  • Do read more about work manager and USE IT to make sure how it works practically... well there is no point where worker runs for non stop 10 minutes as according to my knowledge .. Work Manager might not work in DOZE Mode – Quick learner Aug 22 '19 at 05:00
  • @pfmaggi added constraint in work manager request like you mentioned..updated the answer – Quick learner Aug 22 '19 at 05:10
  • @Zun updated my answer .. now using network type constraint rather than using connection manager class – Quick learner Aug 22 '19 at 05:11
  • You still listened to my criticism and edited your post, lol. Good job buddy I changed my vote – Zun Aug 22 '19 at 07:55
  • if your comment is helpful i appreciate it and will always do though.. i wont say i am a real developer .i will let my code speak .. but yeah i am learning everyday thanks whether u upvote or down vote – Quick learner Aug 22 '19 at 12:41