在当前的互联网环境下,应用版本的更新非常迅速,更新的方式也有很多种,如传统的应用市场更新,使用第三方SDK如友盟等。现在来分享一下在程序内部实现自动检测更新的功能。
当应用检测更新时,安卓客户端发送get JSON到服务器,服务器处理请求后return JSON到客户端,客户端进行三个步骤的处理
1)与本地Version比较
2)若需要更新则从网络下载文件
3)下载文件后安装
这里简单模拟下服务器端的json数据,最主要的是version_code与version_path,分别代表了版本号与下载路径,浏览器上显示的结果如下图所示:
接下来就开始进行客户端的实现,新建一个updateManager类,这个类就是实现更新功能的类,主要方法有以下几个:
checkUpdate();//检测软件是否需要更新
isUpdate();//与本地版本比较判断是否需要更新
showNoticeDialog();//有更新时显示提示对话框
showDownloadDialog();//显示正在下载对话框
downloadAPK();//开启新线程下载文件
installAPK();//下载到本地后进行安装
下面开始分步进行解析:
一. 通过主Activity调用检查是否需要更新的方法,new UpdateManager(this).checkUpdate()
/*
* 检测软件是否需要更新
*/
public void checkUpdate() {
//访问请求队列
RequestQueue requestQueue = Volley.newRequestQueue(mContext);
JsonObjectRequest request = new JsonObjectRequest(PATH, null, new Listener<JSONObject>() {
@Override
public void onResponse(JSONObject jsonObject) {
Message msg = Message.obtain();
msg.obj = jsonObject;
mGetVersionHandler.sendMessage(msg);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
System.out.println(arg0.toString());
}
});
requestQueue.add(request);
}
二. 请求网络使用了很流行的Volley框架,Path就是上图中浏览器中的地址,得到的jsonObject通过handler发送出去
private Handler mGetVersionHandler = new Handler(){
public void handleMessage(Message msg) {
JSONObject jsonObject = (JSONObject) msg.obj;
System.out.println(jsonObject.toString());
try {
mVersion_code = jsonObject.getString("version_code");
mVersion_name = jsonObject.getString("version_name");
mVersion_desc = jsonObject.getString("version_desc");
mVersion_path = jsonObject.getString("version_path");
if (isUpdate()){
Toast.makeText(mContext, "需要更新", Toast.LENGTH_SHORT).show();
// 显示提示更新对话框
showNoticeDialog();
} else{
Toast.makeText(mContext, "已是最新版本", Toast.LENGTH_SHORT).show();
}
} catch (Exception e){
e.printStackTrace();
}
};
};
三. 在此handler中解析得到的数据,并通过isUpdate()判断是否需要更新,并给出提示
/*
* 与本地版本比较判断是否需要更新
*/
protected boolean isUpdate() {
int serverVersion = Integer.parseInt(mVersion_code);
int localVersion = 1;
try {
localVersion = mContext.getPackageManager().getPackageInfo("com.zpc.autoupdate", 0).versionCode;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
if (serverVersion > localVersion)
return true;
else
return false;
}
四.有更新时显示更新提示对话框
protected void showNoticeDialog() {
AlertDialog.Builder builder = new Builder(mContext);
builder.setTitle("提示");
String message = "软件有更新,要下载安装吗?\n" + mVersion_desc;
builder.setMessage(message);
builder.setPositiveButton("更新", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 隐藏当前对话框
dialog.dismiss();
// 显示下载对话框
showDownloadDialog();
}
});
builder.setNegativeButton("下次再说", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 隐藏当前对话框
dialog.dismiss();
}
});
builder.create().show();
}
五.如果用户点击下载,开启下载对话框,其中用到了进度条的progressBar显示下载进度,下载完成后安装文件,如果下载过程中用户点击取消,则隐藏当前对话框,并将下载状态设置为取消
/*
* 显示正在下载对话框
*/
protected void showDownloadDialog() {
AlertDialog.Builder builder = new Builder(mContext);
builder.setTitle("下载中");
View view = LayoutInflater.from(mContext).inflate(R.layout.dialog_progress, null);
mProgressBar = (ProgressBar) view.findViewById(R.id.id_progress);
builder.setView(view);
builder.setNegativeButton("取消", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 隐藏当前对话框
dialog.dismiss();
// 设置下载状态为取消
mIsCancel = true;
}
});
mDownloadDialog = builder.create();
mDownloadDialog.show();
// 下载文件
downloadAPK();
}
六.开启新线程下载文件,其中涉及到了到了是否有SD卡的判断,输入输出流,进度条的处理等
/*
* 开启新线程下载文件
*/
private void downloadAPK() {
new Thread(new Runnable() {
@Override
public void run() {
try{
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
String sdPath = Environment.getExternalStorageDirectory() + "/";
mSavePath = sdPath + "dhccdownload";
File dir = new File(mSavePath);
if (!dir.exists())//如果不存在,创建文件夹
dir.mkdir();
// 下载文件
HttpURLConnection conn = (HttpURLConnection) new URL(mVersion_path).openConnection();
conn.connect();
InputStream is = conn.getInputStream();//输入流
int length = conn.getContentLength();
File apkFile = new File(mSavePath, mVersion_name);
FileOutputStream fos = new FileOutputStream(apkFile);
int count = 0;
byte[] buffer = new byte[1024];
while (!mIsCancel){
int numread = is.read(buffer);
count += numread;
// 计算进度条的当前位置
mProgress = (int) (((float)count/length) * 100);
// 更新进度条
mUpdateProgressHandler.sendEmptyMessage(DOWNLOADING);
// 下载完成
if (numread < 0){
mUpdateProgressHandler.sendEmptyMessage(DOWNLOAD_FINISH);
break;
}
fos.write(buffer, 0, numread);
}
fos.close();
is.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}).start();
}
七.通过下载文件的handler得到的消息更新进度条,如果下载完成,则开始安装APK方法
private Handler mUpdateProgressHandler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what){
case DOWNLOADING:
// 设置进度条
mProgressBar.setProgress(mProgress);
break;
case DOWNLOAD_FINISH:
// 隐藏当前下载对话框
mDownloadDialog.dismiss();
// 安装 APK 文件
installAPK();
}
};
};
八.下载到本地后执行安装APK
/*
* 下载到本地后执行安装
*/
protected void installAPK() {
File apkFile = new File(mSavePath, mVersion_name);
if (!apkFile.exists())
return;
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("file://" + apkFile.toString());
intent.setDataAndType(uri, "application/vnd.android.package-archive");
mContext.startActivity(intent);
}
以上就是实现程序内部自动检测完成更新功能的实现,实现方法并不难,但涉及到的一些细节还是值得关注,重点在于理清思路。源码下载地址:http://download.csdn.net/detail/zpc5925439/8968771