Как работать с API обновления Android в приложении?

Недавно я столкнулся с новым типом потока обновлений приложений, предоставляемым Google Play API. Мне понравился этот плавный процесс обновления приложения для Android. Я наблюдал следующие шаги в приложении Hotstar.

  1. Внизу всплывает карточка, показывающая, что доступно обновление
  2. Когда я нажал кнопку «Обновить Hotstar», появилось одно диалоговое окно (похоже, оно предоставлено Google Play)

Как работать с API обновления Android в приложении?

  1. Загрузка началась в фоновом режиме во время работы приложения
  2. После завершения загрузки появилась одна закусочная, показывающая приложение, готовое к установке.
  3. Приложение перезапущено после установки

Как работать с API обновления Android в приложении?

Как я могу этого добиться? Должен быть способ связи с Google Play. Я просмотрел множество блогов. Но, не нашел никакого решения. Это может быть отличной функцией для разработчика, если автоматическое обновление приложения отключено пользователем.

Он называется In-App Updates API и тестируется выбранными партнерами. Я тоже этого жду. К сожалению, Google любит объявлять о функциях и продуктах, выпуск которых занимает целую вечность.

Sai 01.05.2019 20:09

Вы также можете сослаться на этот ответ stackoverflow.com/questions/15213211/…

Prags 22.07.2021 21:32
43
2
64 825
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Я предполагаю, что им управляет само приложение, а не Google Play. Я разработал приложения, которые при запуске вызывают вызов API, чтобы прочитать «последний» номер версии и указать, является ли эта версия «обязательным» обновлением или нет, и сравнить его с работающей версией приложения. Если доступна новая версия, пользователю предоставляется диалоговое окно, похожее на то, которое вы показали (хотя их диалоговое окно намного лучше), предупреждающее пользователя о наличии обновления. Если обновление является «обязательным», то в сообщении сообщается, что они должны обновить приложение, прежде чем продолжить. Если они нажимают «Обновить», они переходят на страницу App Store, где они начинают загрузку обновления, как обычно, и приложение закрывается. Если они нажмут «Закрыть», приложение просто закроется. Если обновление не является обязательным, их спрашивают, хотят ли они выполнить обновление сейчас или продолжить. Если они нажимают «Обновить», они переходят на страницу App Store, где они начинают загрузку обновления, как обычно, и приложение закрывается. Если они нажмут «Продолжить», они просто перейдут в существующую версию приложения.

Я не уверен, как они управляли фоновой загрузкой, а затем запускали обновление приложения перед выходом из приложения. Это было бы очень хорошо, но наш метод, описанный выше, также очень прост и дает разработчику много возможностей.

Спасибо за ваше время. Мы можем легко разработать это в приложении. Но вы должны привести пользователя в Play Store. Однако, если вы можете догадаться, есть некоторые обратные вызовы из Google Play. Вот почему они могут показывать SnackBar по завершении загрузки.

pratiked 01.05.2019 19:29

Прохладный! Похоже, Google Play сейчас тестирует API обновлений в приложении с некоторыми партнерами. Хотел бы проверить, когда он станет доступен... android-developers.googleblog.com/2018/11/…

Michael Dougan 01.05.2019 20:02

Google тестирует раннюю версию API обновлений в приложениях, как описано в статье этот пост в блоге.

Сейчас он доступен только для некоторых партнеров по раннему тестированию, но в конечном итоге он должен быть доступен для всех разработчиков. Следите за блогом разработчиков Android и за объявлениями в консоли Play.

Сегодня Android официально объявил об обновлениях в приложении для всех.

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

Обновлять: Обработка как НЕМЕДЛЕННЫХ, так и ГИБКИХ обновлений в одном действии; Котлинский способ.

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

Исходный текст: https://gist.github.com/saikiran91/6788ad4d00edca30dad3f51aa47a4c5c

как решить, является ли доступное обновление IMMEDIATE или FLEXIBLE, можем ли мы установить эти флаги в консоли разработчика Google Play, чтобы клиентское устройство знало, должно ли оно обновляться немедленно.

Muhammad Saqib 31.01.2020 13:31

То, о чем думали изначально и создали суть, но оказалось, что мы не можем установить флаг в магазине Google Play; вместо этого я использовал удаленную конфигурацию firebase для завершения процесса. Я обновлю суть через некоторое время. Спасибо. @МухаммадСакиб

Sai 01.02.2020 02:52

После комментариев я провел небольшое исследование и обнаружил, что они действительно планируют реализовать такую ​​​​функцию. Вскоре они представят функцию обновления «Приоритет» в консоли разработчика, и API ядра игры сможет считывать этот приоритет. youtu.be/_o_q6hatcIs?t=577

Muhammad Saqib 01.02.2020 14:20

Для тех, кто хочет реализовать этот флаг, который Google еще не выпустил, кажется, что следующим лучшим вариантом является Firebase Remote Config.

Alec Gerona 03.03.2020 20:10
Ответ принят как подходящий

Шаг 1: Добавьте зависимость (build.gradle (приложение)):

dependencies {

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

Шаг 2. Проверьте наличие обновлений и запустите, если они доступны

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

В методе onStart():

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

Шаг 3. Прослушайте состояние обновления

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

Шаг 4. Получите обратный вызов, чтобы узнать статус обновления

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

Шаг 5. Гибкое обновление

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

Шаг 6: Не забудьте отменить регистрацию слушателя (в методе onStop)

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

Примечание. Добавьте этот прослушиватель в любое действие в вашем приложении, предпочтительно в MainActivity (домашняя страница).

Для тестирования можно использоватьFakeAppUpdateManager

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

Ограничение: Обновление из приложения работает только с устройствами под управлением Android 5.0 (уровень API 21) или выше.

Официальная документация:https://developer.android.com/guide/playcore/in-app-updates

Судя по всему, документация Google содержит ошибки. appUpdateInfo объявлен как Task, поэтому вы не можете получить доступ к методам-членам .updateAvailability() и .isUpdateTypeAllowed(). Кто-то рекомендовал ссылаться на appUpdateInfo внутри Listener, но единственные примеры, которые я смог найти, были в Kotlin...

Michael Dougan 14.05.2019 19:09

@MichaelDougan Да, я заметил некоторые ошибки в документации. Я работал над этими ошибками и реализовал их в одном из своих приложений. Он работает нормально.

pratiked 17.05.2019 07:14

Я запускаю некоторые тесты, но я не могу заставить их работать. Я всегда получаю в ответ UpdateAvailability.UPDATE_NOT_AVAILABLE. Есть ли что-то, что я пропустил?

kevintresuelo 26.05.2019 12:25

@kevintresuelo Я думаю, ваше приложение должно быть опубликовано в магазине Play. Для тестирования уменьшите код версии тестового приложения по сравнению с опубликованным кодом версии и попробуйте.

pratiked 29.05.2019 07:44

@PratikED Братан, я не могу работать с вашим кодом, когда я просто вставляю и запускаю ваш код на своем заставке. Он всегда выдает мне ошибку Что-то другое. Можете ли вы помочь мне найти ошибку в моем приложении.

BlackBlind 06.06.2019 15:46

@BlackBlind Зарегистрируйте appUpdateInfo.installStatus() внутри оператора else. Вы можете найти проблему.

pratiked 07.06.2019 07:37

Бро, я сделал, но не могу найти ничего нового, можешь ли ты дать мне образец приложения для этого.

BlackBlind 07.06.2019 11:39

@PratikED вы проверяете НЕМЕДЛЕННО, а не ГИБКО

vishal patel 14.06.2019 08:02

@kevintresuelo, можешь ли ты найти решение своей проблемы?

vishal patel 14.06.2019 08:04

@vishalpatel да, проверьте мой ответ на stackoverflow.com/a/56319077/3686003

kevintresuelo 14.06.2019 14:12

Что делать, если мобильная версия Android меньше 5.0, нужно ли нам писать отдельную реализацию для обработки этих обновлений?

Satyam Gondhale 23.10.2019 10:19

@Satyam Этого можно добиться, добавив код версии вашего приложения в таблицу на вашем сервере. Этот код версии вы увеличиваете вручную, когда возникает необходимость в принудительном обновлении приложения. Вы получаете код версии каждый раз, когда пользователь запускает приложение, и сравниваете его с кодом версии установленного приложения. Чтобы обновить приложение, вы перенаправляете пользователя в Play Store.

pratiked 31.10.2019 07:57

Как узнать или установить тип обновления - гибкое/немедленное?

Harminder Singh 20.11.2019 07:18

Привет, я тоже пытаюсь это сделать, но я не могу заставить его работать. Я всегда получаю в ответ UpdateAvailability.UPDATE_NOT_AVAILABLE. Это уже доступно для общественности?

heychar 21.11.2019 07:59

@harminder-singh согласно исследованиям, гибкость/немедленность определяется пользователем. вы можете использовать RemoteConfig, чтобы указать, хотите ли вы, чтобы он был гибким или немедленным.

heychar 21.11.2019 08:00

@heychar firebase — это другой подход, когда мне нужно обновить версию вручную. Я спрашиваю об этом inappupdate, предоставленном разработчиками Android developer.android.com/guide/app-bundle/in-app-updates

Harminder Singh 21.11.2019 12:44

вы можете попробовать fakeUpdateManager для проверки

Bawa 28.11.2019 11:14

Почему многие люди просто пытаются/ловят startUpdateFlowResult и просто печатают трассировку стека? Вам это не нужно для успеха или это просто шумный вызов функции?

Alec Gerona 26.03.2020 04:32

Я новичок в студии Android. Пожалуйста, помогите мне с тем, где эти сегменты кода должны быть добавлены.

Bumuthu Dilshan 16.05.2020 20:34

@BumuthuDilshan Я обновил ответ! Надеюсь, что это поможет вам.

pratiked 18.05.2020 10:19

любой способ скрыть всплывающее сообщение при использовании гибкого обновления? Разве мы не можем просто запустить гибкое обновление, не показывая это сообщение об обновлении? Ведь смысл гибкого обновления в том, чтобы не беспокоить пользователя.

Muhammad Saqib 30.06.2020 22:13

@MuhammadSaqib Пользователь может начать установку по своему усмотрению. Вот почему кнопка должна отображаться для начала установки.

pratiked 05.07.2020 16:52

@PratikED Я обрабатываю installation часть в следующий раз, когда пользователь запускает приложение. В настоящее время, когда доступно обновление, я запускаю поток с гибким открытием. Вы нажимаете кнопку обновления, и обновление загружается в фоновом режиме. (no UI no progress bar). Когда пользователь возвращается в приложение, я выполняю установку. Вот почему я спрашиваю, есть ли способ запустить обновление без этого всплывающего окна.

Muhammad Saqib 06.07.2020 16:14

@PratikED Я реализовал тот же код, но не показывал никаких всплывающих окон. любая помощь спасибо

W I Z A R D 19.10.2020 07:35

@PratikED Меня беспокоит только гибкий поток, а что, если пользователь перейдет на другой экран во время загрузки apk? Появится ли закусочная в новом действии? или мы можем как-то показать alertdailog поверх всех действий? или в API-интерфейсе приложения есть другой способ уведомить пользователя после загрузки apk?

Chitrang 23.10.2020 23:34

При попытке реализовать это официальная документация Google, цитируемая в принятом ответе, синтаксически неверна. Потребовалось некоторое исследование, но я наконец нашел правильный синтаксис:

Вместо:

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

Сделай это:

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

Затем добавьте аналогичный фрагмент кода в переопределение onResume() на случай, если установка зависнет по пути:

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

В чем ценность REQUEST_APP_UPDATE ?

Cory Robinson 12.08.2020 00:04

@CoryRobinson это что угодно =)

StayCool 23.11.2020 15:10

Пожалуйста, попробуйте это один раз. Официальный документ для справки

Шаг 1: В файле build.gradle добавьте указанную ниже библиотеку (пожалуйста, проверьте и обновите последнюю версию плагина игрового кода)

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

Шаг 2: Объявите следующие переменные в классе (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;

Шаг 3: В методе onCreate() добавьте приведенный ниже код (инициализация переменных)

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

Шаг 4: В методе onDestroy() просто отмените регистрацию слушателя

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

Шаг 5: В onResume() нам нужно прослушивать как гибкие, так и немедленные обновления с помощью приведенного ниже кода.

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

Шаг 6: В onActivityResult() нам нужно обрабатывать действия кликов пользователя (только для гибкого обновления)

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

Шаг 7: Создайте метод проверки доступности обновления и запустите обновление (немедленное обновление)

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

    }

Шаг 8: Точно создайте диалоговое окно с закусками или любое оповещение, чтобы показать пользователю, что гибкое обновление загружено и готово к обновлению (для запуска обновления требуется действие — только для гибкого обновления)

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

Шаг 9. Теперь вызовите метод с типом обновления в приложении (гибкое или немедленное) в любом месте, где вы хотите начать проверку обновлений.

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

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

Очки, чтобы помнить:

  1. Гибкое обновление будет загружено первым, затем оно уведомит пользователя о том, что загрузка завершена, после чего пользователь должен начать обновление (параметры, указанные выше на шаге 8).

  2. В консоли Google Play есть возможность протестировать совместное использование в приложении, просто мы можем загрузить обычный apk (подписанный apk не требуется) для тестирования. https://support.google.com/googleplay/android-developer/answer/9303479?hl=ru

  3. Необходимо включить опцию обмена внутри приложения в приложении Play Store на тестовом устройстве. Как включить внутренний общий доступ к приложениям для Android?

  4. Тем не менее, любая проблема в магазине игр, просто очистите кеш и очистите данные, затем перезагрузите устройство один раз и попробуйте.

вы всегда получаете false для 3. условия (resultCode == RESULT_IN_APP_UPDATE_FAILED) в onActivityResult() из-за неправильной логики в 2.условии. Ваше 2. условие должно быть следующим (resultCode == RESULT_CANCELED)

Burak Senel 13.01.2022 11:09

Попробуйте эти библиотеки, которые можно реализовать всего за несколько строк кода.

https://github.com/SanojPunchihewa/InAppUpdater

https://github.com/dnKaratzas/android-inapp-обновление

Другие вопросы по теме