JobPreconditions.checkNotEmpty(mTag); JobPreconditions.checkArgumentPositive(mBackoffMs, "backoffMs must be > 0"); JobPreconditions.checkNotNull(mBackoffPolicy); JobPreconditions.checkNotNull(mNetworkType); JobPreconditions.checkArgumentInRange(mIntervalMs, getMinInterval(), Long.MAX_VALUE, "intervalMs"); JobPreconditions.checkArgumentInRange(mFlexMs, getMinFlex(), mIntervalMs, "flexMs"); JobPreconditions.checkArgumentNonnegative(mId, "id can't be negative"); if (mId == CREATE_ID) { builder.mId = JobManager.instance().getJobStorage().nextJobId(); JobPreconditions.checkArgumentNonnegative(builder.mId, "id can't be negative");
/** * Change the back-off policy for a non periodic job. The default value is set to 30 seconds * and {@link BackoffPolicy#EXPONENTIAL}. The time is increasing each time a job fails and * returns {@link Job.Result#RESCHEDULE}, but capped at 5 hours. * * <br> * <br> * * Note that it's not allowed to change the back-off criteria for a periodic job. * * @param backoffMs The initial interval to wait when the job has been rescheduled. * @param backoffPolicy Is either {@link BackoffPolicy#LINEAR} or {@link BackoffPolicy#EXPONENTIAL}. * @see Job.Result#RESCHEDULE * @see Job#onReschedule(int) */ public Builder setBackoffCriteria(long backoffMs, @NonNull BackoffPolicy backoffPolicy) { mBackoffMs = JobPreconditions.checkArgumentPositive(backoffMs, "backoffMs must be > 0"); mBackoffPolicy = JobPreconditions.checkNotNull(backoffPolicy); return this; }
mStartMs = JobPreconditions.checkArgumentPositive(startInMs, "startInMs must be greater than 0"); mEndMs = JobPreconditions.checkArgumentInRange(endInMs, startInMs, Long.MAX_VALUE, "endInMs");
/** * Overrides the executor service for all parallel execution. This could be helpful for Espresso * tests. * * @param executorService The new executor service. */ public static void setExecutorService(@NonNull ExecutorService executorService) { JobConfig.executorService = JobPreconditions.checkNotNull(executorService); }
/** * Specify that this job should recur with the provided interval and flex, not more than once per period. * The flex controls how close to the end of a period the job can run. For example, specifying an interval * of 60 seconds and a flex of 15 seconds will allow the scheduler to determine the best moment between * the 45th and 60th second at which to execute your job. * * <br> * <br> * * As default a job isn't periodic. It isn't allowed to specify a time window for a periodic job. * Instead you set an interval with this function. Since {@link Job.Result#RESCHEDULE} is ignored for * periodic jobs, setting a back-off criteria is illegal as well. * * @param intervalMs The job should run at most once every {@code intervalMs}. The minimum value is {@code 15min}. * @param flexMs How close to the end of the period the job should run. The minimum value is {@code 5min}. * @see #MIN_INTERVAL * @see #MIN_FLEX */ public Builder setPeriodic(long intervalMs, long flexMs) { mIntervalMs = JobPreconditions.checkArgumentInRange(intervalMs, getMinInterval(), Long.MAX_VALUE, "intervalMs"); mFlexMs = JobPreconditions.checkArgumentInRange(flexMs, getMinFlex(), mIntervalMs, "flexMs"); return this; }
/** * Adds an offset to the job IDs. Job IDs are generated and usually start with 1. This offset shifts the * very first job ID. * * @param jobIdOffset The offset for the very first job ID. */ public static void setJobIdOffset(int jobIdOffset) { JobPreconditions.checkArgumentNonnegative(jobIdOffset, "offset can't be negative"); if (jobIdOffset > JobIdsInternal.RESERVED_JOB_ID_RANGE_START - 500) { throw new IllegalArgumentException("offset is too close to Integer.MAX_VALUE"); } JobConfig.jobIdOffset = jobIdOffset; }
/** * Creates a new instance to build a {@link JobRequest}. Note that the {@code tag} doesn't * need to be unique. Each created request has an unique ID to differentiate between jobs * with the same tag. * * <br> * <br> * * When your job is about to start you receive a callback in your {@link JobCreator} to create * a {@link Job} for this {@code tag}. * * @param tag The tag is used to identify your {@code Job} in {@link JobCreator#create(String)}. */ public Builder(@NonNull String tag) { mTag = JobPreconditions.checkNotEmpty(tag); mId = CREATE_ID; mStartMs = -1; mEndMs = -1; mBackoffMs = DEFAULT_BACKOFF_MS; mBackoffPolicy = DEFAULT_BACKOFF_POLICY; mNetworkType = DEFAULT_NETWORK_TYPE; }
mStartMs = JobPreconditions.checkArgumentPositive(startInMs, "startInMs must be greater than 0"); mEndMs = JobPreconditions.checkArgumentInRange(endInMs, startInMs, Long.MAX_VALUE, "endInMs");
/** * Helper method to schedule a request on a background thread. This is helpful to avoid IO operations * on the main thread. The callback notifies you about the job ID or a possible failure. * * @param callback The callback which is invoked after the request has been scheduled. */ public void scheduleAsync(@NonNull final JobScheduledCallback callback) { JobPreconditions.checkNotNull(callback); JobConfig.getExecutorService().execute(new Runnable() { @Override public void run() { try { int jobId = schedule(); callback.onJobScheduled(jobId, getTag(), null); } catch (Exception e) { callback.onJobScheduled(JobScheduledCallback.JOB_ID_ERROR, getTag(), e); } } }); }
/** * Change the back-off policy for a non periodic job. The default value is set to 30 seconds * and {@link BackoffPolicy#EXPONENTIAL}. The time is increasing each time a job fails and * returns {@link Job.Result#RESCHEDULE}, but capped at 5 hours. * * <br> * <br> * * Note that it's not allowed to change the back-off criteria for a periodic job. * * @param backoffMs The initial interval to wait when the job has been rescheduled. * @param backoffPolicy Is either {@link BackoffPolicy#LINEAR} or {@link BackoffPolicy#EXPONENTIAL}. * @see Job.Result#RESCHEDULE * @see Job#onReschedule(int) */ public Builder setBackoffCriteria(long backoffMs, @NonNull BackoffPolicy backoffPolicy) { mBackoffMs = JobPreconditions.checkArgumentPositive(backoffMs, "backoffMs must be > 0"); mBackoffPolicy = JobPreconditions.checkNotNull(backoffPolicy); return this; }
public void setTime(int hour, int minute) { JobPreconditions.checkArgumentInRange(hour, 0, 23, "hour"); JobPreconditions.checkArgumentInRange(minute, 0, 59, "minute"); Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, hour); calendar.set(Calendar.MINUTE, minute); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); setTime(calendar.getTimeInMillis()); } }
/*package*/ static JobRequest fromCursor(Cursor cursor) { JobRequest request = new Builder(cursor).build(); request.mFailureCount = cursor.getInt(cursor.getColumnIndex(JobStorage.COLUMN_NUM_FAILURES)); request.mScheduledAt = cursor.getLong(cursor.getColumnIndex(JobStorage.COLUMN_SCHEDULED_AT)); request.mStarted = cursor.getInt(cursor.getColumnIndex(JobStorage.COLUMN_STARTED)) > 0; request.mFlexSupport = cursor.getInt(cursor.getColumnIndex(JobStorage.COLUMN_FLEX_SUPPORT)) > 0; request.mLastRun = cursor.getLong(cursor.getColumnIndex(JobStorage.COLUMN_LAST_RUN)); JobPreconditions.checkArgumentNonnegative(request.mFailureCount, "failure count can't be negative"); JobPreconditions.checkArgumentNonnegative(request.mScheduledAt, "scheduled at can't be negative"); return request; }
/** * Creates a new instance to build a {@link JobRequest}. Note that the {@code tag} doesn't * need to be unique. Each created request has an unique ID to differentiate between jobs * with the same tag. * * <br> * <br> * * When your job is about to start you receive a callback in your {@link JobCreator} to create * a {@link Job} for this {@code tag}. * * @param tag The tag is used to identify your {@code Job} in {@link JobCreator#create(String)}. */ public Builder(@NonNull String tag) { mTag = JobPreconditions.checkNotEmpty(tag); mId = CREATE_ID; mStartMs = -1; mEndMs = -1; mBackoffMs = DEFAULT_BACKOFF_MS; mBackoffPolicy = DEFAULT_BACKOFF_POLICY; mNetworkType = DEFAULT_NETWORK_TYPE; }
JobPreconditions.checkNotEmpty(mTag); JobPreconditions.checkArgumentPositive(mBackoffMs, "backoffMs must be > 0"); JobPreconditions.checkNotNull(mBackoffPolicy); JobPreconditions.checkNotNull(mNetworkType); JobPreconditions.checkArgumentInRange(mIntervalMs, getMinInterval(), Long.MAX_VALUE, "intervalMs"); JobPreconditions.checkArgumentInRange(mFlexMs, getMinFlex(), mIntervalMs, "flexMs"); JobPreconditions.checkArgumentNonnegative(mId, "id can't be negative"); if (mId == CREATE_ID) { builder.mId = JobManager.instance().getJobStorage().nextJobId(); JobPreconditions.checkArgumentNonnegative(builder.mId, "id can't be negative");
checkNotNull(value, valueName + " must not be null");
/** * Specify that this job should recur with the provided interval and flex, not more than once per period. * The flex controls how close to the end of a period the job can run. For example, specifying an interval * of 60 seconds and a flex of 15 seconds will allow the scheduler to determine the best moment between * the 45th and 60th second at which to execute your job. * * <br> * <br> * * As default a job isn't periodic. It isn't allowed to specify a time window for a periodic job. * Instead you set an interval with this function. Since {@link Job.Result#RESCHEDULE} is ignored for * periodic jobs, setting a back-off criteria is illegal as well. * * @param intervalMs The job should run at most once every {@code intervalMs}. The minimum value is {@code 15min}. * @param flexMs How close to the end of the period the job should run. The minimum value is {@code 5min}. * @see #MIN_INTERVAL * @see #MIN_FLEX */ public Builder setPeriodic(long intervalMs, long flexMs) { mIntervalMs = JobPreconditions.checkArgumentInRange(intervalMs, getMinInterval(), Long.MAX_VALUE, "intervalMs"); mFlexMs = JobPreconditions.checkArgumentInRange(flexMs, getMinFlex(), mIntervalMs, "flexMs"); return this; }
/** * Adds an offset to the job IDs. Job IDs are generated and usually start with 1. This offset shifts the * very first job ID. * * @param jobIdOffset The offset for the very first job ID. */ public static void setJobIdOffset(int jobIdOffset) { JobPreconditions.checkArgumentNonnegative(jobIdOffset, "offset can't be negative"); if (jobIdOffset > JobIdsInternal.RESERVED_JOB_ID_RANGE_START - 500) { throw new IllegalArgumentException("offset is too close to Integer.MAX_VALUE"); } JobConfig.jobIdOffset = jobIdOffset; }
/** * Helper method to schedule a daily job on a background thread. This is helpful to avoid IO operations * on the main thread. The callback notifies you about the job ID or a possible failure. For more * information about scheduling daily jobs see {@link #schedule(JobRequest.Builder, long, long)}. * * @param callback The callback which is invoked after the request has been scheduled. */ public static void scheduleAsync(@NonNull final JobRequest.Builder baseBuilder, final long startMs, final long endMs, @NonNull final JobRequest.JobScheduledCallback callback) { JobPreconditions.checkNotNull(callback); JobConfig.getExecutorService().execute(new Runnable() { @Override public void run() { try { int jobId = schedule(baseBuilder, startMs, endMs); callback.onJobScheduled(jobId, baseBuilder.mTag, null); } catch (Exception e) { callback.onJobScheduled(JobRequest.JobScheduledCallback.JOB_ID_ERROR, baseBuilder.mTag, e); } } }); }
/*package*/ static JobRequest fromCursor(Cursor cursor) { JobRequest request = new Builder(cursor).build(); request.mFailureCount = cursor.getInt(cursor.getColumnIndex(JobStorage.COLUMN_NUM_FAILURES)); request.mScheduledAt = cursor.getLong(cursor.getColumnIndex(JobStorage.COLUMN_SCHEDULED_AT)); request.mStarted = cursor.getInt(cursor.getColumnIndex(JobStorage.COLUMN_STARTED)) > 0; request.mFlexSupport = cursor.getInt(cursor.getColumnIndex(JobStorage.COLUMN_FLEX_SUPPORT)) > 0; request.mLastRun = cursor.getLong(cursor.getColumnIndex(JobStorage.COLUMN_LAST_RUN)); JobPreconditions.checkArgumentNonnegative(request.mFailureCount, "failure count can't be negative"); JobPreconditions.checkArgumentNonnegative(request.mScheduledAt, "scheduled at can't be negative"); return request; }
synchronized (JobManager.class) { if (instance == null) { JobPreconditions.checkNotNull(context, "Context cannot be null");