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 到应用程序。
我正在尝试在我的应用中实施应用内更新,但我所查看的 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 到应用程序。