Pra*_* ED 6 android auto-update google-play in-app-update
最近,我遇到了Google Play提供的一种新的应用更新流程。我喜欢无缝流程来更新Android应用程序。我在Hotstar应用程序中观察了以下提到的步骤。
我该如何实现?必须有一种与Google Play交流的方式。我浏览了许多博客。但是,没有找到任何解决方案。如果用户禁用了自动应用程序更新,这对于开发人员来说可能是一个很棒的功能。
Pra*_* ED 13
官方文档: https : //developer.android.com/guide/app-bundle/in-app-updates
约束:应用内更新仅适用于运行Android 5.0(API级别21)或更高版本的设备
步骤1:添加依赖项:
dependencies {
implementation 'com.google.android.play:core:1.6.3'
...
}
Run Code Online (Sandbox Code Playgroud)
步骤2:检查更新的可用性,然后开始检查是否可用
mAppUpdateManager = AppUpdateManagerFactory.create(this);
mAppUpdateManager.registerListener(installStateUpdatedListener);
mAppUpdateManager.getAppUpdateInfo().addOnSuccessListener(appUpdateInfo -> {
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)){
try {
mAppUpdateManager.startUpdateFlowForResult(
appUpdateInfo, AppUpdateType.FLEXIBLE, MainActivity.this, RC_APP_UPDATE);
}
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
} else if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED){
popupSnackbarForCompleteUpdate();
} else {
Log.e(TAG, "checkForAppUpdateAvailability: something else");
}
});
Run Code Online (Sandbox Code Playgroud)
步骤3:聆听更新状态
InstallStateUpdatedListener installStateUpdatedListener = new
InstallStateUpdatedListener() {
@Override
public void onStateUpdate(InstallState state) {
if (state.installStatus() == InstallStatus.DOWNLOADED){
popupSnackbarForCompleteUpdate();
} else if (state.installStatus() == InstallStatus.INSTALLED){
if (mAppUpdateManager != null){
mAppUpdateManager.unregisterListener(installStateUpdatedListener);
}
} else {
Log.i(TAG, "InstallStateUpdatedListener: state: " + state.installStatus());
}
}
};
Run Code Online (Sandbox Code Playgroud)
步骤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");
}
}
}
Run Code Online (Sandbox Code Playgroud)
步骤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();
}
Run Code Online (Sandbox Code Playgroud)
请尝试一次。官方文档供参考
步骤1:在build.gradle文件中添加以下库(请检查并更新最新的播放代码插件版本)
implementation 'com.google.android.play:core:1.6.4'
Run Code Online (Sandbox Code Playgroud)
第二步:在类中声明如下变量(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;
Run Code Online (Sandbox Code Playgroud)
第 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);
Run Code Online (Sandbox Code Playgroud)
第 4 步:在 onDestroy() 活动方法中,只需取消注册侦听器
@Override
protected void onDestroy() {
mAppUpdateManager.unregisterListener(installStateUpdatedListener);
super.onDestroy();
}
Run Code Online (Sandbox Code Playgroud)
第 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();
}
Run Code Online (Sandbox Code Playgroud)
第六步:在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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
第 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();
}
}
Run Code Online (Sandbox Code Playgroud)
第 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();
}
}
Run Code Online (Sandbox Code Playgroud)
第 9 步:现在在您想要开始检查更新的任何位置调用具有应用内更新类型(灵活或立即)的方法。
//For Immediate
inAppUpdateType = AppUpdateType.IMMEDIATE; //1
inAppUpdate();
//For Flexible
inAppUpdateType = AppUpdateType.FLEXIBLE; //0
inAppUpdate();
Run Code Online (Sandbox Code Playgroud)
要记住的要点:
灵活更新将首先下载,然后它会通知用户下载完成,然后用户必须开始更新(上述步骤 8 给出的选项)。
谷歌播放控制台有一个选项可以测试应用内共享,我们可以上传普通的apk(不需要签名的apk)进行测试。 https://support.google.com/googleplay/android-developer/answer/9303479?hl=en
需要在您的测试设备 Play 商店应用中启用应用内共享选项。 如何为 Android 启用内部应用程序共享?
尽管如此,Play商店中的任何问题,只需清除缓存并清除数据,然后重新启动设备一次并尝试。
Android今天正式向所有人宣布了应用内更新。https://developer.android.com/guide/app-bundle/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
}
}
Run Code Online (Sandbox Code Playgroud)
来源摘要:https : //gist.github.com/saikiran91/6788ad4d00edca30dad3f51aa47a4c5c
Trying to implement this, the official Google Documentation quoted in the accepted answer is syntactically incorrect. It took some research, but I finally found the correct syntax:
Instead of:
// 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);
}
Run Code Online (Sandbox Code Playgroud)
Do this:
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();
}
}
});
Run Code Online (Sandbox Code Playgroud)
Then, code a similar bit of code in the onResume() override in case an install got hung up along the way:
//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();
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8252 次 |
| 最近记录: |