1、版本控制属性
versionCode:
版本号(versionCode)是一个Integer类型的值,所以不要将versionCode设置的太大,最好不要超过Integer的取值范围(当然一般也是不会超过的),一般大家在发布自己的第一个应用到市场的时候,版本取值为1(versionCode=1),这也是目前典型和普遍的做法。然后,每次发布更新版本时可以递增versionCode的值。
vertionName
版本名(versionName)一个值为String类型的属性,一般和VersionCode成对出现。VersionCode是方便程序开发者运行和维护Application而设置的一个有效的值。versionName是一个版本的描述,给用户看的,也是用户放在各个第3方平台上提供给使用者看的一个版本名,可以说是对VersionCode的解释和描述。一般格式可以为:1.1.2。(major.minor.point)的形式。
区别
版本号(versionCode):是用于判断是否升级的,一般每次版本更新,版本号加一。如果获取服务器上的版本号比检测到本程序的版本号高,那么提示升级。
版本名(versionName):用于显示版本改变的幅度大小,比如从2.0.1改变为2.0.2可能只是修改了一个很小的bug,如果改变为2.1.0可能是新增了一些功能,如果改变为3.0.0可能是有很大幅度的修改,比如很多UI界面或功能的添加!
也就是版本号用于判断是否可以升级,而版本名用于显示給用户看!
版本控制的文件位置
Eclipse中在Manifest.xml中的VersionCode为准,而Android studio也可以在Manifest.xml中也有,但是无效的,以app级别的grade中versionCode为准。
2、版本控制步骤
①从自己的服务器获取自己的APP的版本号
②检查是否更新
//对比本程序的版本号和最新程序的版本号
public void checkVersion() {
//如果检测本程序的版本号小于服务器的版本号,那么提示用户更新
if (VersionControlUtils.getVersionCode() < serviceVersionCode) {
//弹出提示版本更新的对话框
showDialogUpdate();
} else {
//否则吐司,说现在是最新的版本
Toast.makeText(context, "最新版本"), Toast.LENGTH_SHORT).show();
}
}
③弹出更新提示的对话框
private void showDialogUpdate() {
View inflate = View.inflate(this, R.layout.dialog_clear_butter, null);
TextView tv_cancel_clear_buffer = (TextView) inflate.findViewById(R.id.tv_cancel_clear_buffer);
TextView tv_ok_clear_butter = (TextView) inflate.findViewById(R.id.tv_ok_clear_butter);
TextView tv_dialog_title = (TextView) inflate.findViewById(R.id.tv_dialog_title);
TextView tv_dialog_message = (TextView) inflate.findViewById(R.id.tv_dialog_message);
tv_dialog_title.setText("版本升级");
tv_dialog_message.setText("请更新到最新版本");
tv_cancel_clear_buffer.setOnClickListener(this);
tv_ok_clear_butter.setOnClickListener(this);
// 这里的属性可以一直设置,因为每次设置后返回的是一个builder对象
dialog = new Dialog(this, R.style.style_dialog);
dialog.setContentView(inflate);
dialog.setCanceledOnTouchOutside(false);
dialog.show();
}
④点击升级版本并下载新版本
private void loadNewVersionProgress() {
final String uri = "http://www.apk.anzhi.com/data3/apk/201703/14/4636d7fce23c9460587d602b9dc20714_88002100.apk";
final ProgressDialog pd; //进度条对话框
pd = new ProgressDialog(this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage(getString(R.string.downloading_new_version));
pd.show();
//启动子线程下载任务
new Thread() {
@Override
public void run() {
try {
File file = getFileFromServer(uri, pd);
sleep(3000);
installApk(file);
pd.dismiss(); //结束掉进度条对话框
} catch (Exception e) {
//下载apk失败
Toast.makeText(getApplicationContext(), R.string.download_new_version_fail, Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
}.start();
}
⑤根据Uri网址获取apk文件
private File getFileFromServer(String uri, ProgressDialog pd) throws Exception {
//如果相等的话表示当前的sdcard挂载在手机上并且是可用的
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
URL url = new URL(uri);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
//获取到文件的大小
pd.setMax(conn.getContentLength());
InputStream is = conn.getInputStream();
long time = System.currentTimeMillis();//当前时间的毫秒数
File file = new File(Environment.getExternalStorageDirectory(), time + "updata.apk");
FileOutputStream fos = new FileOutputStream(file);
BufferedInputStream bis = new BufferedInputStream(is);
byte[] buffer = new byte[1024];
int len;
int total = 0;
while ((len = bis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
total += len;
//获取当前下载量
pd.setProgress(total);
}
fos.close();
bis.close();
is.close();
return file;
} else {
return null;
}
}
⑥安装apk文件
private void installApk(File file) {
Intent intent = new Intent();
//执行动作
intent.setAction(Intent.ACTION_VIEW);
//执行的数据类型
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
startActivity(intent);
}