检查更新并下载更新可以说是一个app必备的功能了.
既然是必备功能,往往需要考虑很多东西,如下:
1,更新方式:
一个软件有更新了,如果是上线了新的功能或修复了某些bug,或者是服务端的接口变了等,需要强制用户更新软件,不然就退出应用,而如果只是进行性能的优化或者界面变化但是数据不变的更新,往往不需要强制更新,所以这就产生两种更新需求:强制更新与非强制更新.
2,后台下载:
强制更新可能实现起来较为简单,必须要求用户下载完更新并安装后才能使用,在技术含量上要求不是太高,而对于非强制更新方式,用户可以选择下载更新,并且要切换到后台进行下载,也就是说要使用到service,但是后台下载又会产生第3点要求.
3,界面展示:
在后台下载的应用,需要在界面上展示实时下载进度,对于这块,很多应用都是选择在通知栏上展示,而CheckUpdateLibrary库也不例外,但是光展示实时下载进度还不够,当应用下载完毕,还得需要进行安装应用,而用户可以选择不安装应用,但是当他想安装的时候,你不能让用户再下载一遍吧,所以需要让用户有个地方直接点击就可以安装之前下载的应用,而CheckUpdateLibrary同样选择在通知栏展示一个不可删除的通知,提示用户已经下载完成,点击就可以安装.而另一方面,如果在软件后台下载的过程中,由于不可预测原因,导致软件下载失败,你需要让用户知道软件下载失败了,对于这一点,CheckUpdateLibrary同样是在通知栏展示一个通知,提示用户软件下载失败了,而用户可以点击该通知,重新激活下载Service进行重新下载.
4,网络状态判断:
可能用户在检查更新时用的是流量但是用户自己不知道,在下载的时候可能会直接下载,所以从用户的角度出发,在有更新的Dialog弹出来的时候,就需要让用户知道他当前的网络环境是移动网络环境还是WIFI网络环境,从而用户可以选择是否使用当前网络环境进行下载应用.
5,可移植性:
既然每个应用都需要检查更新,下载更新功能,那么就必须有超强的可移植性,我们不能在这个应用写一份检查更新代码,然后其他应用需要的时候,再把这些代码粘贴过来,这样做会很容易出错,并且很麻烦,而采用CheckUpdateLibrary,直接在Android Studio中一句话引入该库就可以使用,so方便!!!so快捷!!!
而显然,网络上已经有一些关于检查更新或下载更新的库,所以CheckUpdateLibrary相比于其他库有什么优势呢?
1,零耦合:CheckUpdateLibrary从检查更新到下载更新全部采用HttpURLConnection,Dialog同样自定义,没有引入任何其他第三方库,而其他库要么是用的第三方网络请求框架,要么用的是别人封装好的dialog.所以开发者可能会吐槽,这只是一个单纯的检查更新和下载更新功能,我却需要多引入很多第三方库,这无形之中增加了我APK的体积,我很不爽!!!而用这个库,开发者完全不用担心这些.
2,体积小:基于第一点,所以CheckUpdateLibrary库体积超小,只有10多kb,
3,兼容6.0:因为使用的是HttpURLConnection,所以6.0系统同样适配
4,可扩展性:CheckUpdateLibrary内置了一个实体类CheckUpdateInfo,用来接收检查更新时返回的json数据,当然前提得和服务端商定好,对接好字段.而如果不想使用内置实体,开发者完全可以自定义自己的实体类,但是必须保证自定义的实体类中包含newAppVersionCode字段,该字段在库中用来判断是否有更新,所以必须包含,不然会检查不到是否有更新.目前CheckUpdateLibrary只支持实体类的扩展,Dialog还只能用它提供的.
5,其他功能:比如可以自定义apk文件的存储路径,文件名,后台下载时是否在通知栏显示实时下载进度等.
那么如何使用呢?
使用Android Studio的小伙伴可以在gradle中直接引用如下一句话:
compile 'com.qiangxi.checkupdatelibrary:checkupdatelibrary:1.0.2'
使用eclipse的小伙伴只能从github中下载library文件,然后引入到项目中使用了,
CheckUpdateLibrary的github地址如下:
https://github.com/qiangxi/CheckUpdateLibrary
在代码中,只需要这样做即可,代码如下:
package com.qiangxi.checkupdatelibrarydemo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import com.qiangxi.checkupdatelibrary.bean.CheckUpdateInfo;
import com.qiangxi.checkupdatelibrary.dialog.ForceUpdateDialog;
import com.qiangxi.checkupdatelibrary.dialog.UpdateDialog;
public class MainActivity extends AppCompatActivity {
private CheckUpdateInfo mCheckUpdateInfo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
}
private void initData() {
//被注释的代码用来进行检查更新,这里为了方便,模拟一些假数据
// Q.checkUpdate("post", getVersionCode(), "checkUpdateUrl", new CheckUpdateCallback() {
// @Override
// public void onCheckUpdateSuccess(String result, boolean hasUpdate) {
// //result:服务端返回的json
// CheckUpdateInfo checkUpdateInfo = new Gson().fromJson(result, CheckUpdateInfo.class);
// //有更新,显示dialog等
// if (hasUpdate) {
// //强制更新,这里用0表示强制更新,实际情况中可与服务端商定什么数字代表强制更新即可
// if (checkUpdateInfo.getIsForceUpdate() == 0) {
// //show ForceUpdateDialog
// }
// //非强制更新
// else {
// //show UpdateDialog
// }
// } else {
// //无更新,提示已是最新版等
// }
// }
//
// @Override
// public void onCheckUpdateFailure(String failureMessage, int errorCode) {
// //failureMessage:一般为try{}catch(){}捕获的异常信息
// //errorCode:暂时没什么用
// }
// });
//模拟一些假数据
mCheckUpdateInfo = new CheckUpdateInfo();
mCheckUpdateInfo.setAppName("android检查更新库")
.setIsForceUpdate(1)//设置是否强制更新,该方法的参数只要和服务端商定好什么数字代表强制更新即可
.setNewAppReleaseTime("2016-10-14 12:37")//软件发布时间
.setNewAppSize(12.3f)//单位为M
.setNewAppUrl("http://shouji.360tpcdn.com/160914/c5164dfbbf98a443f72f32da936e1379/com.tencent.mobileqq_410.apk")
.setNewAppVersionCode(20)//新app的VersionCode
.setNewAppVersionName("1.0.2")
.setNewAppUpdateDesc("1,优化下载逻辑\n2,修复一些bug\n3,完全实现强制更新与非强制更新逻辑\n4,非强制更新状态下进行下载,默认在后台进行下载\n5,当下载成功时,会在通知栏显示一个通知,点击该通知,进入安装应用界面\n6,当下载失败时,会在通知栏显示一个通知,点击该通知,会重新下载该应用\n7,当下载中,会在通知栏显示实时下载进度,但前提要dialog.setShowProgress(true).");
}
/**
* 强制更新
*/
public void forceUpdateDialogClick(View view) {
mCheckUpdateInfo.setIsForceUpdate(0);
if (mCheckUpdateInfo.getIsForceUpdate() == 0) {
ForceUpdateDialog dialog = new ForceUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib").show();
}
}
/**
* 非强制更新
*/
public void UpdateDialogClick(View view) {
mCheckUpdateInfo.setIsForceUpdate(1);
if (mCheckUpdateInfo.getIsForceUpdate() == 1) {
UpdateDialog dialog = new UpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
//该方法需设为true,才会在通知栏显示下载进度,默认为false,即不显示
//该方法只会控制下载进度的展示,当下载完成或下载失败时展示的通知不受该方法影响
//即不管该方法是置为false还是true,当下载完成或下载失败时都会在通知栏展示一个通知
.setShowProgress(true)
.setIconResId(R.mipmap.ic_launcher)
.setAppName(mCheckUpdateInfo.getAppName()).show();
}
}
/**
* 获取当前应用版本号
*/
private int getVersionCode() {
try {
PackageManager packageManager = getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(getPackageName(), 0);
return packageInfo.versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return -1;
}
}
}
非强制更新:
强制更新:
最后,再贴一遍CheckUpdateLibrary的github地址:
https://github.com/qiangxi/CheckUpdateLibrary
欢迎start或fork!