我同意另一个回答中的Scott Helme所说的观点。但在某些极端情况下(安全问题,API变更等),您绝对需要用户更新以继续使用应用程序时,可以提供一个简单的版本控制API。该API应如下所示:
版本检查API:
请求参数:
int appVersion
应用版本号响应
boolean forceUpgrade
强制升级boolean recommendUpgrade
推荐升级当您的应用启动时,可以调用此API,并传递当前应用程序版本,然后检查版本控制API调用的响应。
如果 forceUpgrade
是 true
,则显示弹出对话框,让用户选择退出应用程序或前往Google Play商店升级应用程序。
否则,如果recommendUpgrade
是 true
,则显示弹出对话框,让用户选择是更新还是继续使用应用。
即使已经实现了强制升级功能,除非绝对必要,否则您应继续支持旧版本。
试试这个: 首先你需要发起一个请求调用到Play商店的链接,从那里获取当前版本,然后将其与您当前的版本进行比较。
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();
}
当新版本发布时,您不应立即停止支持旧版本,这将导致可怕的用户体验。我不知道有哪家软件供应商会这样做,这很有道理。
如果用户无法更新或在此时不想更新,会发生什么?他们就不能使用您的应用程序,这是不好的。
谷歌不提供类似版本跟踪的选项,因此您需要自己开发此功能。一个简单的Web服务可以返回您的应用程序当前的最新版本进行检查。然后您可以更新版本,应用程序就会知道它已经过时了。我只建议使用此功能让您的用户更快地了解到有更新,而不是依赖Google Play。它应该不会真正阻止应用程序运行,只是促使用户更新。
Google团队的解决方案
从Android 5.0开始,这是通过新的Google Play应用内更新机制很容易实现的。要求使用版本为1.5.0+的Play Core库,并使用App Bundles分发而不是apk。
该库提供了两种不同的方法来通知用户更新:
弹性方式,当用户在后台更新应用程序时可以继续使用该应用程序。
立即方式-阻止屏幕,直到用户更新它为止,不允许用户进入应用程序。
要实施它,请按照以下步骤进行:
所有这些步骤的实现都在官方网站上详细描述:https://developer.android.com/guide/app-bundle/in-app-updates
Scott和Michael的回答是正确的。托管一个提供你支持的最小版本号的服务,并将其与已安装的版本进行比较。希望你永远不需要使用它,但如果某个版本存在严重缺陷而必须摧毁它,它就像救命稻草一样。
我只是想添加下一步要做的代码。接下来是如何启动Google Play Intent并在提示用户必须升级后将他们带到您在商店中的新版本。
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)));
}
});
}
}
如果每次发布都需要强制升级,那么您应该重新考虑您的设计。
官方提供了一种适用于 Android 的 API。
该 API 目前正在与少数合作伙伴进行测试,不久将对所有开发者提供。
更新 API 现在已经可用 - https://developer.android.com/guide/app-bundle/in-app-updates
我强烈建议查看Firebase的远程配置功能。
我使用一个参数-app_version_enabled-实现了它,并使用条件“已禁用的Android版本”进行了设置,如下所示:
applies if App ID == com.example.myapp and App version regular expression ^(5.6.1|5.4.2)
默认参数为"true",但Disabled Android Versions的值为false。在我的Disabled Android Versions正则表达式中,您可以通过另一个用括号括起来的|{version name}
来添加更多禁用版本。
然后我只需检查配置是否指定该版本已启用或未启用--我有一个活动,我会启动它来强制用户升级。我在应用程序仅能从外部启动的两个位置(我的默认启动器活动和一个处理意图的活动)中进行检查。由于远程配置是基于缓存的,如果缓存尚未失效,则不会立即捕获应用程序的"已禁用"版本,但根据他们推荐的缓存过期值,最多需要12小时。
检查本地和应用商店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>