Android 中应用内更新实施的位置

Where to put in-app update implementation in Android

我正在尝试在我的应用中实施应用内更新,但我所查看的 documentation/tutorials 与实际的最终实施之间存在脱节。

我遵循了以下的各种代码教程:

https://developer.android.com/guide/playcore/in-app-updates/kotlin-java#start-update https://www.section.io/engineering-education/android-application-in-app-update-using-android-studio/ https://medium.com/android-news/implement-in-app-update-in-android-68892bd11e35 https://www.raywenderlich.com/8034025-in-app-updates-getting-started

代码本身相当简单。

但我发现所有这些教程中缺少的是如何实际调用应用内更新。这些教程似乎都做了专门的应用内更新 activity。如何从主 activity 启动此应用内更新 activity?或者,我如何将应用内更新代码合并到我现有的主要 activity?

我假设我想要某种异步启动应用程序内更新侦听器或类似的东西,但我似乎无法理解集成所有应用程序内更新的最后一步 code/in-app 将 activity 更新到我的应用程序中。

编辑:这是我尝试过的示例

public class MainActivity extends AppCompatActivity implements RegionViewAdapter.ItemClickListener {
    private InstallStateUpdatedListener installStateUpdatedListener;
    private static final int FLEXIBLE_APP_UPDATE_REQ_CODE = 123;
    // if you change this value, you must also change it in the app build.gradle
    private final String currentVersion = "2021.06.6";

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

        appUpdateManager = AppUpdateManagerFactory.create(this);

        installStateUpdatedListener = state -> {
            if (state.installStatus() == InstallStatus.DOWNLOADED) {
                popupSnackbarForCompleteUpdate();
            } else if (state.installStatus() == InstallStatus.INSTALLED) {
                removeInstallStateUpdateListener();
            } else {
                Toast.makeText(getApplicationContext(), "InstallStateUpdatedListener: state: " + state.installStatus(), Toast.LENGTH_LONG).show();
            }
        };

    ...
    }
...
    public void checkUpdate() {

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

        // Checks that the platform will allow the specified type of update.
        appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
            if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
                    && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
                startUpdateFlow(appUpdateInfo);
            } else if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) {
                popupSnackbarForCompleteUpdate();
            }
        });

    }

    // Displays the snackbar notification and call to action.
    private void popupSnackbarForCompleteUpdate() {
        Snackbar snackbar =
                Snackbar.make(
                        findViewById(R.id.my_drawer_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();
    }

    private void startUpdateFlow(AppUpdateInfo appUpdateInfo) {
        try {
            appUpdateManager.startUpdateFlowForResult(appUpdateInfo, AppUpdateType.FLEXIBLE, this, FLEXIBLE_APP_UPDATE_REQ_CODE);
        } catch (IntentSender.SendIntentException e) {
            e.printStackTrace();
        }
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == FLEXIBLE_APP_UPDATE_REQ_CODE) {
            if (resultCode == RESULT_CANCELED) {
                Toast.makeText(getApplicationContext(), "Update canceled by user! Result Code: " + resultCode, Toast.LENGTH_LONG).show();
            } else if (resultCode == RESULT_OK) {
                Toast.makeText(getApplicationContext(),"Update success! Result Code: " + resultCode, Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(getApplicationContext(), "Update Failed! Result Code: " + resultCode, Toast.LENGTH_LONG).show();
                checkUpdate();
            }
        }
    }

    private void removeInstallStateUpdateListener() {
        if (appUpdateManager != null) {
            appUpdateManager.unregisterListener(installStateUpdatedListener);
        }
    }


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

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

}

你在找这个吗:

调用以提示 FlexibleUpdate,这将弹出 google 提示,用户可以从那里点击“安装”。它似乎可以一并处理 download/install,而且我不必执行文档正在谈论的“重新加载”小吃店步骤。

  appUpdateManager.startUpdateFlowForResult(appUpdateInfo, AppUpdateType.FLEXIBLE, activity, APP_UPDATE_REQUEST_CODE)

这个答案是一个黑客!

我在应用程序更新方面遇到了很多麻烦。问题是这个库是为那些留在同一个 activity 中的用户创建的,从那里调用 startUpdateFlowForResult 然后每当用户做一些意想不到的事情,比如检查 whatsapp 或去下一个 activity一切都崩溃了,更新没有完成。你可以尝试用无尽的样板来修复它,但是因为调用一个 activity 不可知论者的小吃店是超级复杂的,这至少会让你付出一些白发,并留下可能仍然有些错误的精致代码。

备选方案

我终于放弃了,决定将我的用户直接重定向到 GooglePlayStore:

if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE ) { //maybe you could add some additional checks like priority level here
                makeUpdateDialog(mContext).show();
}

我专门使用应用内更新库来检查可用性,然后在操作按钮中显示一个包含以下代码的对话框:

try {
                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(ownGooglePlayLink)));
} catch (android.content.ActivityNotFoundException anfe) {
                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(ownWebLink)));
}

public static final String ownGooglePlayLink="market://details?id=com.my.package.name";
public static final String ownWebLink="https://play.google.com/store/apps/details?id=com.my.package.name";

诚然,这很不靠谱,但并没有看起来那么糟糕。我发现用户体验仍然很好,用户可以在初始化更新后跳过您的更新或 return 到应用程序。