简体   繁体   English

在 Android 中放置应用内更新实现的位置

[英]Where to put in-app update implementation in Android

I am trying to implement in app updates in my app, but there is a disconnect between the documentation/tutorials that I have looked at and the actual final implementation.我正在尝试在我的应用程序中实现应用程序更新,但是我查看的文档/教程与实际的最终实现之间存在脱节。

I followed various code tutorials from:我遵循了以下各种代码教程:

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 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-入门

The code itself is fairly straightforward.代码本身相当简单。

But what I found missing from all of these tutorials was how to actually call the in-app updates.但是我发现所有这些教程中缺少的是如何实际调用应用程序内更新。 These tutorials all seem to make a dedicated in-app update activity.这些教程似乎都进行了专门的应用内更新活动。 How do I launch this in-app update activity from my main activity?如何从我的主要活动启动此应用内更新活动? Or alternatively, how do I incorporate the in app update code into my already existing main activity?或者,我如何将应用内更新代码合并到我现有的主要活动中?

I assume I want some sort of async launch of an in app update listener or something along those lines, but I can't seem to wrap my head around the last step of integrating all the in-app update code/in-app update activity into my app.我假设我想要某种异步启动应用内更新侦听器或类似的东西,但我似乎无法围绕集成所有应用内更新代码/应用内更新活动的最后一步进入我的应用程序。

Edit: here's a sample of what I've tried编辑:这是我尝试过的示例

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

}

are you looking for this:你在找这个吗:

call to prompt for FlexibleUpdate, this will pop up the google prompt and the user can tap "Install" from there.调用以提示灵活更新,这将弹出谷歌提示,用户可以从那里点击“安装”。 It seems to handle the download/install all in one and i dont have to do the "reload" snackbar step the docs were talking about.它似乎可以同时处理下载/安装,而且我不必执行文档所说的“重新加载”小吃店步骤。

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

THIS ANSWER IS A HACK!这个答案是一个黑客!

I have had quite a bit of trouble with in app updates.我在应用程序更新方面遇到了很多麻烦。 the issue being that this librery was made for users that stay in the same activity where startUpdateFlowForResult is called from and then whenever the user does something unexpected like checking whatsapp or going to the next activity everything breaks down and the update doesnt get completed.问题是这个库是为那些停留在调用startUpdateFlowForResult的同一个活动中的用户制作的,然后每当用户做一些意想不到的事情,比如检查 whatsapp 或进入下一个活动时,一切都会崩溃并且更新没有完成。 and you can try to fix it with endless boilerplate but since calling a snackbar that is activity agnostic is super complex that will cost you at least some gray hairs and leave you with delicate code that probably still is somewhat buggy.并且您可以尝试使用无休止的样板来修复它,但是由于调用与活动无关的小吃店非常复杂,这至少会花费您一些白发,并为您留下可能仍然有些错误的精致代码。

THE ALTERNATIVE替代方案

I finally gave upand decided to redirect my users directly to GooglePlayStore:我终于放弃并决定将我的用户直接重定向到 GooglePlayStore:

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

I use the In-app Updates library exclusively to check for availability and then I show a dialog with the following code in the action button:我专门使用应用内更新库来检查可用性,然后在操作按钮中显示一个包含以下代码的对话框:

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

This is admitedly very hacky but its not as bad as it seems.无可否认,这很hacky,但并不像看起来那么糟糕。 I find that the user experience remmains good and the user can either skip your update or return to the app after initializing the update.我发现用户体验仍然很好,用户可以跳过您的更新或在初始化更新后返回应用程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM