1 /* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.work 18 19 import android.annotation.SuppressLint 20 import android.app.PendingIntent 21 import android.content.Context 22 import androidx.lifecycle.LiveData 23 import androidx.work.impl.WorkManagerImpl 24 import com.google.common.util.concurrent.ListenableFuture 25 import java.util.UUID 26 import kotlinx.coroutines.flow.Flow 27 28 /** 29 * WorkManager is the recommended library for persistent work. Scheduled work is guaranteed to 30 * execute sometime after its [Constraints] are met. WorkManager allows observation of work status 31 * and the ability to create complex chains of work. 32 * 33 * WorkManager uses an underlying job dispatching service when available based on the following 34 * criteria: 35 * * Uses JobScheduler for API 23+ 36 * * Uses a custom AlarmManager + BroadcastReceiver implementation for API 14-22 37 * 38 * All work must be done in a [ListenableWorker] class. A simple implementation, [Worker], is 39 * recommended as the starting point for most developers. With the optional dependencies, you can 40 * also use `CoroutineWorker` or `RxWorker`. All background work is given a maximum of ten minutes 41 * to finish its execution. After this time has expired, the worker will be signalled to stop. 42 * 43 * There are two types of work supported by WorkManager: [OneTimeWorkRequest] and 44 * [PeriodicWorkRequest]. You can enqueue requests using WorkManager as follows: 45 * ``` 46 * WorkManager workManager = WorkManager.getInstance(Context); 47 * workManager.enqueue(new OneTimeWorkRequest.Builder(FooWorker.class).build()); 48 * ``` 49 * 50 * A [WorkRequest] has an associated id that can be used for lookups and observation as follows: 51 * ``` 52 * WorkRequest request = new OneTimeWorkRequest.Builder(FooWorker.class).build(); 53 * workManager.enqueue(request); 54 * LiveData<WorkInfo> status = workManager.getWorkInfoByIdLiveData(request.getId()); 55 * status.observe(...); 56 * ``` 57 * 58 * You can also use the id for cancellation: 59 * ``` 60 * WorkRequest request = new OneTimeWorkRequest.Builder(FooWorker.class).build(); 61 * workManager.enqueue(request); 62 * workManager.cancelWorkById(request.getId()); 63 * ``` 64 * 65 * You can chain work as follows: 66 * ``` 67 * WorkRequest request1 = new OneTimeWorkRequest.Builder(FooWorker.class).build(); 68 * WorkRequest request2 = new OneTimeWorkRequest.Builder(BarWorker.class).build(); 69 * WorkRequest request3 = new OneTimeWorkRequest.Builder(BazWorker.class).build(); 70 * workManager.beginWith(request1, request2).then(request3).enqueue(); 71 * ``` 72 * 73 * Each call to [beginWith] returns a [WorkContinuation] upon which you can call 74 * [WorkContinuation.then] with a single [OneTimeWorkRequest] or a list of [OneTimeWorkRequest] to 75 * chain further work. This allows for creation of complex chains of work. For example, to create a 76 * chain like this: 77 * ``` 78 * A 79 * | 80 * +----------+ 81 * | | 82 * B C 83 * | 84 * +----+ 85 * | | 86 * D E 87 * ``` 88 * 89 * you would enqueue them as follows: 90 * ``` 91 * WorkContinuation continuation = workManager.beginWith(A); 92 * continuation.then(B).then(D, E).enqueue(); // A is implicitly enqueued here 93 * continuation.then(C).enqueue(); 94 * ``` 95 * 96 * Work is eligible for execution when all of its prerequisites are complete. If any of its 97 * prerequisites fail or are cancelled, the work will never run. 98 * 99 * WorkRequests can accept [Constraints], inputs (see [Data]), and backoff criteria. WorkRequests 100 * can be tagged with human-readable Strings (see [WorkRequest.Builder.addTag]), and chains of work 101 * can be given a uniquely-identifiable name (see [beginUniqueWork]). 102 * 103 * ### Initializing WorkManager 104 * 105 * By default, WorkManager auto-initializes itself using a built-in `ContentProvider`. 106 * ContentProviders are created and run before the `Application` object, so this allows the 107 * WorkManager singleton to be setup before your code can run in most cases. This is suitable for 108 * most developers. However, you can provide a custom [Configuration] by using 109 * [Configuration.Provider] or [WorkManager.initialize]. 110 * 111 * ### Renaming and Removing ListenableWorker Classes 112 * 113 * Exercise caution in renaming classes derived from [ListenableWorker]s. WorkManager stores the 114 * class name in its internal database when the [WorkRequest] is enqueued so it can later create an 115 * instance of that worker when constraints are met. Unless otherwise specified in the WorkManager 116 * [Configuration], this is done in the default [WorkerFactory] which tries to reflectively create 117 * the ListenableWorker object. Therefore, renaming or removing these classes is dangerous - if 118 * there is pending work with the given class, it will fail permanently if the class cannot be 119 * found. If you are using a custom WorkerFactory, make sure you properly handle cases where the 120 * class is not found so that your code does not crash. 121 * 122 * In case it is desirable to rename a class, implement a custom WorkerFactory that instantiates the 123 * right ListenableWorker for the old class name. 124 */ 125 // Suppressing Metalava checks for added abstract methods in WorkManager. 126 // WorkManager cannot be extended, because the constructor is marked @Restricted 127 @SuppressLint("AddedAbstractMethod") 128 abstract class WorkManager internal constructor() { 129 130 companion object { 131 /** 132 * Retrieves the `default` singleton instance of [WorkManager]. 133 * 134 * @return The singleton instance of [WorkManager]; this may be `null` in unusual 135 * circumstances where you have disabled automatic initialization and have failed to 136 * manually call [initialize]. 137 * @throws IllegalStateException If WorkManager is not initialized properly as per the 138 * exception message. 139 */ 140 // `open` modifier was added to avoid errors in WorkManagerImpl: 141 // "WorkManagerImpl cannot override <X> in WorkManager", even though methods are static 142 @Suppress("NON_FINAL_MEMBER_IN_OBJECT") 143 @Deprecated( 144 message = "Use the overload receiving Context", 145 replaceWith = ReplaceWith("WorkManager.getContext(context)"), 146 ) 147 @JvmStatic getInstancenull148 open fun getInstance(): WorkManager { 149 @Suppress("DEPRECATION") val workManager: WorkManager? = WorkManagerImpl.getInstance() 150 checkNotNull(workManager) { 151 "WorkManager is not initialized properly. The most " + 152 "likely cause is that you disabled WorkManagerInitializer in your manifest " + 153 "but forgot to call WorkManager#initialize in your Application#onCreate or a " + 154 "ContentProvider." 155 } 156 return workManager 157 } 158 159 /** 160 * Retrieves the `default` singleton instance of [WorkManager]. 161 * 162 * @param context A [Context] for on-demand initialization. 163 * @return The singleton instance of [WorkManager]; this may be `null` in unusual 164 * circumstances where you have disabled automatic initialization and have failed to 165 * manually call [initialize]. 166 * @throws IllegalStateException If WorkManager is not initialized properly 167 */ 168 // `open` modifier was added to avoid errors in WorkManagerImpl: 169 // "WorkManagerImpl cannot override <X> in WorkManager", even though methods are static 170 @Suppress("NON_FINAL_MEMBER_IN_OBJECT") 171 @JvmStatic getInstancenull172 open fun getInstance(context: Context): WorkManager { 173 return WorkManagerImpl.getInstance(context) 174 } 175 176 /** 177 * Used to do a one-time initialization of the [WorkManager] singleton with a custom 178 * [Configuration]. By default, this method should not be called because WorkManager is 179 * automatically initialized. To initialize WorkManager yourself, please follow these steps: 180 * * Disable `androidx.work.WorkManagerInitializer` in your manifest. 181 * * Invoke this method in `Application#onCreate` or a `ContentProvider`. Note that this 182 * method **must** be invoked in one of these two places or you risk getting a 183 * `NullPointerException` in [getInstance]. 184 * 185 * This method throws an [IllegalStateException] when attempting to initialize in direct 186 * boot mode. 187 * 188 * This method throws an exception if it is called multiple times. 189 * 190 * @param context A [Context] object for configuration purposes. Internally, this class will 191 * call [Context.getApplicationContext], so you may safely pass in any Context without 192 * risking a memory leak. 193 * @param configuration The [Configuration] for used to set up WorkManager. 194 * @see Configuration.Provider for on-demand initialization. 195 */ 196 // `open` modifier was added to avoid errors in WorkManagerImpl: 197 // "WorkManagerImpl cannot override <X> in WorkManager", even though methods are static 198 @Suppress("NON_FINAL_MEMBER_IN_OBJECT") 199 @JvmStatic initializenull200 open fun initialize(context: Context, configuration: Configuration) { 201 WorkManagerImpl.initialize(context, configuration) 202 } 203 204 /** 205 * Provides a way to check if [WorkManager] is initialized in this process. 206 * 207 * @return `true` if [WorkManager] has been initialized in this process. 208 */ 209 @Suppress("NON_FINAL_MEMBER_IN_OBJECT") 210 @JvmStatic isInitializednull211 open fun isInitialized(): Boolean = WorkManagerImpl.isInitialized() 212 } 213 214 /** The [Configuration] instance that [WorkManager] was initialized with. */ 215 abstract val configuration: Configuration 216 217 /** 218 * Enqueues one item for background processing. 219 * 220 * @param request The [WorkRequest] to enqueue 221 * @return An [Operation] that can be used to determine when the enqueue has completed 222 */ 223 fun enqueue(request: WorkRequest): Operation { 224 return enqueue(listOf(request)) 225 } 226 227 /** 228 * Enqueues one or more items for background processing. 229 * 230 * @param requests One or more [WorkRequest] to enqueue 231 * @return An [Operation] that can be used to determine when the enqueue has completed 232 */ enqueuenull233 abstract fun enqueue(requests: List<WorkRequest>): Operation 234 235 /** 236 * Begins a chain with one or more [OneTimeWorkRequest]s, which can be enqueued together in the 237 * future using [WorkContinuation.enqueue]. 238 * 239 * If any work in the chain fails or is cancelled, all of its dependent work inherits that state 240 * and will never run. 241 * 242 * @param request One or more [OneTimeWorkRequest] to start a chain of work 243 * @return A [WorkContinuation] that allows for further chaining of dependent 244 * [OneTimeWorkRequest] 245 */ 246 fun beginWith(request: OneTimeWorkRequest): WorkContinuation { 247 return beginWith(listOf(request)) 248 } 249 250 /** 251 * Begins a chain with one or more [OneTimeWorkRequest]s, which can be enqueued together in the 252 * future using [WorkContinuation.enqueue]. 253 * 254 * If any work in the chain fails or is cancelled, all of its dependent work inherits that state 255 * and will never run. 256 * 257 * @param requests One or more [OneTimeWorkRequest] to start a chain of work 258 * @return A [WorkContinuation] that allows for further chaining of dependent 259 * [OneTimeWorkRequest] 260 */ beginWithnull261 abstract fun beginWith(requests: List<OneTimeWorkRequest>): WorkContinuation 262 263 /** 264 * This method allows you to begin unique chains of work for situations where you only want one 265 * chain with a given name to be active at a time. For example, you may only want one sync 266 * operation to be active. If there is one pending, you can choose to let it run or replace it 267 * with your new work. 268 * 269 * The `uniqueWorkName` uniquely identifies this set of work. 270 * 271 * If this method determines that new work should be enqueued and run, all records of previous 272 * work with `uniqueWorkName` will be pruned. If this method determines that new work should NOT 273 * be run, then the entire chain will be considered a no-op. 274 * 275 * If any work in the chain fails or is cancelled, all of its dependent work inherits that state 276 * and will never run. This is particularly important if you are using `APPEND` as your 277 * [ExistingWorkPolicy]. 278 * 279 * @param uniqueWorkName A unique name which for this chain of work 280 * @param existingWorkPolicy An [ExistingWorkPolicy] 281 * @param request The [OneTimeWorkRequest] to enqueue. `REPLACE` ensures that if there is 282 * pending work labelled with `uniqueWorkName`, it will be cancelled and the new work will 283 * run. `KEEP` will run the new sequence of work only if there is no pending work labelled 284 * with `uniqueWorkName`. `APPEND` will create a new sequence of work if there is no existing 285 * work with `uniqueWorkName`; otherwise, `work` will be added as a child of all leaf nodes 286 * labelled with `uniqueWorkName`. 287 * @return A [WorkContinuation] that allows further chaining 288 */ 289 fun beginUniqueWork( 290 uniqueWorkName: String, 291 existingWorkPolicy: ExistingWorkPolicy, 292 request: OneTimeWorkRequest 293 ): WorkContinuation { 294 return beginUniqueWork(uniqueWorkName, existingWorkPolicy, listOf(request)) 295 } 296 297 /** 298 * This method allows you to begin unique chains of work for situations where you only want one 299 * chain with a given name to be active at a time. For example, you may only want one sync 300 * operation to be active. If there is one pending, you can choose to let it run or replace it 301 * with your new work. 302 * 303 * The `uniqueWorkName` uniquely identifies this set of work. 304 * 305 * If this method determines that new work should be enqueued and run, all records of previous 306 * work with `uniqueWorkName` will be pruned. If this method determines that new work should NOT 307 * be run, then the entire chain will be considered a no-op. 308 * 309 * If any work in the chain fails or is cancelled, all of its dependent work inherits that state 310 * and will never run. This is particularly important if you are using `APPEND` as your 311 * [ExistingWorkPolicy]. 312 * 313 * @param uniqueWorkName A unique name which for this chain of work 314 * @param existingWorkPolicy An [ExistingWorkPolicy]; see below for more information 315 * @param requests One or more [OneTimeWorkRequest] to enqueue. `REPLACE` ensures that if there 316 * is pending work labelled with `uniqueWorkName`, it will be cancelled and the new work will 317 * run. `KEEP` will run the new sequence of work only if there is no pending work labelled 318 * with `uniqueWorkName`. `APPEND` will create a new sequence of work if there is no existing 319 * work with `uniqueWorkName`; otherwise, `work` will be added as a child of all leaf nodes 320 * labelled with `uniqueWorkName`. 321 * @return A [WorkContinuation] that allows further chaining 322 */ beginUniqueWorknull323 abstract fun beginUniqueWork( 324 uniqueWorkName: String, 325 existingWorkPolicy: ExistingWorkPolicy, 326 requests: List<OneTimeWorkRequest> 327 ): WorkContinuation 328 329 /** 330 * This method allows you to enqueue `work` requests to a uniquely-named [WorkContinuation], 331 * where only one continuation of a particular name can be active at a time. For example, you 332 * may only want one sync operation to be active. If there is one pending, you can choose to let 333 * it run or replace it with your new work. 334 * 335 * The `uniqueWorkName` uniquely identifies this [WorkContinuation]. 336 * 337 * @param uniqueWorkName A unique name which for this operation 338 * @param existingWorkPolicy An [ExistingWorkPolicy]; see below for more information 339 * @param request The [OneTimeWorkRequest]s to enqueue. `REPLACE` ensures that if there is 340 * pending work labelled with `uniqueWorkName`, it will be cancelled and the new work will 341 * run. `KEEP` will run the new OneTimeWorkRequests only if there is no pending work labelled 342 * with `uniqueWorkName`. `APPEND` will append the OneTimeWorkRequests as leaf nodes labelled 343 * with `uniqueWorkName`. 344 * @return An [Operation] that can be used to determine when the enqueue has completed 345 */ 346 open fun enqueueUniqueWork( 347 uniqueWorkName: String, 348 existingWorkPolicy: ExistingWorkPolicy, 349 request: OneTimeWorkRequest 350 ): Operation { 351 return enqueueUniqueWork(uniqueWorkName, existingWorkPolicy, listOf(request)) 352 } 353 354 /** 355 * This method allows you to enqueue `work` requests to a uniquely-named [WorkContinuation], 356 * where only one continuation of a particular name can be active at a time. For example, you 357 * may only want one sync operation to be active. If there is one pending, you can choose to let 358 * it run or replace it with your new work. 359 * 360 * The `uniqueWorkName` uniquely identifies this [WorkContinuation]. 361 * 362 * @param uniqueWorkName A unique name which for this operation 363 * @param existingWorkPolicy An [ExistingWorkPolicy] 364 * @param requests [OneTimeWorkRequest]s to enqueue. `REPLACE` ensures that if there is pending 365 * work labelled with `uniqueWorkName`, it will be cancelled and the new work will run. `KEEP` 366 * will run the new OneTimeWorkRequests only if there is no pending work labelled with 367 * `uniqueWorkName`. `APPEND` will append the OneTimeWorkRequests as leaf nodes labelled with 368 * `uniqueWorkName`. 369 * @return An [Operation] that can be used to determine when the enqueue has completed 370 */ enqueueUniqueWorknull371 abstract fun enqueueUniqueWork( 372 uniqueWorkName: String, 373 existingWorkPolicy: ExistingWorkPolicy, 374 requests: List<OneTimeWorkRequest> 375 ): Operation 376 377 /** 378 * This method allows you to enqueue a uniquely-named [PeriodicWorkRequest], where only one 379 * PeriodicWorkRequest of a particular name can be active at a time. For example, you may only 380 * want one sync operation to be active. If there is one pending, you can choose to let it run 381 * or replace it with your new work. 382 * 383 * The `uniqueWorkName` uniquely identifies this PeriodicWorkRequest. 384 * 385 * @param uniqueWorkName A unique name which for this operation 386 * @param existingPeriodicWorkPolicy An [ExistingPeriodicWorkPolicy] 387 * @param request A [PeriodicWorkRequest] to enqueue. `REPLACE` ensures that if there is pending 388 * work labelled with `uniqueWorkName`, it will be cancelled and the new work will run. `KEEP` 389 * will run the new PeriodicWorkRequest only if there is no pending work labelled with 390 * `uniqueWorkName`. 391 * @return An [Operation] that can be used to determine when the enqueue has completed 392 */ 393 abstract fun enqueueUniquePeriodicWork( 394 uniqueWorkName: String, 395 existingPeriodicWorkPolicy: ExistingPeriodicWorkPolicy, 396 request: PeriodicWorkRequest 397 ): Operation 398 399 /** 400 * Cancels work with the given id if it isn't finished. Note that cancellation is a best-effort 401 * policy and work that is already executing may continue to run. Upon cancellation, 402 * [ListenableFuture] returned by [ListenableWorker.startWork] will be cancelled. Also 403 * [ListenableWorker.onStopped] will be invoked for any affected workers. 404 * 405 * @param id The id of the work 406 * @return An [Operation] that can be used to determine when the cancelWorkById has completed 407 */ 408 abstract fun cancelWorkById(id: UUID): Operation 409 410 /** 411 * Cancels all unfinished work with the given tag. Note that cancellation is a best-effort 412 * policy and work that is already executing may continue to run. Upon cancellation, 413 * [ListenableFuture] returned by [ListenableWorker.startWork] will be cancelled. Also 414 * [ListenableWorker.onStopped] will be invoked for any affected workers. 415 * 416 * @param tag The tag used to identify the work 417 * @return An [Operation] that can be used to determine when the cancelAllWorkByTag has 418 * completed 419 */ 420 abstract fun cancelAllWorkByTag(tag: String): Operation 421 422 /** 423 * Cancels all unfinished work in the work chain with the given name. Note that cancellation is 424 * a best-effort policy and work that is already executing may continue to run. Upon 425 * cancellation, [ListenableFuture] returned by [ListenableWorker.startWork] will be cancelled. 426 * Also [ListenableWorker.onStopped] will be invoked for any affected workers. 427 * 428 * @param uniqueWorkName The unique name used to identify the chain of work 429 * @return An [Operation] that can be used to determine when the cancelUniqueWork has completed 430 */ 431 abstract fun cancelUniqueWork(uniqueWorkName: String): Operation 432 433 /** 434 * Cancels all unfinished work. **Use this method with extreme caution!** By invoking it, you 435 * will potentially affect other modules or libraries in your codebase. It is strongly 436 * recommended that you use one of the other cancellation methods at your disposal. 437 * 438 * Upon cancellation, [ListenableFuture] returned by [ListenableWorker.startWork] will be 439 * cancelled. Also [ListenableWorker.onStopped] will be invoked for any affected workers. 440 * 441 * @return An [Operation] that can be used to determine when the cancelAllWork has completed 442 */ 443 abstract fun cancelAllWork(): Operation 444 445 /** 446 * Creates a [PendingIntent] which can be used to cancel a [WorkRequest] with the given `id`. 447 * 448 * @param id The [WorkRequest] id. 449 * @return The [PendingIntent] that can be used to cancel the [WorkRequest]. 450 */ 451 abstract fun createCancelPendingIntent(id: UUID): PendingIntent 452 453 /** 454 * Prunes all eligible finished work from the internal database. Eligible work must be finished 455 * ([WorkInfo.State.SUCCEEDED], [WorkInfo.State.FAILED], or [WorkInfo.State.CANCELLED]), with 456 * zero unfinished dependents. 457 * 458 * **Use this method with caution**; by invoking it, you (and any modules and libraries in your 459 * codebase) will no longer be able to observe the [WorkInfo] of the pruned work. You do not 460 * normally need to call this method - WorkManager takes care to auto-prune its work after a 461 * sane period of time. This method also ignores the 462 * [OneTimeWorkRequest.Builder.keepResultsForAtLeast] policy. 463 * 464 * @return An [Operation] that can be used to determine when the pruneWork has completed 465 */ 466 abstract fun pruneWork(): Operation 467 468 /** 469 * Gets a [LiveData] of the last time all work was cancelled. This method is intended for use by 470 * library and module developers who have dependent data in their own repository that must be 471 * updated or deleted in case someone cancels their work without their prior knowledge. 472 * 473 * @return A [LiveData] of the timestamp (`System#getCurrentTimeMillis()`) when [cancelAllWork] 474 * was last invoked; this timestamp may be `0L` if this never occurred 475 */ 476 abstract fun getLastCancelAllTimeMillisLiveData(): LiveData<Long> 477 478 /** 479 * Gets a [ListenableFuture] of the last time all work was cancelled. This method is intended 480 * for use by library and module developers who have dependent data in their own repository that 481 * must be updated or deleted in case someone cancels their work without their prior knowledge. 482 * 483 * @return A [ListenableFuture] of the timestamp (`System#getCurrentTimeMillis()`) when 484 * [cancelAllWork] was last invoked; this timestamp may be `0L` if this never occurred 485 */ 486 abstract fun getLastCancelAllTimeMillis(): ListenableFuture<Long> 487 488 /** 489 * Gets a [LiveData] of the [WorkInfo] for a given work id. 490 * 491 * @param id The id of the work 492 * @return A [LiveData] of the [WorkInfo] associated with `id`; note that this [WorkInfo] may be 493 * `null` if `id` is not known to WorkManager. 494 */ 495 abstract fun getWorkInfoByIdLiveData(id: UUID): LiveData<WorkInfo?> 496 497 /** 498 * Gets a [Flow] of the [WorkInfo] for a given work id. 499 * 500 * @param id The id of the work 501 * @return A [Flow] of the [WorkInfo] associated with `id`; note that this [WorkInfo] may be 502 * `null` if `id` is not known to WorkManager. 503 */ 504 abstract fun getWorkInfoByIdFlow(id: UUID): Flow<WorkInfo?> 505 506 /** 507 * Gets a [ListenableFuture] of the [WorkInfo] for a given work id. 508 * 509 * @param id The id of the work 510 * @return A [ListenableFuture] of the [WorkInfo] associated with `id`; note that this 511 * [WorkInfo] may be `null` if `id` is not known to WorkManager 512 */ 513 abstract fun getWorkInfoById(id: UUID): ListenableFuture<WorkInfo?> 514 515 /** 516 * Gets a [LiveData] of the [WorkInfo] for all work for a given tag. 517 * 518 * @param tag The tag of the work 519 * @return A [LiveData] list of [WorkInfo] for work tagged with `tag` 520 */ 521 abstract fun getWorkInfosByTagLiveData(tag: String): LiveData<List<WorkInfo>> 522 523 /** 524 * Gets a [Flow] of the [WorkInfo] for all work for a given tag. 525 * 526 * @param tag The tag of the work 527 * @return A [Flow] list of [WorkInfo] for work tagged with `tag` 528 */ 529 abstract fun getWorkInfosByTagFlow(tag: String): Flow<List<WorkInfo>> 530 531 /** 532 * Gets a [ListenableFuture] of the [WorkInfo] for all work for a given tag. 533 * 534 * @param tag The tag of the work 535 * @return A [ListenableFuture] list of [WorkInfo] for work tagged with `tag` 536 */ 537 abstract fun getWorkInfosByTag(tag: String): ListenableFuture<List<WorkInfo>> 538 539 /** 540 * Gets a [LiveData] of the [WorkInfo] for all work in a work chain with a given unique name. 541 * 542 * @param uniqueWorkName The unique name used to identify the chain of work 543 * @return A [LiveData] of the [WorkInfo] for work in the chain named `uniqueWorkName` 544 */ 545 abstract fun getWorkInfosForUniqueWorkLiveData(uniqueWorkName: String): LiveData<List<WorkInfo>> 546 547 /** 548 * Gets a [Flow] of the [WorkInfo] for all work in a work chain with a given unique name. 549 * 550 * @param uniqueWorkName The unique name used to identify the chain of work 551 * @return A [Flow] of the [WorkInfo] for work in the chain named `uniqueWorkName` 552 */ 553 abstract fun getWorkInfosForUniqueWorkFlow(uniqueWorkName: String): Flow<List<WorkInfo>> 554 555 /** 556 * Gets a [ListenableFuture] of the [WorkInfo] for all work in a work chain with a given unique 557 * name. 558 * 559 * @param uniqueWorkName The unique name used to identify the chain of work 560 * @return A [ListenableFuture] of the [WorkInfo] for work in the chain named `uniqueWorkName` 561 */ 562 abstract fun getWorkInfosForUniqueWork(uniqueWorkName: String): ListenableFuture<List<WorkInfo>> 563 564 /** 565 * Gets the [LiveData] of the [List] of [WorkInfo] for all work referenced by the [WorkQuery] 566 * specification. 567 * 568 * @param workQuery The work query specification 569 * @return A [LiveData] of the [List] of [WorkInfo] for work referenced by this [WorkQuery]. 570 */ 571 abstract fun getWorkInfosLiveData(workQuery: WorkQuery): LiveData<List<WorkInfo>> 572 573 /** 574 * Gets the [Flow] of the [List] of [WorkInfo] for all work referenced by the [WorkQuery] 575 * specification. 576 * 577 * @param workQuery The work query specification 578 * @return A [Flow] of the [List] of [WorkInfo] for work referenced by this [WorkQuery]. 579 */ 580 abstract fun getWorkInfosFlow(workQuery: WorkQuery): Flow<List<WorkInfo>> 581 582 /** 583 * Gets the [ListenableFuture] of the [List] of [WorkInfo] for all work referenced by the 584 * [WorkQuery] specification. 585 * 586 * @param workQuery The work query specification 587 * @return A [ListenableFuture] of the [List] of [WorkInfo] for work referenced by this 588 * [WorkQuery]. 589 */ 590 abstract fun getWorkInfos(workQuery: WorkQuery): ListenableFuture<List<WorkInfo>> 591 592 /** 593 * Updates the work with the new specification. A [WorkRequest] passed as parameter must have an 594 * id set with [WorkRequest.Builder.setId] that matches an id of the previously enqueued work. 595 * 596 * It preserves enqueue time, e.g. if a work was enqueued 3 hours ago and had 6 hours long 597 * initial delay, after the update it would be still eligible for run in 3 hours, assuming that 598 * initial delay wasn't updated. 599 * 600 * If the work being updated is currently running the returned ListenableFuture will be 601 * completed with [UpdateResult.APPLIED_FOR_NEXT_RUN]. In this case the current run won't be 602 * interrupted and will continue to rely on previous state of the request, e.g. using old 603 * constraints, tags etc. However, on the next run, e.g. retry of one-time Worker or another 604 * iteration of periodic worker, the new worker specification will be used. 605 * 606 * If the one time work that is updated is already finished the returned ListenableFuture will 607 * be completed with [UpdateResult.NOT_APPLIED]. 608 * 609 * If update can be applied immediately, e.g. the updated work isn't currently running, the 610 * returned ListenableFuture will be completed with [UpdateResult.APPLIED_IMMEDIATELY]. 611 * 612 * If the work with the given id (`request.getId()`) doesn't exist the returned ListenableFuture 613 * will be completed exceptionally with [IllegalArgumentException]. 614 * 615 * Worker type can't be changed, [OneTimeWorkRequest] can't be updated to [PeriodicWorkRequest] 616 * and otherwise, the returned ListenableFuture will be completed with 617 * [IllegalArgumentException]. 618 * 619 * @param request the new specification for the work. 620 * @return a [ListenableFuture] that will be successfully completed if the update was 621 * successful. The future will be completed with an exception if the work is already running 622 * or finished. 623 */ 624 // consistent with already existent method like getWorkInfos() in WorkManager 625 @Suppress("AsyncSuffixFuture") 626 abstract fun updateWork(request: WorkRequest): ListenableFuture<UpdateResult> 627 628 /** An enumeration of results for [WorkManager.updateWork] method. */ 629 enum class UpdateResult { 630 /** An update wasn't applied, because `Worker` has already finished. */ 631 NOT_APPLIED, 632 633 /** 634 * An update was successfully applied immediately, meaning the updated work wasn't currently 635 * running in the moment of the request. See [UpdateResult.APPLIED_FOR_NEXT_RUN] for the 636 * case of running worker. 637 */ 638 APPLIED_IMMEDIATELY, 639 640 /** 641 * An update was successfully applied, but the worker being updated was running. This run 642 * isn't interrupted and will continue to rely on previous state of the request, e.g. using 643 * old constraints, tags etc. However, on the next run, e.g. retry of one-time Worker or 644 * another iteration of periodic worker, the new worker specification. will be used. 645 */ 646 APPLIED_FOR_NEXT_RUN, 647 } 648 } 649