| /* |
| * Copyright 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package androidx.work; |
| |
| import android.annotation.SuppressLint; |
| import android.os.Build; |
| |
| import androidx.annotation.NonNull; |
| import androidx.annotation.RequiresApi; |
| |
| import java.time.Duration; |
| import java.util.concurrent.TimeUnit; |
| |
| /** |
| * A {@link WorkRequest} for repeating work. This work executes multiple times until it is |
| * cancelled, with the first execution happening immediately or as soon as the given |
| * {@link Constraints} are met. The next execution will happen during the period interval; note |
| * that execution may be delayed because {@link WorkManager} is subject to OS battery optimizations, |
| * such as doze mode. |
| * <p> |
| * You can control when the work executes in the period interval more exactly - see |
| * {@link PeriodicWorkRequest.Builder} for documentation on {@code flexInterval}s. |
| * <p> |
| * Periodic work has a minimum interval of 15 minutes. |
| * <p> |
| * Periodic work is intended for use cases where you want a fairly consistent delay between |
| * consecutive runs, and you are willing to accept inexactness due to battery optimizations and doze |
| * mode. Please note that if your periodic work has constraints, it will not execute until the |
| * constraints are met, even if the delay between periods has been met. |
| * <p> |
| * If you need to schedule work that happens exactly at a certain time or only during a certain time |
| * window, you should consider using {@link OneTimeWorkRequest}s. |
| * <p> |
| * The normal lifecycle of a PeriodicWorkRequest is {@code 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. However, in the case of retries, periodic work |
| * will still back off according to |
| * {@link PeriodicWorkRequest.Builder#setBackoffCriteria(BackoffPolicy, long, TimeUnit)}. |
| * <p> |
| * Periodic work cannot be part of a chain or graph of work. |
| */ |
| |
| public final class PeriodicWorkRequest extends WorkRequest { |
| |
| /** |
| * The minimum interval duration for {@link PeriodicWorkRequest} (in milliseconds). |
| */ |
| @SuppressLint("MinMaxConstant") |
| public static final long MIN_PERIODIC_INTERVAL_MILLIS = 15 * 60 * 1000L; // 15 minutes. |
| /** |
| * The minimum flex duration for {@link PeriodicWorkRequest} (in milliseconds). |
| */ |
| @SuppressLint("MinMaxConstant") |
| public static final long MIN_PERIODIC_FLEX_MILLIS = 5 * 60 * 1000L; // 5 minutes. |
| |
| PeriodicWorkRequest(Builder builder) { |
| super(builder.mId, builder.mWorkSpec, builder.mTags); |
| } |
| |
| /** |
| * Builder for {@link PeriodicWorkRequest}s. |
| */ |
| public static final class Builder extends WorkRequest.Builder<Builder, PeriodicWorkRequest> { |
| |
| /** |
| * Creates a {@link PeriodicWorkRequest} to run periodically once every interval period. The |
| * {@link PeriodicWorkRequest} is guaranteed to run exactly one time during this interval |
| * (subject to OS battery optimizations, such as doze mode). The repeat interval must |
| * be greater than or equal to {@link PeriodicWorkRequest#MIN_PERIODIC_INTERVAL_MILLIS}. It |
| * may run immediately, at the end of the period, or any time in between so long as the |
| * other conditions are satisfied at the time. The run time of the |
| * {@link PeriodicWorkRequest} can be restricted to a flex period within an interval (see |
| * {@code #Builder(Class, long, TimeUnit, long, TimeUnit)}). |
| * |
| * @param workerClass The {@link ListenableWorker} class to run for this work |
| * @param repeatInterval The repeat interval in {@code repeatIntervalTimeUnit} units |
| * @param repeatIntervalTimeUnit The {@link TimeUnit} for {@code repeatInterval} |
| */ |
| public Builder( |
| @NonNull Class<? extends ListenableWorker> workerClass, |
| long repeatInterval, |
| @NonNull TimeUnit repeatIntervalTimeUnit) { |
| super(workerClass); |
| mWorkSpec.setPeriodic(repeatIntervalTimeUnit.toMillis(repeatInterval)); |
| } |
| |
| /** |
| * Creates a {@link PeriodicWorkRequest} to run periodically once every interval period. The |
| * {@link PeriodicWorkRequest} is guaranteed to run exactly one time during this interval |
| * (subject to OS battery optimizations, such as doze mode). The repeat interval must |
| * be greater than or equal to {@link PeriodicWorkRequest#MIN_PERIODIC_INTERVAL_MILLIS}. It |
| * may run immediately, at the end of the period, or any time in between so long as the |
| * other conditions are satisfied at the time. The run time of the |
| * {@link PeriodicWorkRequest} can be restricted to a flex period within an interval (see |
| * {@code #Builder(Class, Duration, Duration)}). |
| * |
| * @param workerClass The {@link ListenableWorker} class to run for this work |
| * @param repeatInterval The repeat interval |
| */ |
| @RequiresApi(26) |
| public Builder( |
| @NonNull Class<? extends ListenableWorker> workerClass, |
| @NonNull Duration repeatInterval) { |
| super(workerClass); |
| mWorkSpec.setPeriodic(repeatInterval.toMillis()); |
| } |
| |
| /** |
| * Creates a {@link PeriodicWorkRequest} to run periodically once within the |
| * <strong>flex period</strong> of every interval period. See diagram below. The flex |
| * period begins at {@code repeatInterval - flexInterval} to the end of the interval. |
| * The repeat interval must be greater than or equal to |
| * {@link PeriodicWorkRequest#MIN_PERIODIC_INTERVAL_MILLIS} and the flex interval must |
| * be greater than or equal to {@link PeriodicWorkRequest#MIN_PERIODIC_FLEX_MILLIS}. |
| * |
| * <p><pre> |
| * [ before flex | flex ][ before flex | flex ]... |
| * [ cannot run work | can run work ][ cannot run work | can run work ]... |
| * \____________________________________/\____________________________________/... |
| * interval 1 interval 2 ...(repeat) |
| * </pre></p> |
| * |
| * @param workerClass The {@link ListenableWorker} class to run for this work |
| * @param repeatInterval The repeat interval in {@code repeatIntervalTimeUnit} units |
| * @param repeatIntervalTimeUnit The {@link TimeUnit} for {@code repeatInterval} |
| * @param flexInterval The duration in {@code flexIntervalTimeUnit} units for which this |
| * work repeats from the end of the {@code repeatInterval} |
| * @param flexIntervalTimeUnit The {@link TimeUnit} for {@code flexInterval} |
| */ |
| public Builder( |
| @NonNull Class<? extends ListenableWorker> workerClass, |
| long repeatInterval, |
| @NonNull TimeUnit repeatIntervalTimeUnit, |
| long flexInterval, |
| @NonNull TimeUnit flexIntervalTimeUnit) { |
| super(workerClass); |
| mWorkSpec.setPeriodic( |
| repeatIntervalTimeUnit.toMillis(repeatInterval), |
| flexIntervalTimeUnit.toMillis(flexInterval)); |
| } |
| |
| /** |
| * Creates a {@link PeriodicWorkRequest} to run periodically once within the |
| * <strong>flex period</strong> of every interval period. See diagram below. The flex |
| * period begins at {@code repeatInterval - flexInterval} to the end of the interval. |
| * The repeat interval must be greater than or equal to |
| * {@link PeriodicWorkRequest#MIN_PERIODIC_INTERVAL_MILLIS} and the flex interval must |
| * be greater than or equal to {@link PeriodicWorkRequest#MIN_PERIODIC_FLEX_MILLIS}. |
| * |
| * <p><pre> |
| * [ before flex | flex ][ before flex | flex ]... |
| * [ cannot run work | can run work ][ cannot run work | can run work ]... |
| * \____________________________________/\____________________________________/... |
| * interval 1 interval 2 ...(repeat) |
| * </pre></p> |
| * |
| * @param workerClass The {@link ListenableWorker} class to run for this work |
| * @param repeatInterval The repeat interval |
| * @param flexInterval The duration in for which this work repeats from the end of the |
| * {@code repeatInterval} |
| */ |
| @RequiresApi(26) |
| public Builder( |
| @NonNull Class<? extends ListenableWorker> workerClass, |
| @NonNull Duration repeatInterval, |
| @NonNull Duration flexInterval) { |
| super(workerClass); |
| mWorkSpec.setPeriodic(repeatInterval.toMillis(), flexInterval.toMillis()); |
| } |
| |
| @Override |
| @NonNull PeriodicWorkRequest buildInternal() { |
| if (mBackoffCriteriaSet |
| && Build.VERSION.SDK_INT >= 23 |
| && mWorkSpec.constraints.requiresDeviceIdle()) { |
| throw new IllegalArgumentException( |
| "Cannot set backoff criteria on an idle mode job"); |
| } |
| if (mWorkSpec.expedited) { |
| throw new IllegalArgumentException( |
| "PeriodicWorkRequests cannot be expedited"); |
| } |
| return new PeriodicWorkRequest(this); |
| } |
| |
| @Override |
| @NonNull Builder getThis() { |
| return this; |
| } |
| } |
| } |