AppUpdateManager doesn't install app when completeUpdate() is called

jonathan3087 :

I am trying to implement Android In App Update API using AppUpdateManager. I first tried following the documentation, which if you are here, then you know that doesn't work.

So then I've read about a dozen tutorials and blog articles on how to get this to work. I'm about 90% there. For me after the user accepts the update, the update is downloaded, my listener detects that the download is complete, and I display my own message with a call back (most of the tutorials use a Toast at this point, but that shouldn't matter). If my user taps on "Restart" which is the label I gave the OK side of the message that I'm displaying, then I call appUpdateManager.completeUpdate().

At this point I get a screen from Google Play being displayed with some nice animation, and an Installing progress bar when that finishes, the Google screen disappears, and then my app is restarted.

Problem, is that it didn't get installed, I can tell from my app version that it is still the previous version, and since it is still the previous version, the appUpdateManager is recreated and when it checks UpdateAvailability.UPDATE_AVAILABLE, it finds (obviously) that there is an update available, and goes back through the whole processing, downloading it again and trying to restart the app again.

I have added some log messages and checked to see if I am getting RESULT_IN_APP_UPDATE_FAILED in the onActivityResult, but it is coming back fine.

Any help or suggestions anyone has, would be great.

I create a handle to appUpdateManager at the beginning of MainActivity, like this:

private AppUpdateManager appUpdateManager;

I also create a listener to monitor the install state as I am working towards a FLEXABLE AppUpdateType like:

    private InstallStateUpdatedListener UPDATE_LISTENER = installState -> {
    if (installState.installStatus() == DOWNLOADED) {
        Log.d(TAG, "~UPDATE_LISTENER - installStatus is DOWNLOADED");
        Utility.displayAlert(UPDATE_READY);
    }

    Log.d(TAG, "~Error code is: " + installState.installErrorCode());
    Log.d(TAG, "~Package name is: " + installState.packageName());
};

In my onCreate, I create the appUpdateManager and register the download listener as well as add the addOnSuccessListener like so:

Log.d(TAG, "~updateAppIfAvailable");
    // Creates instance of the manager.
    appUpdateManager = AppUpdateManagerFactory.create(this);
    Log.d(TAG, "~registerListener");
    appUpdateManager.registerListener(UPDATE_LISTENER);

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

                // Checks that the platform will allow the specified type of update.
                Log.d(TAG, "~updateAvailability is " + appUpdateInfo.updateAvailability());
                if ((appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE)
                        && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
                    // Request the update.
                    try {
                        appUpdateManager.startUpdateFlowForResult(
                                appUpdateInfo,
                                AppUpdateType.FLEXIBLE,
                                this,
                                MY_REQUEST_CODE);
                    } catch (IntentSender.SendIntentException e) {
                        e.printStackTrace();
                    }
                }
            });

My onActivityResult looks like this: @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); Log.d(TAG, "~onActivityResult"); if (requestCode == MY_REQUEST_CODE) { switch (resultCode) { case Activity.RESULT_OK: Log.d(TAG, "~User approved update"); break; case Activity.RESULT_CANCELED: Log.d(TAG, "~User rejected update"); break; case RESULT_IN_APP_UPDATE_FAILED: Log.d(TAG, "~Update failed"); break; } } }

onResume is:

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 {
                        Log.d(TAG, "~onResume appUpdateManager is calling startUpdateFlowForResult");
                        appUpdateManager.startUpdateFlowForResult(
                                appUpdateInfo,
                                AppUpdateType.FLEXIBLE,
                                this,
                                MY_REQUEST_CODE);
                    } catch (IntentSender.SendIntentException e) {
                        e.printStackTrace();
                    }
                }
            });

Finally when I display my alert (this could be a Toast if you wanted), I have both a Cancel and a Restart option with a message that says "Update download is complete."

If the user presses the "Restart" option, then it calls this updateAndRestart() method:

private void updateAndRestart() {
    Log.d(TAG, "~updateAndRestart");
    Log.d(TAG, "~Completing app update.");
    if (appUpdateManager != null) {
        appUpdateManager.completeUpdate();
        Log.d(TAG, "~unregisterListener");
        appUpdateManager.unregisterListener(UPDATE_LISTENER);
    }
}
jonathan3087 :

Ok, it's been a week, apparently I've stumped the entire SO community. :) Seriously though, I've been reading Android docs and tutorials for the past week and I have no other answers, so I'm going to just say the Google Update API just isn't ready for production.

I found an alternate solution. It is a combination of

  1. Using the AppUpdater library as mentioned in the answer to this question.
  2. If I get a callback that the user tapped Update, then I take them to my Play Store App listing, using this intent. Make sure you replace "com.example.android" with your own app id. This google doc page shows you how to do it.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://play.google.com/store/apps/details?id=com.example.android"));
intent.setPackage("com.android.vending");
startActivity(intent);

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=153909&siteId=1