SkillAgentSearch skills...

AppUpdateWrapper

A wrapper for Android `AppUpdateManager` to encapsulate update workflow

Install / Use

/learn @motorro/AppUpdateWrapper
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

AppUpdateWrapper Check Maven Central

A wrapper for Android AppUpdateManager to simplify in-app update flow.

Here is an intoroduction article to this library describing problems I've come across when implementing in-app updates in a real-world Android application.

Contents

<!-- toc --> <!-- tocstop -->

Features

  • A complete lifecycle-aware component to take a burden of managing update state (especially FLEXIBLE).
  • You should only implement a couple of UI methods to display install consents the way you like it to get running.
  • Makes things easier to run flexible update for multi-activity applications - suspends and resumes UI interaction along with main application flow.
  • Flexible updates are non-intrusive for app users with UpdateFlowBreaker.

Basics

Refer to original documentation to understand the basics of in-app update. This library consists of two counterparts:

  • AppUpdateWrapper is a presenter (or presentation model to some extent) that is responsible for carrying out the IMMEDIATE or FLEXIBLE update flow. It is designed as a single-use lifecycle observer that starts the flow as soon as it is created. The wrapper will also maintain a current state of update especially the UI state (the thing missing in original AppUpdateManager). The update flow completes either with calling updateComplete() or updateFailed(e: Throwable) methods of AppUpdateView.
  • AppUpdateView is a presenter counterpart that you implement to ask user consents, notify of update errors, etc.

Here is the basic activity setup that is enough to run a flexible update in background each time your activity starts:

/**
 * Basic update activity that checks for update
 */
class TestActivity : AppCompatActivity(), AppUpdateView {
    /**
     * Update flow
     */
    private lateinit var updateWrapper: AppUpdateWrapper

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Starts flexible update flow that (if cancelled) will ask again tomorrow
        updateWrapper = startFlexibleUpdate(
            AppUpdateManagerFactory.create(this.applicationContext),
            this,
            UpdateFlowBreaker.forOneDay(getSharedPreferences("uiState", Context.MODE_PRIVATE))
        )
    }

    // Passes an activity result to wrapper to check for play-core interaction
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (updateWrapper.checkActivityResult(requestCode, resultCode)) {
            // Result handled and processed
            return
        }
        // Process your request codes
    }

    /********************************/
    /* AppUpdateView implementation */
    /********************************/

    // AppUpdateManager needs your activity to start dialogs
    override val resultContractRegistry: ActivityResultRegistry = this.activityResultRegistry

    // Called when flow starts
    override fun updateChecking() {
        // Show some spinner...
    }

    // Update is downloaded and ready to install
    override fun updateReady() {
        // Display confirmation dialog of your choice and complete update...
        updateWrapper.userConfirmedUpdate()
        // ...or cancel it
        updateWrapper.userCanceledUpdate()
    }

    // Update check complete
    override fun updateComplete() {
        Toast.makeText(this, "Update check complete", Toast.LENGTH_SHORT).show()
    }

    // Update check critical error (effective in IMMEDIATE flow)
    override fun updateFailed(e: Throwable) {
        Toast.makeText(this, "Update failed", Toast.LENGTH_SHORT).show()
        finish()
    }
}

Using in your project

Follow the steps below to use AppUpdateWrapper in your application. Some of them are optional, some of them are required for multi-activity applications only.

1. Setting up the dependency

repositories {
    mavenCentral()
}

dependencies {
    implementation 'com.motorro.appupdatewrapper:appupdatewrapper:x.x.x@aar'
}

2. Implementing AppUpdateView

AppUpdateView represents a UI part of application update flow and the only point of interaction between your application and AppUpdateWrapper. You may directly extend it in your hosting Activity or delegate it to some fragment. Here are the methods you may implement:

resultContractRegistry (mandatory)

val resultContractRegistry: ActivityResultRegistry

AppUpdateManager launches activities on behalf of your application. Implement this value to pass the activity result registry that will handle the onActivityResult. Typically you pass your activity activityResultRegistry there.

updateReady (mandatory)

fun updateReady()

Called in flexible flow to report that update has been downloaded and ready to be installed. The UI may display some confirmation dialogue at this point. Depending on user's answer call AppUpdateWrapper.userConfirmedUpdate to install and restart or AppUpdateWrapper.userCanceledUpdate to postpone installation. The next time the user will be asked to update an app in a latter case is configurable.

updateFailed (mandatory)

fun updateFailed(e: Throwable)

Effective within the IMMEDIATE update flow to report a critical update error. Within the immediate update flow this is considered critical and you may want to terminate application.

updateDownloadProgress (optional)

fun updateDownloadProgress(bytesLoaded: Long, bytesTotal: Long)

Called in flexible flow to report that update download progress. You may display a progress bar or something.

  • bytesLoaded - number of bytes downloaded
  • bytesTotal - total number of bytes to download

updateChecking (optional)

fun updateChecking()

Called by presenter when update flow starts. UI may display a spinner of some kind.

updateDownloadStarts (optional)

fun updateDownloadStarts()

Called when user confirms flexible update and background download begins. Called in flexible flow.

updateInstallUiVisible (optional)

fun updateInstallUiVisible()

Called when play-core install activity covers your application. In some cases (immediate update flow for example) you may want to finish your main activity (or clear stack) at this point so user won't 'back' to it from update screen.

updateComplete (optional)

fun updateComplete()

Called when flow is finished. Either update not found, or cancelled, etc. Indicates a successful outcome. Called in flexible flow. Immediate flow either restarts (on success) or fails with updateFailed.

nonCriticalUpdateError (optional)

fun nonCriticalUpdateError(e: Throwable)

Some error occurred during the update but it is considered non-critical within selected update flow. UI may toast or notify the user in some other way. Called in flexible flow. Immediate flow is designed to be mandatory so it fails with critical updateFailed.

3. Start your update flow

The library supports both IMMEDIATE and FLEXIBLE update flows.

  • Choose IMMEDIATE flow when you need user to update or to quit. For example you may receive a 'not-supported' message from your server and user can't use the outdated application any
View on GitHub
GitHub Stars36
CategoryDevelopment
Updated7mo ago
Forks2

Languages

Kotlin

Security Score

87/100

Audited on Aug 25, 2025

No findings