Implementing in-app updates on Android

Before starting, please open your play store and check for app updates. What did you found? Almost every app in your mobile device will have some app update. But what to do with this in our blog? I asked you to do this because I want to show you that the user of an app download the app, uses it but he/she never bothers about the update of the app and due to this they might not get the latest feature of the app

Being an Android developer, we want our users to have the latest version of our app. But in real life, only a few users have the updated version of our app. One of the major reason for not updating the app is that the users don’t have much time to go to the play store to search for updates and then download and install the update.

To address the same problem, Google has proposed an in-app update system to update the apps. In this feature, you can update your app on your user’s mobile by taking permission from the user. The user can use the app during downloading the update. So, now user need not go to the play store to find the update for your app.

In this blog, we will learn how to implement the in-app update in our app. So, let’s get started.

In-app update

The in-app update is a feature of Android Play Core library, that allows you to provide a prompt to the user to offer them an in-app update for a particular app. In simple words, it provides an option to the user which says that an update for the app is available and the user can select if they are interested in updating the app or not.

Not only that, it provides an option to download the update of the app in the background and once downloaded, install the update and restart the app and the user don’t have to do anything.

The Play Core Library offers two ways of implementing the in-app update in our mobile application. Let’s look at them, one by one:

Flexible Update

If your app update contains some features that don’t affect the core functionality of your app, then you can use the flexible update option in your app. In flexible update, the update of the app is download in the background. After downloading, the user will be asked to restart the app. During the restart period, the update of the app will be installed and the app will be restarted. The benefit of using this is, the user can use the app until the download process is finished. A simple flexible update example is shown below:

Immediate Update

If your app update contains the features that directly affect the core functionality of your app, then you should use the immediate update facility. In the immediate update, a prompt or alert dialog box is opened to ask the user for downloading and installing the update of the app. The user can’t use the app until the downloading, installing and restart will be done. A simple example of an in-app update using the immediate update is shown below:

Check for update

Before doing the update operation, you must check if some update is available or not. This is done because if the update is not available then we will ask the user to update the app then it will be a bad impression on the user. So, we should first check, if an update is available or not. To check for an update you can use the AppUpdateManager. The code is shown below

// Creates instance of the manager.
val appUpdateManager = AppUpdateManagerFactory.create(context)

// Returns an intent object that you use to check for an update.
val appUpdateInfoTask = appUpdateManager.getAppUpdateInfo()

// Checks that the platform will allow the specified type of update.
appUpdateInfoTask.addOnSuccessListener({ appUpdateInfo->
    if ((appUpdateInfo.updateAvailability() === UpdateAvailability.UPDATE_AVAILABLE
    // For a flexible update, use AppUpdateType.FLEXIBLE
    && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE))){
    // Request the update.
    }
})

If an update is available and is allowed then from the returned AppUpdateInfo, you can start the app update.

Start an update

Once you check that if the available or not and if the update is available then the update is allowed or not, if the update is available and the update is allowed then you can start updating the app by using AppUpdateManager.startUpdateFlowForResult(). Use the below code:

appUpdateManager.startUpdateFlowForResult(
    // Pass the intent that is returned by 'getAppUpdateInfo()'.
    appUpdateInfo,
    // Or 'AppUpdateType.FLEXIBLE' for flexible updates.
    AppUpdateType.IMMEDIATE,
    // The current activity making the update request.
    this,
    // Include a request code to later monitor this update request.
    MY_REQUEST_CODE)

You should not use this for each and every update you have in your app. Always have some preference. Also, the request for the update should be done only once, unless the update fails. If the update has failed(due to any reason) then you can request for the update again.

While doing update, you can handle the update related failure or cancellation by using the onActivityResult() as follows:

fun onActivityResult(requestCode:Int, resultCode:Int, data:Intent) {
    if (myRequestCode === MY_REQUEST_CODE){
        if (myRequestCode !== RESULT_OK){
            log("Update flow failed! Result code: " + resultCode)
            // If the update is cancelled or fails,
            // you can request to start the update again.
        }
    }
}

Here we are getting the MY_REQUEST_CODE from the appUpdateManager. Following are the request codes that you get in the onActivityResult:

  • RESULT_OK: You will get this if the user has accepted the request for update.
  • RESULT_CANCELED: The user has canceled the update or denied for the an update.
  • RESULT_IN_APP_UPDATE_FAILED: Some error has occurred during the update. It may be some error from the user side or some other error.

Handling a flexible Update

A flexible in-app update can be done by using the AppUpdateType.FLEXIBLE while starting an update.

In the immediate update, the Google play will restart the app after the update is successful. But in a flexible update, the user can use the app and restart the app after using the app. Google play will not automatically restart the app for you. So, in order to restart the app, it is advised to give some alert or some kind of notification to the user to restart the app.

For example, you can create a snackbar for the same purpose, use the below code:

fun onStateUpdate(state:InstallState) {
    if (state.installStatus() === InstallStatus.DOWNLOADED){
        // After the update is downloaded, show a notification
        // and request user confirmation to restart the app.
        popupSnackbarForCompleteUpdate()
    }
}

/* Displays the snackbar notification and call to action. */
private fun popupSnackbarForCompleteUpdate() {
    val snackbar = Snackbar.make(
        findViewById(R.id.activity_main_layout),
        "An update has just been downloaded.",
        Snackbar.LENGTH_INDEFINITE)
    snackbar.setAction("RESTART", { view-> appUpdateManager.completeUpdate() })
    snackbar.setActionTextColor(
        getResources().getColor(R.color.snackbar_action_text_color))
    snackbar.show()
}

This will restart the app after proper installation of the update.

Handling an immediate update,

An immediate in-app update can be done by using the AppUpdateType.IMMEDIATE while starting the update.

During an immediate update, you should handle each and every aspect of the update. During an update, if the user closes the app or your app gets terminated then your app should download and update the app in the background and if your app comes to foreground then you should handle this situation by using the UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS state

// Checks that the update is not stalled during 'onResume()'.
// However, you should execute this check at all entry points into the app.
protected fun onResume() {
    super.onResume()

    appUpdateManager
        .getAppUpdateInfo()
        .addOnSuccessListener({
            appUpdateInfo->
            ...
            if ((appUpdateInfo.updateAvailability() === UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS)){
                // If an in-app update is already running, resume the update.
                manager.startUpdateFlowForResult(
                    appUpdateInfo,
                    IMMEDIATE,
                    this,
                    MY_REQUEST_CODE)
            }
        })
}

By adding the above lines, the immediate update will be handled in Android applications.

Conclusion

In this blog, we learned how to use the in-app update feature in our app. We saw the two types of in-app update i.e. the flexible in-app update and the immediate in-app update. Make sure to use the flexible in-app update when your app has very few updates and your update does not affect the core functionality of your app. So, apply this concept in your app and publish some cool updates of your app.

Note: The in-app update feature is available for API level 21 or above and is only available to those apps which are on the play store.

Keep Learning :)

Team MindOrks