Answers:
我同意Scott Helme在这里的另一个回答。但是在某些极端情况(安全问题,API重大更改...)中,您绝对需要用户进行更新才能继续使用该应用程序时,可以提供一个简单的版本控制API。该API如下所示:
versionCheck API:
请求参数:
int appVersion响应
boolean forceUpgradeboolean recommendUpgrade当您的应用启动时,您可以调用传入当前应用版本的此API,并检查版本控制API调用的响应。
如果forceUpgrade为true,则显示一个弹出对话框,其中包含允许用户退出该应用程序或前往Google Play商店升级该应用程序的选项。
否则,如果recommendUpgrade是true,显示的选项弹出对话框更新或继续使用应用程序。
即使有了这种强制升级功能,除非绝对需要,您仍应继续支持旧版本。
尝试以下操作:首先,您需要对playstore链接进行请求调用,从那里获取当前版本,然后将其与当前版本进行比较。
String currentVersion, latestVersion;
Dialog dialog;
private void getCurrentVersion(){
PackageManager pm = this.getPackageManager();
PackageInfo pInfo = null;
try {
pInfo = pm.getPackageInfo(this.getPackageName(),0);
} catch (PackageManager.NameNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
currentVersion = pInfo.versionName;
new GetLatestVersion().execute();
}
private class GetLatestVersion extends AsyncTask<String, String, JSONObject> {
private ProgressDialog progressDialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected JSONObject doInBackground(String... params) {
try {
//It retrieves the latest version by scraping the content of current version from play store at runtime
Document doc = Jsoup.connect(urlOfAppFromPlayStore).get();
latestVersion = doc.getElementsByClass("htlgb").get(6).text();
}catch (Exception e){
e.printStackTrace();
}
return new JSONObject();
}
@Override
protected void onPostExecute(JSONObject jsonObject) {
if(latestVersion!=null) {
if (!currentVersion.equalsIgnoreCase(latestVersion)){
if(!isFinishing()){ //This would help to prevent Error : BinderProxy@45d459c0 is not valid; is your activity running? error
showUpdateDialog();
}
}
}
else
background.start();
super.onPostExecute(jsonObject);
}
}
private void showUpdateDialog(){
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("A New Update is Available");
builder.setPositiveButton("Update", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse
("market://details?id=yourAppPackageName")));
dialog.dismiss();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
background.start();
}
});
builder.setCancelable(false);
dialog = builder.show();
}
新版本问世后,您不应该停止支持旧版本。这将导致糟糕的用户体验。我不知道有任何软件供应商会这样做,这是有充分的理由的。
如果用户当时无法更新或不愿意怎么办?他们根本无法使用您的应用程序,这很糟糕。
Google没有提供类似的版本跟踪选项,因此您必须自己滚动。一个简单的Web服务返回您的应用程序可以检查的当前实时版本就足够了。然后,您可以更新版本,应用程序将知道它已过时。与使用Google Play相比,我只建议使用此方法让您的用户更快地知道有更新。它不应真正用来阻止应用程序正常运行,仅用于提示用户进行更新。
Google团队的解决方案
从Android 5.0开始,可以通过新的Google Play In App更新机制轻松实现。要求是拥有1.5.0+版的Play Core库,并使用App Bundles idstribution而不是apks。
该库为您提供了两种不同的方式来通知用户有关更新的信息:
灵活,当用户在后台对其进行更新时可以继续使用该应用程序时。
立即-阻止屏幕,直到用户对其进行更新,用户才可以进入该应用。
有实现它的下一步:
所有这些步骤的实现均在官方网站上进行了详细描述:https://developer.android.com/guide/app-bundle/in-app-updates
斯科特和迈克尔的答案是正确的。托管提供您支持的最低版本号的服务,并将其与已安装的版本进行比较。希望您永远不需要使用此功能,但是如果存在某些版本,则由于某些严重的缺陷而绝对必须杀死它,这可以节省生命。
我只想添加下一步的代码。提示用户必须升级后,您可以按照以下方法启动Google Play意图并将其带到商店中的新版本。
public class UpgradeActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_upgrade);
final String appName = "com.appname";
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id="+appName)));
}
});
}
}
如果必须在每个版本上强制升级,则应重新考虑设计。
Google引入了应用内更新库(https://developer.android.com/guide/app-bundle/in-app-updates),该库可在Lollipop +上运行,并且使您可以向用户要求更新的功能对话框(FLEXIBLE)或带有强制性全屏消息(IMMEDIATE)。
我在此答案中涵盖了所有代码:https : //stackoverflow.com/a/56808529/5502121
我强烈建议您为此检查Firebase的Remote Config功能。
我使用参数app_version_enabled来实现它,条件为“ Disabled Android Versions”,如下所示:
applies if App ID == com.example.myapp and App version regular expression ^(5.6.1|5.4.2)
参数的默认值为“ true”,但“ Disabled Android Versions”的值为false。在禁用Android版本的正则表达式中,您可以添加更多禁用版本,只需|{version name}在括号内添加另一个即可。
然后,我只是检查配置是否显示了版本已启用-我启动了一项活动,该活动会强制用户进行升级。我检查了可以从外部启动应用程序的仅有两个位置(我的默认启动器活动和意图处理活动)。由于Remote Config是基于缓存工作的,因此,如果没有经过必要的时间才能使缓存无效,则它不会立即捕获应用程序的“已禁用”版本,但是如果您经过的时间最多为12个小时,他们推荐的缓存过期值。
谷歌正式为此提供了一个Android API。
该API目前正在与一些合作伙伴进行测试,并将很快对所有开发人员开放。
更新 API现在可用-https: //developer.android.com/guide/app-bundle/in-app-updates
检查本地版本代码并播放商店apk
try {
versionChecker VersionChecker = new versionChecker();
String versionUpdated = VersionChecker.execute().get().toString();
Log.i("version code is", versionUpdated);
PackageInfo packageInfo = null;
try {
packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
int version_code = packageInfo.versionCode;
String version_name = packageInfo.versionName;
Log.i("updated version code", String.valueOf(version_code) + " " + version_name);
if (version_name != versionUpdated) {
String packageName = getApplicationContext().getPackageName();//
UpdateMeeDialog updateMeeDialog = new UpdateMeeDialog();
updateMeeDialog.showDialogAddRoute(MainActivity.this, packageName);
Toast.makeText(getApplicationContext(), "please updated", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
e.getStackTrace();
}
实现类以进行版本检查
class versionChecker extends AsyncTask<String, String, String> {
String newVersion;
@Override
protected String doInBackground(String... params) {
try {
newVersion = Jsoup.connect("https://play.google.com/store/apps/details?id=+YOR_PACKAGE_NAME+&hl=en")
.timeout(30000)
.userAgent("Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6")
.referrer("http://www.google.com")
.get()
.select("div[itemprop=softwareVersion]")
.first()
.ownText();
} catch (IOException e) {
e.printStackTrace();
}
return newVersion;
}
}
拨号框用于更新
public class UpdateMeeDialog {
ActivityManager am;
TextView rootName;
Context context;
Dialog dialog;
String key1,schoolId;
public void showDialogAddRoute(Activity activity, final String packageName){
context=activity;
dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCancelable(false);
dialog.setContentView(R.layout.dialog_update);
am = (ActivityManager)activity.getSystemService(Context.ACTIVITY_SERVICE);
Button cancelDialogue=(Button)dialog.findViewById(R.id.buttonUpdate);
Log.i("package name",packageName);
cancelDialogue.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://play.google.com/store/apps/details?
id="+packageName+"&hl=en"));
context.startActivity(intent);
}
});
dialog.show();
}
}
对话框布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#d4e9f2">
<TextView
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="Please Update First..!!"
android:textSize="20dp"
android:textColor="#46a5df"
android:textAlignment="center"
android:layout_marginTop="50dp"
android:id="@+id/textMessage"
/>
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:weightSum="1"
android:layout_marginTop="50dp"
android:layout_below="@+id/textMessage"
android:layout_height="50dp">
<Button
android:id="@+id/buttonUpdate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Update"
android:background="#67C6F1"
android:textAlignment="center" />
</LinearLayout>
最好定义我们自己的升级过程。
Android&iOS: 如果有可用的最新应用程序版本,则它将显示为“具有更多功能的最新版本,要升级,请单击升级按钮”(带有“ Upgarde”和“ No.谢谢”按钮的警告。)然后,应用程序将重定向到playstore / Appstore,它将打开最新版本。
--- we can do upgrade compulsory or optionally.
如果有任何数据库架构更改,请在升级过程之前确保已处理正确的数据库迁移过程。
要在市场上有可用更新时强制应用程序用户进行更新,您应该首先检查市场上的应用程序版本,并将其与设备上的应用程序版本进行比较。如果它们不同,则可能是可用的更新。在这篇文章中,我写下了获取市场最新版本和设备上当前版本并将它们进行比较的代码。我还展示了如何显示更新对话框以及如何将用户重定向到更新页面。请访问此链接:https : //stackoverflow.com/a/33925032/5475941只要确保在对话框中仅显示用户更新按钮,而不向他显示取消按钮即可。在这种情况下,他将被迫更新,然后才能使用该应用程序。
这里肯定要提到的是即将发布的In-app Updates API。
您将有两个使用此API的选项;第一种是当您期望用户等待立即应用更新时对关键更新的全屏体验。第二个选项是灵活的更新,这意味着用户可以在下载更新时继续使用该应用程序。您可以完全自定义更新流程,因此感觉就像您的应用程序的一部分。
最好为应用程序版本使用远程配置,并始终检查启动活动是否当前应用程序版本与远程版本相同(如果不是从应用程序商店强制更新)。
简单逻辑快乐编码
您可以使用Play Core Library应用内更新来解决此问题。您可以检查更新是否可用,如果可以无缝安装,请安装它们。
应用内更新与使用APK扩展文件(.obb文件)的应用不兼容。您可以选择灵活下载或立即更新,Google Play会负责为您下载和安装更新。
dependencies {
implementation 'com.google.android.play:core:1.5.0'
...
}
您可以通过在变量中保留在应用程序中的版本号与服务器端保留的当前应用程序版本之间的匹配进行匹配,每次用户打开该应用程序时,都应发送第一个请求以检查是否找到了该请求匹配什么也不做,只会让用户使用您的应用,否则会向Google Playstore发出意图或向您的应用打开网络视图窗口(window.open(“ https://play.google.com/store/apps/details?id= package_name “,'_system','location = yes');),在那里,如果您没有自动更新,他们将自动具有询问更新的按钮,这就是google playstore为您执行的操作。
嗯,可能有很多解决此问题的方法,例如从App Page(Google Play App页面)中抓取版本代码等。
但是,我将向您展示最终的解决方案,该解决方案不会花费一分钱,并且会像魔术一样起作用。
将其与应用程序的当前版本代码进行比较,您可以通过以下代码获得
private int getCurrentVersionCode() {
try {
return getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return -1;
}
如果获取的版本代码大于当前版本,请显示AlertDialog要求更新应用程序。否则,该应用程序已更新。
因此,每当推出新版本时,都需要将该新版本代码放入Firebase远程配置面板中
您可以阅读有关如何使用Firebase Remote Config强制用户更新应用程序的整个教程。
Google为Play Core库发布了应用内更新。
我实现了一个轻量级的库来轻松实现应用程序内更新。您可以在以下链接中找到有关如何强制用户执行更新的示例。
https://github.com/dnKaratzas/android-inapp-update#forced-updates