如果是当前版本,则提示 Android 应用用户更新应用 <>市场版

2022-01-20 00:00:00 android google-play java

假设我的 Android 应用程序 0.1 版当前安装在用户的手机上.每次他们启动我的应用程序时,我都想检查 Android 市场中是否有不同的版本,假设这个版本是 0.2.如果这两个版本不匹配,我想显示一个对话框,提示用户升级应用程序.

我完全理解 Android Market 本身有一个通知程序给用户,但就我的分析数据而言,它在提醒用户升级到应用程序的新版本方面不是很有效.

任何见解都会非常有帮助.感谢 StackOverflowers,你们摇滚!

解决方案

截至 2019 年,更新应用的最佳方式是使用 Play Core 库 (1.5.0+) 提供的应用内更新.它适用于 Lollipop 和更新版本,但公平地说,Kit-Kat 到今天还不到 7%,很快就会永远消失.您可以在 Kit-Kat 上安全地运行此代码,无需版本检查,它不会崩溃.

官方文档:

而 立即 将要求您更新应用才能继续使用全屏消息(此页面可以关闭):

重要提示:目前,您无法在 Developer Play Console 的应用发布"部分选择推出哪种类型的更新.但显然,他们很快就会给我们这个选择.根据我的测试,目前,我们在 onSuccessListener 中提供了这两种类型.

让我们在代码中实现两种类型.

在模块build.gradle中添加如下依赖:

依赖项{implementation 'com.google.android.play:core:1.6.1'//for new version updater}

MainActivity.class中:

private static final int REQ_CODE_VERSION_UPDATE = 530;私有 AppUpdateManager 应用更新管理器;私人 InstallStateUpdatedListener installStateUpdatedListener;@覆盖protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);checkForAppUpdate();}@覆盖受保护的无效 onResume() {超级.onResume();checkNewAppVersionState();}@覆盖public void onActivityResult(int requestCode, final int resultCode, Intent intent) {super.onActivityResult(requestCode, resultCode, intent);开关(请求代码){案例 REQ_CODE_VERSION_UPDATE:if (resultCode != RESULT_OK) {//RESULT_OK/RESULT_CANCELED/RESULT_IN_APP_UPDATE_FAILEDL.d("更新流程失败!结果代码:" + resultCode);//如果更新被取消或失败,//您可以请求重新开始更新.unregisterInstallStateUpdListener();}休息;}}@覆盖受保护的无效 onDestroy() {unregisterInstallStateUpdListener();super.onDestroy();}私人无效 checkForAppUpdate() {//创建管理器的实例.appUpdateManager = AppUpdateManagerFactory.create(AppCustom.getAppContext());//返回一个用于检查更新的意图对象.任务<AppUpdateInfo>appUpdateInfoTask = appUpdateManager.getAppUpdateInfo();//创建一个监听器来跟踪请求状态更新.installStateUpdatedListener = 新的 InstallStateUpdatedListener() {@覆盖公共无效 onStateUpdate(InstallState installState) {//显示模块进度、日志状态或安装更新.if (installState.installStatus() == InstallStatus.DOWNLOADED)//更新下载后,显示通知//并请求用户确认以重新启动应用程序.popupSnackbarForCompleteUpdateAndUnregister();}};//检查平台是否允许指定类型的更新.appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) {//请求更新.if (appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {//在开始更新之前,注册一个更新的监听器.appUpdateManager.registerListener(installStateUpdatedListener);//开始更新.startAppUpdateFlexible(appUpdateInfo);} else if (appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) ) {//开始更新.startAppUpdateImmediate(appUpdateInfo);}}});}私人无效 startAppUpdateImmediate(AppUpdateInfo appUpdateInfo) {尝试 {appUpdateManager.startUpdateFlowForResult(应用更新信息,AppUpdateType.IMMEDIATE,//发出更新请求的当前活动.这,//包含一个请求代码,以便稍后监控此更新请求.MainActivity.REQ_CODE_VERSION_UPDATE);} 捕捉(IntentSender.SendIntentException e){e.printStackTrace();}}私人无效 startAppUpdateFlexible(AppUpdateInfo appUpdateInfo) {尝试 {appUpdateManager.startUpdateFlowForResult(应用更新信息,AppUpdateType.FLEXIBLE,//发出更新请求的当前活动.这,//包含一个请求代码,以便稍后监控此更新请求.MainActivity.REQ_CODE_VERSION_UPDATE);} 捕捉(IntentSender.SendIntentException e){e.printStackTrace();unregisterInstallStateUpdListener();}}/*** 显示小吃店通知和号召性用语.* 仅适用于灵活的应用更新*/私人无效popupSnackbarForCompleteUpdateAndUnregister() {小吃店小吃店=Snackbar.make(drawerLayout, getString(R.string.update_downloaded), Snackbar.LENGTH_INDEFINITE);小吃吧.setAction(R.string.restart, new View.OnClickListener() {@覆盖public void onClick(查看视图){appUpdateManager.completeUpdate();}});小吃吧.setActionTextColor(getResources().getColor(R.color.action_color));小吃吧.show();unregisterInstallStateUpdListener();}/*** 检查更新在onResume()"期间是否停止.* 但是,您应该在所有应用程序入口点执行此检查.*/私人无效 checkNewAppVersionState() {应用更新管理器.getAppUpdateInfo().addOnSuccessListener(应用更新信息->{//灵活的://如果更新已下载但未安装,//通知用户完成更新.if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) {popupSnackbarForCompleteUpdateAndUnregister();}//即时:if (appUpdateInfo.updateAvailability()== UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {//如果应用内更新已经在运行,则继续更新.startAppUpdateImmediate(appUpdateInfo);}});}/*** 仅在灵活更新时需要*/私人无效 unregisterInstallStateUpdListener() {if (appUpdateManager != null && installStateUpdatedListener != null)appUpdateManager.unregisterListener(installStateUpdatedListener);}

我们完成了!

测试.请阅读 docs 以便您知道如何正确测试它与 Google Play 上的测试曲目.

长话短说:

  1. 使用发布证书对您的应用进行签名,并将其上传到开发者 Play 控制台中 App Releases 下的发布轨道之一(alpha/beta/其他自定义封闭轨道).

  2. 在管理测试人员"部分的发布跟踪页面中,创建并添加测试人员列表,并确保您选中了复选框!- 此步骤是可选的,因为您的开发者帐户电子邮件也是测试者帐户,您可以使用它进行测试.

  3. 在测试人员列表下,您会找到选择加入 URL" - 复制此 URL 并将其提供给您的测试人员或自行打开.转到该页面并接受测试建议.将有一个指向该应用程序的链接.(您将无法在 Play 商店中搜索该应用,因此请为其添加书签)

  4. 通过该链接在您的设备上安装应用程序.

  5. build.gradle 中增加 defaultConfig { versionCode k+1 } 的版本并构建另一个签名的 apk Build > Generate Signed Bundle/APK...并将其上传到您的发布轨道.

  6. 等待... 1 小时?2小时?或更多,才能在赛道上发布.

  7. 清除您设备上 Play 商店应用的缓存.问题是 Play 应用会缓存有关已安装应用及其可用更新的详细信息,因此您需要清除缓存.为此,采取两个步骤:

7.1.转到设置 > 应用程序 > Google PLay 商店 > 存储 > 清除缓存.

7.2.打开 Play 商店应用 > 打开主菜单 > 我的应用和游戏 > 在那里你应该看到你的应用有一个新的更新.

如果您没有看到它,请确保您的新更新已经发布在轨道上(转到您的书签页面并使用它打开您在 Play 商店中的应用列表,以查看那里显示的版本).此外,当您的更新上线时,您会在 Developer Play Console 的右上角看到一条通知(铃铛图标将带有一个红点).

希望对你有帮助.

Lets say my Android App version 0.1 is installed currently on the User's phone. Everytime they launch my App I want to check if there is a different version available in the Android Market let's say this version is 0.2. If there is a mismatch between these two version I want to show a dialog box prompting the user to Upgrade the App.

I totally understand there exists a notification procedure from Android Market itself to the users but as far as my Analytics data is concerned it is not very effective in reminding users to upgrade to the new version of the App.

Any insight would be very helpful. Thanks StackOverflowers, you guys rock!

解决方案

As of 2019 the best way for updating your app is to use In-app updates provided by Play Core library (1.5.0+). It works for Lollipop and newer, but let's be fair, Kit-Kat is less than 7% as of today and soon will be gone forever. You can safely run this code on Kit-Kat without version checks, it won't crash.

Official documentation: https://developer.android.com/guide/app-bundle/in-app-updates

There are two types of In-app updates: Flexible and Immediate

Flexible will ask you nicely in a dialog window:

whereas Immediate will require you to update the app in order to continue using it with full-screen message (this page can be dismissed):

Important: for now, you can't choose which type of update to roll out in your App Release section on Developer Play Console. But apparently, they will give us that option soon. From what I've tested, currently, we're getting both types available in onSuccessListener.

So let's implement both types in our code.

In module build.gradle add the following dependency:

dependencies {
    implementation 'com.google.android.play:core:1.6.1'//for new version updater
}

In MainActivity.class:

private static final int REQ_CODE_VERSION_UPDATE = 530;
private AppUpdateManager appUpdateManager;
private InstallStateUpdatedListener installStateUpdatedListener;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

   checkForAppUpdate();
}

@Override
protected void onResume() {
    super.onResume();
    checkNewAppVersionState();
}

@Override
public void onActivityResult(int requestCode, final int resultCode, Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);

    switch (requestCode) {

        case REQ_CODE_VERSION_UPDATE:
            if (resultCode != RESULT_OK) { //RESULT_OK / RESULT_CANCELED / RESULT_IN_APP_UPDATE_FAILED
                L.d("Update flow failed! Result code: " + resultCode);
                // If the update is cancelled or fails,
                // you can request to start the update again.
                unregisterInstallStateUpdListener();
            }

            break;
    }
}

@Override
protected void onDestroy() {
    unregisterInstallStateUpdListener();
    super.onDestroy();
}


private void checkForAppUpdate() {
    // Creates instance of the manager.
    appUpdateManager = AppUpdateManagerFactory.create(AppCustom.getAppContext());

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

    // Create a listener to track request state updates.
    installStateUpdatedListener = new InstallStateUpdatedListener() {
        @Override
        public void onStateUpdate(InstallState installState) {
            // Show module progress, log state, or install the update.
            if (installState.installStatus() == InstallStatus.DOWNLOADED)
                // After the update is downloaded, show a notification
                // and request user confirmation to restart the app.
                popupSnackbarForCompleteUpdateAndUnregister();
        }
    };

    // Checks that the platform will allow the specified type of update.
    appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
        if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) {
            // Request the update.
            if (appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {

                // Before starting an update, register a listener for updates.
                appUpdateManager.registerListener(installStateUpdatedListener);
                // Start an update.
                startAppUpdateFlexible(appUpdateInfo);
            } else if (appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) ) {
                // Start an update.
                startAppUpdateImmediate(appUpdateInfo);
            }
        }
    });
}

private void startAppUpdateImmediate(AppUpdateInfo appUpdateInfo) {
    try {
        appUpdateManager.startUpdateFlowForResult(
                appUpdateInfo,
                AppUpdateType.IMMEDIATE,
                // The current activity making the update request.
                this,
                // Include a request code to later monitor this update request.
                MainActivity.REQ_CODE_VERSION_UPDATE);
    } catch (IntentSender.SendIntentException e) {
        e.printStackTrace();
    }
}

private void startAppUpdateFlexible(AppUpdateInfo appUpdateInfo) {
    try {
        appUpdateManager.startUpdateFlowForResult(
                appUpdateInfo,
                AppUpdateType.FLEXIBLE,
                // The current activity making the update request.
                this,
                // Include a request code to later monitor this update request.
                MainActivity.REQ_CODE_VERSION_UPDATE);
    } catch (IntentSender.SendIntentException e) {
        e.printStackTrace();
        unregisterInstallStateUpdListener();
    }
}

/**
 * Displays the snackbar notification and call to action.
 * Needed only for Flexible app update
 */
private void popupSnackbarForCompleteUpdateAndUnregister() {
    Snackbar snackbar =
            Snackbar.make(drawerLayout, getString(R.string.update_downloaded), Snackbar.LENGTH_INDEFINITE);
    snackbar.setAction(R.string.restart, new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            appUpdateManager.completeUpdate();
        }
    });
    snackbar.setActionTextColor(getResources().getColor(R.color.action_color));
    snackbar.show();

    unregisterInstallStateUpdListener();
}

/**
 * Checks that the update is not stalled during 'onResume()'.
 * However, you should execute this check at all app entry points.
 */
private void checkNewAppVersionState() {
    appUpdateManager
            .getAppUpdateInfo()
            .addOnSuccessListener(
                    appUpdateInfo -> {
                        //FLEXIBLE:
                        // If the update is downloaded but not installed,
                        // notify the user to complete the update.
                        if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) {
                            popupSnackbarForCompleteUpdateAndUnregister();
                        }

                        //IMMEDIATE:
                        if (appUpdateInfo.updateAvailability()
                                == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
                            // If an in-app update is already running, resume the update.
                            startAppUpdateImmediate(appUpdateInfo);
                        }
                    });

}

/**
 * Needed only for FLEXIBLE update
 */
private void unregisterInstallStateUpdListener() {
    if (appUpdateManager != null && installStateUpdatedListener != null)
        appUpdateManager.unregisterListener(installStateUpdatedListener);
}

And we're done!

Testing. Please read the docs so you will know how to test it properly with test tracks on Google Play.

Long story short:

  1. Sign your app with the release certificate and upload it to the one of publishing tracks in Developer Play Console under App Releases (alpha/beta/other custom closed track).

  2. In your release track page in the Manage Testers section create and add a list of testers and make sure you checked the checkbox! - this step is optional since your developer account email is also a testers account and you can use it for testing.

  3. Under the list of testers you will find "Opt-in URL" - copy this url and give it to your testers or open it yourself. Go to that page and accept proposition for testing. There will be a link to the app. (You won't be able to search for the app in Play Store so bookmark it)

  4. Install the app on your device by that link.

  5. In build.gradle increment the version of defaultConfig { versionCode k+1 } and build another signed apk Build > Generate Signed Bundle / APK... and upload it to your publishing track.

  6. Wait for... 1 hour? 2 hours? or more before it will be published on the track.

  7. CLEAR THE CACHE of Play Store app on your device. The problem is that Play app caches details about installed apps and their available updates so you need to clear the cache. In order to do that take two steps:

7.1. Go to Settings > App > Google PLay Store > Storage > Clear Cache.

7.2. Open the Play Store app > open main menu > My apps & games > and there you should see that your app has a new update.

If you don't see it make sure that your new update is already released on the track (go to your bookmarked page and use it to open your apps listing on the Play Store to see what version is shown there). Also, when your update will be live you'll see a notification on the top right of your Developer Play Console (a bell icon will have a red dot).

Hope it helps.

相关文章