Skip to content

pavi2410/kmp-app-updater

Repository files navigation

kmp-app-updater

CI Maven Central

A Kotlin Multiplatform library for in-app updates. Supports Android and Desktop (JVM).

Features

  • Pluggable update sources — GitHub Releases out of the box, bring your own for GitLab / custom servers
  • Streaming download with real-time progress via StateFlow<UpdateState>
  • Platform-specific installation (APK intent on Android, OS launcher on Desktop)
  • Pre-built Compose Multiplatform UI components (optional)
  • Configurable asset matching (.apk, .msi, .dmg, etc.)
  • Pre-release support

Modules

Module Description
:core Headless KMP library — AppUpdater, UpdateSource, downloader, installer
:compose-ui Optional Compose Multiplatform UI — UpdateCard, DownloadProgressIndicator, UpdateBanner
:sample:android Android demo app
:sample:desktop Desktop demo app

Quick Start

Android

Platform defaults (downloader, installer, asset matcher) are wired automatically:

val updater = AppUpdater.github(
    context = applicationContext,
    owner = "your-org",
    repo = "your-app",
    // currentVersion auto-detected from PackageManager
)

// Check → Download → Install
updater.checkForUpdate()
updater.downloadUpdate()   // observe updater.state for progress
updater.installUpdate()

Desktop

val updater = AppUpdater.github(
    owner = "your-org",
    repo = "your-app",
    currentVersion = "1.0.0",
)

Custom Update Source

Implement UpdateSource to connect any backend:

val updater = AppUpdater(
    currentVersion = "1.0.0",
    source = object : UpdateSource {
        override suspend fun fetchReleases() = listOf(/* your releases */)
    },
    downloader = myDownloader,
    installer = myInstaller,
    assetMatcher = { it.endsWith(".msi") },
)

With Compose UI

UpdateCard(updater = updater)

State Machine

Idle → Checking → UpdateAvailable → Downloading(progress) → ReadyToInstall
                → UpToDate
                → Error

Observe updater.state: StateFlow<UpdateState> for reactive UI updates.

// Compose
val state by updater.state.collectAsState()
when (state) {
    is UpdateState.Downloading -> DownloadProgressIndicator(state.progress, ...)
    // ...
}

// Coroutines
updater.state.collect { state -> /* react */ }

Background Updates

Android (WorkManager)

Use WorkManager to check for updates periodically in the background:

class UpdateCheckWorker(
    context: Context,
    params: WorkerParameters,
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        val updater = AppUpdater.github(
            context = applicationContext,
            owner = "your-org",
            repo = "your-app",
        )
        val release = updater.checkForUpdate()
        if (release != null) {
            // Show a notification prompting the user to update
        }
        return Result.success()
    }
}

// Schedule periodic checks (e.g. once every 24 hours)
val request = PeriodicWorkRequestBuilder<UpdateCheckWorker>(24, TimeUnit.HOURS)
    .setConstraints(
        Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()
    )
    .build()

WorkManager.getInstance(context).enqueueUniquePeriodicWork(
    "update_check",
    ExistingPeriodicWorkPolicy.KEEP,
    request,
)

Desktop (Coroutine Timer)

On Desktop JVM, use a coroutine-based timer to poll for updates:

fun startBackgroundUpdateCheck(updater: AppUpdater, scope: CoroutineScope) {
    scope.launch {
        while (isActive) {
            updater.checkForUpdate()
            delay(24.hours)
        }
    }
}

Android Setup

Add to your AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

And res/xml/file_paths.xml:

<paths>
    <cache-path name="app_updates" path="app_updates/" />
</paths>

License

Apache 2.0

About

Kotlin Multiplatform in-app update library with pluggable update sources. Android + Desktop JVM.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages