Write once, schedule anywhere. Unified API for background tasks on Android & iOS.
📖 Documentation • 🚀 Quick Start • 💡 Examples • 📦 Migration to v3.0
- 🚀 60% Faster iOS - File-based storage replaces NSUserDefaults
- 🎯 Better API Design -
SystemConstraintreplaces trigger/constraint confusion - ⏰ Smart Exact Alarms - Auto-fallback when permission denied (Android 12+)
- 🔋 Heavy Task Support - New
KmpHeavyWorkerfor long-running tasks - 🔔 AlarmReceiver Base - Easy exact alarm implementation
- 🛡️ Thread-Safe iOS - File locking + duplicate detection
See Full Migration Guide | Breaking Changes: Deprecated triggers (backward compatible)
// Android - WorkManager
val androidWork = OneTimeWorkRequestBuilder<SyncWorker>()
.setConstraints(/* ... */)
.build()
WorkManager.getInstance(context).enqueue(androidWork)
// iOS - Different API!
BGTaskScheduler.shared.submit(BGAppRefreshTaskRequest(/* ... */))Different APIs. Double the code. Double the bugs. |
// One API for both platforms!
scheduler.enqueue(
id = "data-sync",
trigger = TaskTrigger.Periodic(15_MINUTES),
workerClassName = "SyncWorker",
constraints = Constraints(requiresNetwork = true)
)Single unified API. Shared code. Zero headaches. |
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.vietnguyentuan2019:kmptaskmanager:3.0.0")
}
}
}|
Android - startKoin {
androidContext(this@MyApp)
modules(kmpTaskManagerModule())
} |
iOS - KoinIOSKt.doInitKoinIos()
registerBackgroundTasks() |
class MyViewModel(private val scheduler: BackgroundTaskScheduler) {
fun scheduleSync() = viewModelScope.launch {
scheduler.enqueue(
id = "data-sync",
trigger = TaskTrigger.Periodic(intervalMs = 15_MINUTES),
workerClassName = "SyncWorker",
constraints = Constraints(requiresNetwork = true)
)
}
}That's it! Your task runs on both Android and iOS!
scheduler.enqueue(
id = "user-data-sync",
trigger = TaskTrigger.Periodic(intervalMs = 15_MINUTES),
workerClassName = "SyncWorker",
constraints = Constraints(requiresNetwork = true)
)// Execute tasks in sequence: Download → Process → Upload
scheduler
.beginWith(TaskRequest(workerClassName = "DownloadWorker"))
.then(TaskRequest(workerClassName = "ProcessWorker"))
.then(TaskRequest(workerClassName = "UploadWorker"))
.enqueue()
// Run tasks in parallel, then finalize
scheduler
.beginWith(listOf(
TaskRequest("SyncWorker"),
TaskRequest("CacheWorker"),
TaskRequest("CleanupWorker")
))
.then(TaskRequest("FinalizeWorker"))
.enqueue()scheduler.enqueue(
id = "ml-training",
trigger = TaskTrigger.OneTime(),
workerClassName = "MLTrainingWorker",
constraints = Constraints(
isHeavyTask = true,
requiresCharging = true,
systemConstraints = setOf(
SystemConstraint.REQUIRE_BATTERY_NOT_LOW,
SystemConstraint.DEVICE_IDLE
)
)
)// v3.0+: Automatically falls back to WorkManager if permission denied
class MyScheduler(context: Context) : NativeTaskScheduler(context) {
override fun getAlarmReceiverClass() = MyAlarmReceiver::class.java
}
scheduler.enqueue(
id = "reminder",
trigger = TaskTrigger.Exact(atEpochMillis = System.currentTimeMillis() + 60_000),
workerClassName = "ReminderWorker"
)| Feature | KMP TaskManager | Others |
|---|---|---|
| Unified API (Android + iOS) | ✅ | ❌ |
| 9 Trigger Types | ✅ | 1-2 |
| Task Chains (Sequential & Parallel) | ✅ | ❌ |
| Smart Retry with Backoff | ✅ | ❌ |
| Real-time Event System | ✅ | ❌ |
| Exact Alarm Auto-Fallback | ✅ v3.0 | ❌ |
| Heavy Task Support | ✅ v3.0 | ❌ |
| Production Ready | ✅ v3.0.0 |
- Periodic - Repeat at intervals (15 min minimum)
- OneTime - Run once with optional delay
- Exact - Precise timing (alarms, reminders)
- ContentUri - React to media changes (Android)
- Windowed - iOS time window (not implemented)
constraints = Constraints(
requiresNetwork = true,
requiresCharging = true,
systemConstraints = setOf(
SystemConstraint.REQUIRE_BATTERY_NOT_LOW, // Battery > 15%
SystemConstraint.DEVICE_IDLE, // Device idle
SystemConstraint.ALLOW_LOW_STORAGE, // Allow when storage low
SystemConstraint.ALLOW_LOW_BATTERY // Allow when battery low
)
)constraints = Constraints(
backoffPolicy = BackoffPolicy.EXPONENTIAL,
backoffDelayMs = 10_000 // 10s → 20s → 40s → 80s...
)
|
|
- Quick Start Guide - Get up and running in 5 minutes
- Migration to v3.0 - Upgrade from v2.x
- Platform Setup - Android & iOS configuration
- Examples - Real-world use cases
- API Reference - Complete API documentation
- Task Chains Guide - Sequential & parallel workflows
- Architecture Guide - Design & implementation
- Native APIs: Different code for each platform, hard to maintain
- KMP TaskManager: Single API, shared code, maintainable
- Others: Limited features (1-2 triggers), no chains, pre-release
- KMP TaskManager: 9 triggers, task chains, production-ready v3.0
- Fully Tested - 100+ test cases covering edge cases
- Type-Safe - 100% Kotlin with strong typing
- Well Documented - Comprehensive guides & API docs
- Actively Maintained - Regular updates and bug fixes
- Production Proven - Used in real-world apps
We love contributions! Here's how you can help:
- Report bugs via GitHub Issues
- Suggest features in GitHub Issues
- Improve docs - Submit a PR
- Star the repo - Show your support!
Copyright © 2025 Nguyễn Tuấn Việt
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.
If KMP TaskManager saves you time, please give us a star!
It helps other developers discover this project.
Made with ❤️ by Nguyễn Tuấn Việt
Support: [email protected] • Community: GitHub Issues