README.md

March 29, 2026 · View on GitHub

Android App Updater

A flexible, lightweight Android library to prompt users to update your app — via 16 app stores or direct APK download.

Maven Central Android Arsenal API 23+ Codacy Badge License


Features

  • Works with Jetpack Compose and XML Views (DialogFragment)
  • Supports 16 app stores out of the box (Google Play, Huawei, Samsung, Amazon, and more)
  • Direct APK download with built-in download management and installation
  • Light, Dark, and System Default themes
  • Force update mode (non-dismissable dialog)
  • Custom typeface support
  • DSL builders for clean, expressive configuration
  • Built-in store icons for all supported stores
  • Handles APK installation across all API levels (M through latest)
  • Customizable string resources for localization

Installation

Add the dependency for the module that matches your UI toolkit:

dependencies {
    // Jetpack Compose
    implementation("com.pouyaheydari.updater:compose:latest_version")

    // XML Views / DialogFragment
    implementation("com.pouyaheydari.updater:main:latest_version")
}

Replace latest_version with the latest version from Maven Central.


Quick Start

1. Define your store list

val stores = listOf(
    StoreListItem(
        store = StoreFactory.getStore(AppStoreType.GOOGLE_PLAY, "com.your.package"),
        title = "Google Play",
        icon = R.drawable.appupdater_ic_google_play
    ),
    StoreListItem(
        store = StoreFactory.getStore(AppStoreType.HUAWEI_APP_GALLERY, "com.your.package"),
        title = "Huawei AppGallery",
        icon = R.drawable.appupdater_ic_app_gallery
    )
)

Add these permissions to your AndroidManifest.xml:

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

Then create the list:

val directLinks = listOf(
    DirectDownloadListItem(
        title = "Direct Download",
        url = "https://example.com/your-app.apk"
    )
)

3. Show the dialog

Jetpack Compose

var showDialog by remember { mutableStateOf(true) }

if (showDialog) {
    AndroidAppUpdater(
        dialogData = UpdaterDialogData(
            dialogTitle = "New Update Available!",
            dialogDescription = "We've added new features and fixed bugs.",
            dividerText = "or",
            storeList = stores,
            directDownloadList = directLinks,
            onDismissRequested = { showDialog = false },
            theme = Theme.SYSTEM_DEFAULT
        )
    )
}

DialogFragment (XML Views)

AppUpdaterDialog.getInstance(
    UpdaterDialogData(
        title = "New Update Available!",
        description = "We've added new features and fixed bugs.",
        storeList = stores,
        directDownloadList = directLinks,
        isForceUpdate = false,
        theme = Theme.LIGHT
    )
).show(supportFragmentManager, "updater")

DSL Builders

Both Compose and Fragment APIs offer Kotlin DSL builders for a more expressive syntax.

Fragment DSL

updateDialogBuilder {
    title = "New Update Available!"
    description = "We've added new features and fixed bugs."
    isForceUpdate = false
    theme = Theme.DARK
    storeList = listOf(
        store {
            store = StoreFactory.getStore(AppStoreType.GOOGLE_PLAY, "com.your.package")
            title = "Google Play"
            icon = R.drawable.appupdater_ic_google_play
        }
    )
    directDownloadList = listOf(
        directDownload {
            title = "Direct Download"
            url = "https://example.com/your-app.apk"
        }
    )
    typeface = Typeface.createFromAsset(assets, "fonts/custom.ttf")
    errorWhileOpeningStoreCallback = { storeName ->
        Toast.makeText(this@MainActivity, "$storeName is not installed", Toast.LENGTH_SHORT).show()
    }
}.show(supportFragmentManager, "updater")

Compose DSL

val dialogData = updaterDialogData {
    dialogTitle = "New Update Available!"
    dialogDescription = "We've added new features and fixed bugs."
    dividerText = "or"
    theme = Theme.SYSTEM_DEFAULT
    storeList = listOf(
        store {
            store = StoreFactory.getStore(AppStoreType.GOOGLE_PLAY, "com.your.package")
            title = "Google Play"
            icon = R.drawable.appupdater_ic_google_play
        }
    )
    directDownloadList = listOf(
        directDownload {
            title = "Direct Download"
            url = "https://example.com/your-app.apk"
        }
    )
    onDismissRequested = { /* handle dismiss */ }
    errorWhileOpeningStoreCallback = { storeName -> /* handle error */ }
}

AndroidAppUpdater(dialogData)

Configuration Reference

Fragment UpdaterDialogData

ParameterTypeDefaultDescription
titleString""Title shown at the top of the dialog
descriptionString""Description text below the title
storeListList<StoreListItem>[]App stores to show as update options
directDownloadListList<DirectDownloadListItem>[]Direct APK download links
isForceUpdateBooleanfalseIf true, the dialog cannot be dismissed
typefaceTypeface?nullCustom typeface for dialog text
themeThemeSYSTEM_DEFAULTLIGHT, DARK, or SYSTEM_DEFAULT
errorWhileOpeningStoreCallback((String) -> Unit)?nullCalled with store name if opening fails

Compose UpdaterDialogData

ParameterTypeDefaultDescription
dialogTitleString""Title shown at the top of the dialog
dialogDescriptionString""Description text below the title
dividerTextString""Text on the divider between stores and downloads
storeListList<StoreListItem>[]App stores to show as update options
directDownloadListList<DirectDownloadListItem>[]Direct APK download links
onDismissRequested() -> Unit{}Called when the user dismisses the dialog
typefaceTypeface?nullCustom typeface for dialog text
themeThemeSYSTEM_DEFAULTLIGHT, DARK, or SYSTEM_DEFAULT
errorWhileOpeningStoreCallback(String) -> Unit{}Called with store name if opening fails

Supported Stores

StoreEnum ValueBuilt-in Icon
Google PlayGOOGLE_PLAYappupdater_ic_google_play
Cafe BazaarCAFE_BAZAARappupdater_ic_bazar
MyketMYKETappupdater_ic_myket
Huawei AppGalleryHUAWEI_APP_GALLERYappupdater_ic_app_gallery
Samsung Galaxy StoreSAMSUNG_GALAXY_STOREappupdater_ic_galaxy_store
Amazon App StoreAMAZON_APP_STOREappupdater_ic_amazon_app_store
AptoideAPTOIDEappupdater_ic_aptoide
F-DroidFDROIDappupdater_ic_fdroid
Xiaomi GetAppsMI_GET_APP_STOREappupdater_ic_get_app_store
OneStoreONE_STORE_APP_MARKETappupdater_ic_one_store
Oppo App MarketOPPO_APP_MARKETappupdater_ic_oppo_app_market
Vivo V-AppStoreV_APP_STOREappupdater_ic_v_app_store
9AppsNINE_APPS_STOREappupdater_ic_nine_apps
Tencent App StoreTENCENT_APPS_STOREappupdater_ic_tencent_app_store
ZTE App CenterZTE_APP_CENTERappupdater_ic_zte_app_center
Lenovo App CenterLENOVO_APP_CENTERappupdater_ic_lenovo_app_center

All icons are bundled with the library. Use them via R.drawable.appupdater_ic_*.


Customization

Themes

Pass one of the Theme enum values to control the dialog appearance:

Theme.LIGHT          // Light background, dark text
Theme.DARK           // Dark background, light text
Theme.SYSTEM_DEFAULT // Follows the device's current theme

Custom Typeface

val typeface = Typeface.createFromAsset(assets, "fonts/your_font.ttf")

// Pass it to either API:
UpdaterDialogData(
    // ...
    typeface = typeface
)

String Resources

Override these in your strings.xml to localize or customize dialog text:

<string name="appupdater_please_wait">Please wait</string>
<string name="appupdater_downloading_new_version">Downloading new version...</string>
<string name="appupdater_download_notification_title">Downloading...</string>
<string name="appupdater_download_notification_desc">Downloading new version</string>
<string name="appupdater_please_install">Please install</string>
<string name="appupdater_or">or</string>
<string name="appupdater_download_from_store">Download from store</string>
<string name="appupdater_couldnt_find_downloaded_file">Couldn't find downloaded file</string>

Architecture

The library is split into focused modules:

AndroidAppUpdater/
├── core/             # Theme enum and shared constants (pure Kotlin)
├── store/            # Store implementations, StoreFactory, icons
├── directdownload/   # APK download via DownloadManager + installation
├── appupdater/       # Fragment/XML UI (published as "main")
├── compose/          # Jetpack Compose UI
└── app/              # Sample/demo application
ModuleArtifactDescription
:corecom.pouyaheydari.updater:coreTheme enum and constants — no Android dependency
:storecom.pouyaheydari.updater:storeAll 16 store implementations with built-in icons
:directdownloadcom.pouyaheydari.updater:directdownloadDownload manager, permissions, APK installation
:appupdatercom.pouyaheydari.updater:mainDialogFragment-based update dialog
:composecom.pouyaheydari.updater:composeJetpack Compose update dialog

Requirements

RequirementValue
Min SDK23 (Android 6.0)
Compile SDK36
Kotlin2.3+
Java17

Sample App

The :app module contains a fully working demo with examples for:

  • Kotlin API — Direct constructor usage
  • DSL API — Builder-style configuration
  • Compose — Composable dialog integration

Clone the repo and run the app module to see the library in action.


License

Copyright 2018 Pouya Heydari

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.

Library icon and design by Amir Gerdakane