ApexFetch is an enterprise-grade download manager for Kotlin Multiplatform (KMP). It is designed to handle large-scale file downloads with built-in local database persistence, automatic resume capabilities, and modern UI support for Android (Jetpack Compose & XML View Systems) and Desktop (Windows & Linux).
ApexFetch is divided into modular components for maximum flexibility:
apexfetch-coreβ The pure KMP logic core (Ktor, Okio, SQLDelight).apexfetch-composeβ UI wrapper for Compose Multiplatform (rememberApexDownload).apexfetch-android-xmlβ Extensions for Android XML View Systems (LiveData & ViewModel).
- Smart Resume β Automatically resumes downloads from the last downloaded byte using HTTP Range headers.
- Local Persistence β Stores download history and real-time states in a local SQLite database.
- Multiplatform β Write once, run on Android, Windows, and Linux.
- Lifecycle Aware β Safely manages download scopes, specifically tailored for UI modules.
- Disk-Efficient β Writes streams directly to storage via Okio to prevent memory overhead and OOM crashes.
Ensure your development environment meets the following specifications:
| Requirement | Version |
|---|---|
| Kotlin | 2.1.0 |
| Android Gradle Plugin (AGP) | 8.11.2 |
| SQLDelight | 2.0.1 |
Android minSdk |
21 (Android 5.0 Lollipop) |
Android compileSdk |
34 (Android 14) |
| Java Source/Target | Java 8 (VERSION_1_8) |
| JDK (to run AGP 8.x) | 17+ |
Supported Targets: Android, JVM (Desktop)
Kotlin DSL (settings.gradle.kts)
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
}Groovy (settings.gradle)
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
}Add the required modules to your app or module-level build.gradle.kts or build.gradle:
Kotlin DSL
dependencies {
val apexVersion = "1.0.0"
// Core engine (required)
implementation("io.github.muhamadsyafii:apexfetch-core:$apexVersion")
// For Jetpack Compose / Compose Multiplatform
implementation("io.github.muhamadsyafii:apexfetch-compose:$apexVersion")
// For Android XML (LiveData support)
implementation("io.github.muhamadsyafii:apexfetch-android-xml:$apexVersion")
}Groovy
dependencies {
def apexVersion = "1.0.0"
// Core engine (required)
implementation "io.github.muhamadsyafii:apexfetch-core:$apexVersion"
// For Jetpack Compose / Compose Multiplatform
implementation "io.github.muhamadsyafii:apexfetch-compose:$apexVersion"
// For Android XML (LiveData support)
implementation "io.github.muhamadsyafii:apexfetch-android-xml:$apexVersion"
}val fetcher = ApexFetcher(database = mySqlDelightDb)val download = rememberApexDownload(fetcher, url, path)
Button(onClick = { download.start() }) {
Text("Download Now")
}
if (download.state.value is DownloadState.Downloading) {
val progress = (download.state.value as DownloadState.Downloading).progress
LinearProgressIndicator(progress = progress / 100f)
}fetcher.downloadAsLiveData(url, path).observe(viewLifecycleOwner) { state ->
when (state) {
is DownloadState.Downloading -> binding.progressBar.progress = state.progress
is DownloadState.Success -> binding.statusText.text = "Completed!"
// Handle other states: Paused, Error, etc.
}
}Contributions are welcome! Please read our CONTRIBUTING.md before submitting a pull request.
By contributing to this project, you agree that your contributions will be licensed under the Apache License 2.0.
Copyright 2026 Muhamad Syafii
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
https://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.



