7

I want to create a running job with a specific time and a given periodicity. For example, I want to schedule a job the second day of each month and it should run every month.

Looking at the JobInfo.Builder documentation I haven't found a way to set an initial delay.

Any idea on how could I achieve this?

Here is the code that runs with the correct periodicity but not with the initial delay I want:

fun build(application: Application, periodicity: Days, startDay: Days) {
    val serviceComponent = ComponentName(application, GenerateDebtJobService::class.java)
    val builder = JobInfo.Builder(1, serviceComponent)
        .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
        .setPeriodic(TimeUnit.DAYS.toMillis(periodicity.days.toLong()))

    (application.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler).schedule(builder.build())
Fábio Nascimento
  • 2,644
  • 1
  • 21
  • 27
César Alberca
  • 2,321
  • 2
  • 20
  • 32
  • 1
    Does the delay only apply for the first run? – Willi Mentzel Jan 08 '18 at 11:53
  • You can trigger alarm to fire Job ,as per your specific – hemen Jan 08 '18 at 11:54
  • Yes, the delay only applies to the first run – César Alberca Jan 08 '18 at 12:38
  • Well, actually the answer is at your hands already. Initial delay is unnecessary because of two totally acceptable workarounds: 1. You may specify "Effective date" as one of your job parameters and just check it on every job wakeup (less elegant, but simpler to implement). 2. You may postpone actual job creation and schedule the job which will create it at "Effective date" (more elegant, more code to write). – Max Alekseev Jan 08 '18 at 14:01

4 Answers4

1

You can't apply an initial delay for the periodic job. Currently should may use a one shot job for the initial delay and then schedule a new periodic job with the periodic interval.

Ron____
  • 782
  • 1
  • 6
  • 6
1

Indeed, there is no way out of the box. I use SharedPreferences to detect the first job run. Example:

public class MyReminder extends JobService {
    private static final String TAG = "MyReminder";
    private static final String IS_FIRST_RUN_KEY = "MyReminder.isFirstRun";

    @Override
    public boolean onStartJob(JobParameters jobParameters) {
        if (isFirstRun()) {
            // just skip it, will mark as first run and 
            // will do the real thing next time
            markFirstRunComplete();
        } else {
            // do the real thing here, show a notification, whatever...
        }
        return false;
    }

    @Override
    public boolean onStopJob(JobParameters jobParameters) {
        return false;
    }

    private boolean isFirstRun() {
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        return sharedPreferences.getBoolean(IS_FIRST_RUN_KEY, true);
    }

    private void markFirstRunComplete() {
        Log.d(TAG, "mark first run complete");
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putBoolean(IS_FIRST_RUN_KEY, false);
        editor.apply();
    }
}

iutinvg
  • 3,479
  • 3
  • 21
  • 18
0

You can try looking into the following implementation

https://github.com/evernote/android-job/blob/master/library/src/main/java/com/evernote/android/job/DailyJob.java

hiten pannu
  • 186
  • 1
  • 6
-2

Since API 24, it is possible using setPeriodic(long interval, long flex) it is gurenteed that your job will run any time between the flex and the supplied interval:

see documentation

Gal Rom
  • 6,221
  • 3
  • 41
  • 33