app升级下载
app升级下载在应用开发中是一种非常常见的场景,每当产品迭代出一个新的版本,我们常常可以看到以下两种情况:
1. 用户启动App时,App直接获取到最新版本信息提示用户更新;
2. 用户在“设置”-“检查更新”(也可能是其它描述),“检查更新”的时候获取最新的版本更新;
这两种不同的场景,一种是用户主动请求,另一种则是App主动检查,但原理上来说基本是一致的。
升级模式
在App的升级中,一般会出现如下两种不同的升级模式。
1. 普通升级:正常情况下的升级模式,提示用户升级,并提供“升级”与“取消”选项,用户可以立即升级应用,或者取消升级。
2. 强制升级:顾名思义,在某些特殊情况下使用(如处理了某个严重致命的Bug),提示用户升级,并提供“升级”与“退出”选项,用户必须“升级”立即升级应用才可以继续使用,否则只能“取消”退出应用。
升级判断
关于如何判断当前应用是否升级,这个就比较简单了。
在build.gralde或者AndroidMainifest.xml文件中,我们可以使用versionCode来标识当前应用的版本号(整型值)是多少。
一般情况下,我们可以在后台服务器配置最新的升级信息(如一段json数据),该升级信息可能包含的数据有:最新版本app版本号,最新版本app安装文件下载路径,最新版本app安装文件的md5值,最新版本app更新内容及该版本是否需要用户强制升级等等数据。
{
"versionCode":"100",
"download_url":"http://192.168.2.235:8080/appupdatedemo/yingyongbao_7004130.apk",
"md5":"6581a2a7b16ba3429efda73fe8220e86",
"force_update":"0"
}
客户端可以通过相应的请求接口获取升级信息,然后解析出最新app的版本号,对比判断出当前app是否是最新的,若不是,则弹出应用升级提示。
升级文件下载
关于下载最新的app安装文件,一般情况下,在应用程序中,我们都会默认指定下载路径及文件保存名称,因此,在下载app最新版本安装文件前,我们可以先判断本地是否已经存在该升级文件。当然,获取到该文件后我们需要判断该文件与我们要下载的升级文件是否是同个文件,判断也很简单,通过计算本地文件的MD5值是否与升级信息中的MD5值一致。若不是一个文件,我们就可以通过升级信息中获取到最新安装包的下载路径下载最新的安装文件,这就是Android中的文件下载了。
// 判断是否已经下载过该升级文件
private File getDownloadApkFile() {
File file = new File(DownloadUtils.getDownloadDir(this, DownloadUtils.APK_FOLDER_NAME), DownloadUtils.APK_FILE_NAME);
if (file.exists() && file.isFile()) {
// 获取本地下载文件MD5值
String fileMD5 = MD5Utils.getFileMD5String(file);
// 获取服务器最新升级文件MD5值,这里使用假设值,其实该值直接从升级信息文件中md5字段解析即可
String updateFileMD5 = "6581a2a7b16ba3429efda73fe8220e86";
if (fileMD5.equals(updateFileMD5)) {
return file;
}
}
return null;
}
然后就是关于升级安装包的下载了,在下载的过程中,我们可以通过定义一个接口,然后把我们下载中的各种情况通过这个接口回调传递出去,如我们下载成功了,有成功的回调;下载失败了,有失败的回调,失败的错误代码,失败的错误信息;还有当前下载的进度,也可以通过回调的方式传递出去。
public interface IDownloadCallback {
public void success(Object object);
public void process(int current, int total);
public void fail(Exception e);
}
一般情况下都是使用Http请求下载文件,这在Android中我们也经常用到。
InputStream is = null;
FileOutputStream fos = null;
try {
URLConnection urlConnection = url.openConnection();
urlConnection.setConnectTimeout(30000);
urlConnection.setReadTimeout(30000);
fos = new FileOutputStream(savedFile);
is = urlConnection.getInputStream();
byte[] buff = new byte[1024];
int len;
int now = 0;
int total = urlConnection.getContentLength();
while ((len = is.read(buff)) != -1) {
if (isCanceled) {
throw new RuntimeException("已取消");
}
fos.write(buff, 0, len);
now += len;
if(callback != null) {
callback.process(now, total);
}
}
if(callback != null) {
callback.success(savedFile);
}
} catch (Exception e) {
if(callback != null) {
callback.fail(e);
}
}
然后我们就通过升级安装包的url请求下载文件,再通过callback来更新我们下载的各种状态。
关于下载各阶段状态的显示,有一些应用使用了Dialog直观显示,有一些应用使用Notification形式显示,这个主要看具体产品需求。
还有一点需要注意的是,我们通过在线程中做下载动作,有时我们需要取消下载,那么如何取消下载呢?切记不要使用手动调用stop()方法来结束一个线程,这种方式是不安全,也不是Google推荐的。可以使用如下方式,设置一个标志位结束线程,然后再调用线程的interrupt()就可以了。
private void finishDownloadThread() {
isCanceled = true;
if(mDownloadThread != null) {
mDownloadThread.interrupt();
mDownloadThread = null;
}
}
至此,App升级下载的主要流程就介绍完。