How to work with Android's in-app update API?

68,539

Solution 1

Step 1: Add dependency (build.gradle (app)):

dependencies {

    implementation 'com.google.android.play:core:1.7.3'
    ...
}

Step 2: Check for update availability and start if it's available

private AppUpdateManager mAppUpdateManager;
private static final int RC_APP_UPDATE = 11;

In onStart() method:

mAppUpdateManager = AppUpdateManagerFactory.create(this);

mAppUpdateManager.registerListener(installStateUpdatedListener);

mAppUpdateManager.getAppUpdateInfo().addOnSuccessListener(appUpdateInfo -> {

        if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
                && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE /*AppUpdateType.IMMEDIATE*/)){

            try {    
                    mAppUpdateManager.startUpdateFlowForResult(
                            appUpdateInfo, AppUpdateType.FLEXIBLE /*AppUpdateType.IMMEDIATE*/, MainActivity.this, RC_APP_UPDATE);

            } catch (IntentSender.SendIntentException e) {
                e.printStackTrace();
            }

        } else if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED){
            //CHECK THIS if AppUpdateType.FLEXIBLE, otherwise you can skip
            popupSnackbarForCompleteUpdate();
        } else {
            Log.e(TAG, "checkForAppUpdateAvailability: something else");
        }
    });

Step 3: Listen to update state

InstallStateUpdatedListener installStateUpdatedListener = new 
  InstallStateUpdatedListener() {
    @Override
    public void onStateUpdate(InstallState state) {
        if (state.installStatus() == InstallStatus.DOWNLOADED){
            //CHECK THIS if AppUpdateType.FLEXIBLE, otherwise you can skip
            popupSnackbarForCompleteUpdate();
        } else if (state.installStatus() == InstallStatus.INSTALLED){
            if (mAppUpdateManager != null){
          mAppUpdateManager.unregisterListener(installStateUpdatedListener);
            }

        } else {
            Log.i(TAG, "InstallStateUpdatedListener: state: " + state.installStatus());
        }
    }
};

Step 4: Get a callback for update status

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == RC_APP_UPDATE) {
        if (resultCode != RESULT_OK) {
            Log.e(TAG, "onActivityResult: app download failed");
        }
    }
}

Step 5: Flexible update

private void popupSnackbarForCompleteUpdate() {

    Snackbar snackbar =
            Snackbar.make(
                    findViewById(R.id.coordinatorLayout_main),
                    "New app is ready!",
                    Snackbar.LENGTH_INDEFINITE);

    snackbar.setAction("Install", view -> {
        if (mAppUpdateManager != null){
            mAppUpdateManager.completeUpdate();
        }
    });

    
snackbar.setActionTextColor(getResources().getColor(R.color.install_color));
    snackbar.show();
}

Step 6: Don't forget to unregister listener (in onStop method)

if (mAppUpdateManager != null) {
     mAppUpdateManager.unregisterListener(installStateUpdatedListener);
}

Note: Add this listener in any one activity in your app preferably in MainActivity (Home page)

For testing, you can use FakeAppUpdateManager

https://developer.android.com/reference/com/google/android/play/core/appupdate/testing/FakeAppUpdateManager.html

Constraint: In-app update works only with devices running Android 5.0 (API level 21) or higher

Official Documentation: https://developer.android.com/guide/playcore/in-app-updates

Solution 2

Android officially announced the in-app updates to everyone today.

https://developer.android.com/guide/playcore/in-app-updates

Update: Handling both IMMEDIATE and FLEXIBLE updates in a single activity; Kotlin way.

import android.app.Activity
import android.content.Intent
import android.content.IntentSender
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.google.android.material.snackbar.Snackbar
import com.google.android.play.core.appupdate.AppUpdateManager
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
import com.google.android.play.core.install.InstallState
import com.google.android.play.core.install.InstallStateUpdatedListener
import com.google.android.play.core.install.model.AppUpdateType
import com.google.android.play.core.install.model.InstallStatus
import com.google.android.play.core.install.model.UpdateAvailability
import timber.log.Timber

class BaseUpdateCheckActivity : AppCompatActivity() {

    private val appUpdateManager: AppUpdateManager by lazy { AppUpdateManagerFactory.create(this) }
    private val appUpdatedListener: InstallStateUpdatedListener by lazy {
        object : InstallStateUpdatedListener {
            override fun onStateUpdate(installState: InstallState) {
                when {
                    installState.installStatus() == InstallStatus.DOWNLOADED -> popupSnackbarForCompleteUpdate()
                    installState.installStatus() == InstallStatus.INSTALLED -> appUpdateManager.unregisterListener(this)
                    else -> Timber.d("InstallStateUpdatedListener: state: %s", installState.installStatus())
                }
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_ad_view)
        checkForAppUpdate()
    }

    private fun checkForAppUpdate() {
        // Returns an intent object that you use to check for an update.
        val appUpdateInfoTask = appUpdateManager.appUpdateInfo

        // Checks that the platform will allow the specified type of update.
        appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
            if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) {
                // Request the update.
                try {
                    val installType = when {
                        appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE) -> AppUpdateType.FLEXIBLE
                        appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) -> AppUpdateType.IMMEDIATE
                        else -> null
                    }
                    if (installType == AppUpdateType.FLEXIBLE) appUpdateManager.registerListener(appUpdatedListener)

                    appUpdateManager.startUpdateFlowForResult(
                            appUpdateInfo,
                            installType!!,
                            this,
                            APP_UPDATE_REQUEST_CODE)
                } catch (e: IntentSender.SendIntentException) {
                    e.printStackTrace()
                }
            }
        }
    }


    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == APP_UPDATE_REQUEST_CODE) {
            if (resultCode != Activity.RESULT_OK) {
                Toast.makeText(this,
                        "App Update failed, please try again on the next app launch.",
                        Toast.LENGTH_SHORT)
                        .show()
            }
        }
    }

    private fun popupSnackbarForCompleteUpdate() {
        val snackbar = Snackbar.make(
                findViewById(R.id.drawer_layout),
                "An update has just been downloaded.",
                Snackbar.LENGTH_INDEFINITE)
        snackbar.setAction("RESTART") { appUpdateManager.completeUpdate() }
        snackbar.setActionTextColor(ContextCompat.getColor(this, R.color.accent))
        snackbar.show()
    }


    override fun onResume() {
        super.onResume()
        appUpdateManager
                .appUpdateInfo
                .addOnSuccessListener { appUpdateInfo ->

                    // If the update is downloaded but not installed,
                    // notify the user to complete the update.
                    if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) {
                        popupSnackbarForCompleteUpdate()
                    }

                    //Check if Immediate update is required
                    try {
                        if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
                            // If an in-app update is already running, resume the update.
                            appUpdateManager.startUpdateFlowForResult(
                                    appUpdateInfo,
                                    AppUpdateType.IMMEDIATE,
                                    this,
                                    APP_UPDATE_REQUEST_CODE)
                        }
                    } catch (e: IntentSender.SendIntentException) {
                        e.printStackTrace()
                    }
                }
    }

    companion object {
        private const val APP_UPDATE_REQUEST_CODE = 1991
    }
}

Source Gist: https://gist.github.com/saikiran91/6788ad4d00edca30dad3f51aa47a4c5c

Solution 3

Trying to implement this, the official Google Documentation quoted in the accepted answer is syntactically incorrect. It took some research, but I finally found the correct syntax:

Instead of:

// Creates an instance of the manager.
AppUpdateManager appUpdateManager = AppUpdateManagerFactory.create(context);

// Returns an intent object that you use to check for an update.
Task<AppUpdateInfo> appUpdateInfo = appUpdateManager.getAppUpdateInfo();

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

    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);
}

Do this:

    private AppUpdateManager appUpdateManager;
    ...
    // onCreate(){ 
    // Creates instance of the manager.
    appUpdateManager = AppUpdateManagerFactory.create(mainContext);

    // Don't need to do this here anymore
    // Returns an intent object that you use to check for an update.
    //Task<AppUpdateInfo> appUpdateInfo = appUpdateManager.getAppUpdateInfo();

    appUpdateManager
            .getAppUpdateInfo()
            .addOnSuccessListener(
                    appUpdateInfo -> {

                        // Checks that the platform will allow the specified type of update.
                        if ((appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE)
                                && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE))
                        {
                            // Request the update.
                            try {
                                appUpdateManager.startUpdateFlowForResult(
                                        appUpdateInfo,
                                        AppUpdateType.IMMEDIATE,
                                        this,
                                        REQUEST_APP_UPDATE);
                            } catch (IntentSender.SendIntentException e) {
                                e.printStackTrace();
                            }
                        }
                    });

Then, code a similar bit of code in the onResume() override in case an install got hung up along the way:

//Checks that the update is not stalled during 'onResume()'.
//However, you should execute this check at all entry points into the app.
@Override
protected void 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.
                            try {
                                appUpdateManager.startUpdateFlowForResult(
                                        appUpdateInfo,
                                        AppUpdateType.IMMEDIATE,
                                        this,
                                        REQUEST_APP_UPDATE);
                            } catch (IntentSender.SendIntentException e) {
                                e.printStackTrace();
                            }
                        }
                    });
}

Solution 4

Please try this once. Official Document for reference

Step 1: In the build.gradle file add the below library (please check and update latest play code plugin version)

implementation 'com.google.android.play:core:1.6.4'

Step 2: Declare the following variables in class (Ex MainActivity.java)

    private AppUpdateManager mAppUpdateManager;
    private int RC_APP_UPDATE = 999;
    private int inAppUpdateType;
    private com.google.android.play.core.tasks.Task<AppUpdateInfo> appUpdateInfoTask;
    private InstallStateUpdatedListener installStateUpdatedListener;

Step 3: In onCreate() method add the below code (initializing variables)

        // Creates instance of the manager.
        mAppUpdateManager = AppUpdateManagerFactory.create(this);
        // Returns an intent object that you use to check for an update.
        appUpdateInfoTask = mAppUpdateManager.getAppUpdateInfo();
        //lambda operation used for below listener
        //For flexible update
        installStateUpdatedListener = installState -> {
            if (installState.installStatus() == InstallStatus.DOWNLOADED) {
                popupSnackbarForCompleteUpdate();
            }
        };
        mAppUpdateManager.registerListener(installStateUpdatedListener);

Step 4: In onDestroy() method of activity just unregister the listener

 @Override
    protected void onDestroy() {
        mAppUpdateManager.unregisterListener(installStateUpdatedListener);
        super.onDestroy();
    }

Step 5: In onResume() we need to listen to both Flexible and Immediate updates by the below code.

@Override
        protected void onResume() {
           try {   
  mAppUpdateManager.getAppUpdateInfo().addOnSuccessListener(appUpdateInfo -> {
        if (appUpdateInfo.updateAvailability() == 
           UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
           // If an in-app update is already running, resume the update.
                       try {
                            mAppUpdateManager.startUpdateFlowForResult(
                                    appUpdateInfo,
                                    inAppUpdateType,
                                    this,
                                    RC_APP_UPDATE);
                        } catch (IntentSender.SendIntentException e) {
                            e.printStackTrace();
                        }
                    }
                });
    
       
  mAppUpdateManager.getAppUpdateInfo().addOnSuccessListener(appUpdateInfo -> {
     //For flexible update            
       if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) {
                        popupSnackbarForCompleteUpdate();
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            super.onResume();
    }

Step 6: In onActivityResult() we need to handle user click actions(only for flexible update)

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_APP_UPDATE) {
            //when user clicks update button
            if (resultCode == RESULT_OK) {
                Toast.makeText(MainActivity.this, "App download starts...", Toast.LENGTH_LONG).show();
            } else if (resultCode != RESULT_CANCELED) {
                //if you want to request the update again just call checkUpdate()
                Toast.makeText(MainActivity.this, "App download canceled.", Toast.LENGTH_LONG).show();
            } else if (resultCode == RESULT_IN_APP_UPDATE_FAILED) {
                Toast.makeText(MainActivity.this, "App download failed.", Toast.LENGTH_LONG).show();
            }
        }
}

Step 7: Create a method to check update available or not and start the update (Immediate update)

private void inAppUpdate() {

        try {
            // Checks that the platform will allow the specified type of update.
            appUpdateInfoTask.addOnSuccessListener(new OnSuccessListener<AppUpdateInfo>() {
                @Override
                public void onSuccess(AppUpdateInfo appUpdateInfo) {
                    if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
                            // For a flexible update, use AppUpdateType.FLEXIBLE
                            && appUpdateInfo.isUpdateTypeAllowed(inAppUpdateType)) {
                        // Request the update.

                        try {
                            mAppUpdateManager.startUpdateFlowForResult(
                                    // Pass the intent that is returned by 'getAppUpdateInfo()'.
                                    appUpdateInfo,
                                    // Or 'AppUpdateType.FLEXIBLE' for flexible updates.
                                    inAppUpdateType,
                                    // The current activity making the update request.
                                    MainActivity.this,
                                    // Include a request code to later monitor this update request.
                                    RC_APP_UPDATE);
                        } catch (IntentSender.SendIntentException ignored) {

                        }
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

Step 8: Finely create a snack dialog or any alert to show the user that flexible update is downloaded and ready to update(need used action to start update - only for flexible update)

private void popupSnackbarForCompleteUpdate() {
        try {
        Snackbar snackbar =
            Snackbar.make(
                    findViewById(R.id.id_of_root_loyout),
                    "An update has just been downloaded.\nRestart to update",
                    Snackbar.LENGTH_INDEFINITE);

    snackbar.setAction("INSTALL", view -> {
        if (mAppUpdateManager != null){
            mAppUpdateManager.completeUpdate();
        }
    });
snackbar.setActionTextColor(getResources().getColor(R.color.install_color));
    snackbar.show();

        } catch (Resources.NotFoundException e) {
            e.printStackTrace();
        }
    } 

Step 9: Now call the method with the in-app update type(Flexible or Immediate) wherever you want to start to check updates.

//For Immediate 
inAppUpdateType = AppUpdateType.IMMEDIATE; //1
inAppUpdate();

//For Flexible 
inAppUpdateType = AppUpdateType.FLEXIBLE; //0
inAppUpdate();

Points to Remember:

  1. The flexible update will download first then it will notify the user that download completed then the user has to start the update(options given above step 8).

  2. There is an option in google play console to test in-app sharing, just we can upload normal apk(no need signed apk)to test. https://support.google.com/googleplay/android-developer/answer/9303479?hl=en

  3. Need to enable in-app sharing option in your test device play store app. How to Enable Internal App Sharing for Android?

  4. Still, any issue in the play store, just clear cache and clear data then restart the device once and try.

Solution 5

My guess is that it is controlled by the app itself, rather than Google Play. I've developed apps that make an API call on startup to read the 'latest' version number and whether that version is a 'mandatory' update or not, and compares it to the running app version. If a new version is available, the user is presented with a dialog like the one you displayed (though their's is much nicer) alerting the user that an update is available. If the update is 'mandatory', then the message tells them that they must update the app before continuing. If they click Update, then they are taken to the App Store page where they initiate the download of the update as usual and the app exits. If they click Close, the app just exits. If the update is not mandatory, they are asked if they would like to update now, or continue. If they click Update, then they are taken to the App Store page where they initiate the download of the update as usual and the app exits. If they click Continue, then they are just taken into the existing version of the app.

I'm not sure how they managed the background download then kicked off the app update before exiting the app. That would be very nice, but our method above was also very easy and gives a lot of capability to the developer.

Share:
68,539
pratiked
Author by

pratiked

Updated on October 07, 2021

Comments

  • pratiked
    pratiked over 2 years

    I recently came across a new kind of app update flow which has provided by Google Play API. I liked this seamless flow to update an Android application. I observed the below-mentioned steps in the Hotstar app.

    1. A card popped up from the bottom showing update is available
    2. When I clicked on "Update Hotstar" button, one dialog popped up (seems like it is provided by Google Play)

    enter image description here

    1. Downloading was started in the background while the app was running
    2. After completion of the download, one SnackBar popped up showing app ready to install
    3. App restarted after the installation

    enter image description here

    How can I achieve this? There must be a way to communicate with Google Play. I went through many blogs. But, didn't find any solution. This could be an awesome feature for a developer if the auto app update is disabled by the user.

    • Sai
      Sai about 5 years
      It is called in-app Updates API and tested by selected partners. I am waiting for this too. Unfortunately, Google loves to announce features and products that take forever to release.
    • Prags
      Prags almost 3 years
      You may refer this answer as well stackoverflow.com/questions/15213211/…
  • pratiked
    pratiked about 5 years
    Thanks for your time. We can develop this easily within the app. But you have to take the user to Play Store. However, if you can guess it, there are some callbacks from Google Play. That's why they are able to show SnackBar on completion on download.
  • Michael Dougan
    Michael Dougan about 5 years
    Cool! It appears Google Play is testing an in-app Update API with select partners now. Would like to check it out when it becomes available... android-developers.googleblog.com/2018/11/…
  • Michael Dougan
    Michael Dougan about 5 years
    Apparently, the Google Documentation contains errors. The appUpdateInfo is declared as a Task, and therefore you can't access the member methods .updateAvailability() and .isUpdateTypeAllowed(). Someone recommended referencing the appUpdateInfo inside of a Listener, but the only examples I was able to find appear to be in Kotlin...
  • pratiked
    pratiked about 5 years
    @MichaelDougan Yes, I noticed some errors in the documentation. I worked on those errors and implemented it in one of my apps. It is working fine.
  • kevintresuelo
    kevintresuelo about 5 years
    I'm running some tests but I can't seem to make it to work. I'm always getting the UpdateAvailability.UPDATE_NOT_AVAILABLE as a response. Is there anything that I've missed?
  • pratiked
    pratiked about 5 years
    @kevintresuelo I think your app should be published on Play store. For testing, decrease the version code of test app than published version code and try.
  • BlackBlind
    BlackBlind about 5 years
    @PratikED Bro I am unable to work with your code when I am just paste and run your code in my splash screen It always gives me error of SomeThing Else Can you help me to find out error on my app.
  • pratiked
    pratiked about 5 years
    @BlackBlind Log the appUpdateInfo.installStatus() inside else statement. You might find the issue.
  • BlackBlind
    BlackBlind about 5 years
    Bro I did but cannot find any thing new can you give me sample app for this.
  • vishal patel
    vishal patel about 5 years
    @PratikED you are checking IMMEDIATE instead of FLEXIBLE
  • vishal patel
    vishal patel about 5 years
    @kevintresuelo can you found any solution for your issue?
  • kevintresuelo
    kevintresuelo about 5 years
    @vishalpatel yes, check my answer at stackoverflow.com/a/56319077/3686003
  • Satyam Gondhale
    Satyam Gondhale over 4 years
    What if the Mobile Android Version is less than 5.0, whether we have to write separate implementation for this updates to handle ?
  • pratiked
    pratiked over 4 years
    @Satyam This can be achieved by adding the version code of your app in a table on your server. This version code you increment manually when there is a need for force update of the app. You fetch the version code every time the user launches the app and compare it with the installed app's version code. To update the app, you redirect the user to the Play Store.
  • Harminder Singh
    Harminder Singh over 4 years
    How to know or set the update type- flexible/immediate?
  • heychar
    heychar over 4 years
    Hi I'm also trying this but I can't seem to make it to work. I'm always getting the UpdateAvailability.UPDATE_NOT_AVAILABLE as a response. Is this already available to the public?
  • heychar
    heychar over 4 years
    @harminder-singh as per research, flexible/immediate is determine by user. you may use RemoteConfig to set whether you want it to be flexible or immediate.
  • Harminder Singh
    Harminder Singh over 4 years
    @heychar firebase is different approach where I need to update the version manually. I am asking about this inappupdate provided by android developers developer.android.com/guide/app-bundle/in-app-updates
  • Bawa
    Bawa over 4 years
    you can try fakeUpdateManager to test
  • Muhammad Saqib
    Muhammad Saqib over 4 years
    how to decide if the available update is IMMEDIATE or FLEXIBLE can we set these flags in google play developer console so the client device will know if it has to update on immediate bases.
  • Sai
    Sai over 4 years
    That what thought initially and created a gist, but it turned out we cannot set the flag in google play store; instead, I used firebase remote config to compleat the process. I will update the gist in some time. Thanks. @MuhammadSaqib
  • Muhammad Saqib
    Muhammad Saqib over 4 years
    I did a little research after commenting and I find out that they are actually planing to implement such feature. They will soon introduce update "Priority" feature in developer console and play core API would be able to read that priority. youtu.be/_o_q6hatcIs?t=577
  • Alec Gerona
    Alec Gerona over 4 years
    For those wanting to implement this flag that Google hasn't released yet, seems like the next best option is Firebase Remote Config.
  • Alec Gerona
    Alec Gerona over 4 years
    Why does a lot of people simply try/catch the startUpdateFlowResult and just print the stacktrace? Don't you need this to succeed or is this just a noisy function call?
  • Bumuthu Dilshan
    Bumuthu Dilshan about 4 years
    I am new to android studio. Please help me with where these code segments should be added.
  • pratiked
    pratiked about 4 years
    @BumuthuDilshan I've updated the answer! Hope this will help you.
  • Muhammad Saqib
    Muhammad Saqib almost 4 years
    any way to hide popup message when using flexible update? Can't we just start the flexible update without showing this update message? After all the meaning of flexible update is to don't disturb user.
  • pratiked
    pratiked almost 4 years
    @MuhammadSaqib The user can start the installation as per her convenience. That is why a button needs to show for commencing installation.
  • Muhammad Saqib
    Muhammad Saqib almost 4 years
    @PratikED I handle installation part next time when user start the app. Currently when there is an update available, I start the flow with flexible open. You click update button and update downloaded in the background. (no UI no progress bar). When the user come back to app then I perform installation. That's why I'm asking if there is any way to start the update without this prompt popup.
  • Cory Robinson
    Cory Robinson almost 4 years
    What is the value of REQUEST_APP_UPDATE ?
  • W I Z A R D
    W I Z A R D over 3 years
    @PratikED i have implemented the same code but not showing any popup. any help thank you
  • Chitrang
    Chitrang over 3 years
    @PratikED My only concern with Flexible flow is what if the user will move to another screen while apk is being downloaded? Will snackbar appears in a new activity? or can we show alertdailog somehow on top of all activities? or in-app api has any other way to notify user after apk is dowloaded?
  • StayCool
    StayCool over 3 years
    @CoryRobinson it's anything =)
  • Burak Senel
    Burak Senel over 2 years
    you get always false for 3. condition (resultCode == RESULT_IN_APP_UPDATE_FAILED) in onActivityResult(), because of wrong logic in 2.condition. Your 2. condition should be as following (resultCode == RESULT_CANCELED)