Schedule a one-shot¶
A one-shot job runs once. It survives process death and reboot (unless ephemeral = true), and is retried per BackoffPolicy.maxAttempts if the worker returns WorkResult.Retry.
import com.happycodelucky.backgrounder.*
import kotlin.time.Duration.Companion.seconds
val outcome = backgrounder.schedule(
WorkRequest.OneTime(
taskId = SyncWorker.ID,
constraints = WorkConstraints(
networkRequired = NetworkRequirement.Any,
requiresCharging = false,
),
initialDelay = 30.seconds,
backoff = BackoffPolicy.exponential(
initialDelay = 30.seconds,
maxAttempts = 5,
),
),
)
when (outcome) {
ScheduleOutcome.Scheduled -> Unit
is ScheduleOutcome.Rejected -> log.e { "rejected: ${outcome.reason}" }
}
What can go wrong¶
- iOS Info.plist — every
TaskIdyou schedule must appear inBGTaskSchedulerPermittedIdentifiers. The library logs an error duringbackgrounder.start()if it's missing; rejected atschedule()time withScheduleOutcome.Rejected. - Constraints conflict on iOS —
NetworkRequirement.Unmeteredis honoured by the library's pre-execution reachability gate (isDataMetered == false), but the OS-level scheduling hint (BGProcessingTaskRequest.requiresNetworkConnectivity) is downgraded toAnywith a log warning — iOS's BGTaskScheduler has no metered/unmetered distinction at the dispatch level. - Backoff policy with too-small initial delay — minimum is 10 seconds, validated at construction.
Conflict policy¶
If a one-shot with the same TaskId is already pending:
backgrounder.schedule(request, policy = ConflictPolicy.Replace) // default — cancel pending, enqueue new
backgrounder.schedule(request, policy = ConflictPolicy.Keep) // ignore new, keep pending
Append (Android chained-work semantics) is v2.
Periodic Replace on Android is an in-place update
For periodic work on Android, Replace maps to WorkManager's ExistingPeriodicWorkPolicy.UPDATE: the existing request's interval, constraints, and input are patched in place, preserving run history and the next-run anchor. It is not a cancel-and-re-enqueue — the cadence does not reset. One-shot Replace keeps the cancel-and-re-enqueue semantics (ExistingWorkPolicy.REPLACE).