项目尾声,做一个在线升级的功能。做出来感觉效果还不错,拆分出来一个demo分享出来,先上图:
以下只上后台文件,前台文件和资源文件,需要的请下载源码包。
首先是一个封装的UpdateManager类,如下:
package com.example.updatedemo;
import com.example.updatedemo.R;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.json.JSONObject;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
/*
* 检验apk是否有新版本,是否升级
*
* @author yuanjiang 11.29.2014
*/
public class UpdateManager {
/* 上下文 */
private Context mContext;
/* 下载包安装路径 */
private static final String savePath = Environment.getExternalStorageDirectory()+"/Download/";
private static final int NEW_VERSION = 3;
private static final int DOWN_UPDATE = 1;
private static final int DOWN_OVER = 2;
/* 刷新的进度条 */
private ProgressBar mProgress;
/* 新版本apk的远程路径 */
private String apkUrl ;
/* 保存下载的apk的名称为 */
private String saveFileName;
/* 下载进度 */
private int progress;
private boolean interceptFlag = false;
/*
* Handler静态化,防止内存泄露
*/
private static class MHandler extends Handler
{
/* 引用外部类 */
private WeakReference<UpdateManager> updatemanager;
public MHandler(UpdateManager activity)
{
updatemanager = new WeakReference<UpdateManager>(activity);
}
/* 处理线程结果 */
@Override
public void handleMessage(android.os.Message msg)
{
UpdateManager theClass = updatemanager.get();
switch (msg.what)
{
//对比后有新版本
case NEW_VERSION:
theClass.showUpdateDialog((JSONObject)msg.obj);
break;
//正在下载,更新进度条
case DOWN_UPDATE:
theClass.showProgress();
break;
//下载完成,进行安装
case DOWN_OVER:
theClass.installApk();
}
}
}
/* 实例化Handler */
MHandler mHandler = new MHandler(this);
//构造函数
public UpdateManager(Context context) {
this.mContext = context;
}
/*
* 检查新版本
*/
public void checkVersion()
{
android.util.Log.i("UpdateManager","checkVersion");
Runnable checkVersionRunnable = new Runnable(){
@Override
public void run()
{
try
{
//远程请求服务器,获取远程服务器上的apk版本;这里我们直接模拟返回的结果
JSONObject data = new JSONObject("{"
+ "\"status\":1,"
+ "\"msg\":{"
+ "\"versionCode\":7,"
+ "\"versionName\":\"1.1.7\","
+ "\"versionUrl\":\"http://www.baidu.com\","
+ "\"versionDesc\":\"1,新增定位功能;2,修复定位功能相关BUG;3,增加针对信息推送功能\","
+ "\"versionDate\":\"2013.11.48\","
+ "\"versionSize\":\"1.6M\"}}");
if(data.length()>0) //有返回数据,则发送消息
{
int status = data.getInt("status");
if(status==1)
{
JSONObject newVersionInfo = data.getJSONObject("msg");
int versionCode = newVersionInfo.getInt("versionCode");
String versionName = newVersionInfo.getString("versionName");
saveFileName = "56ol_"+versionName+".apk";
apkUrl = newVersionInfo.getString("versionUrl");
int versionCodeClient = Utils.getversionCode(mContext);
if(versionCode>versionCodeClient) //服务器版本大于本机版本,则视为有新版本
{
Message message = mHandler.obtainMessage(NEW_VERSION);
message.obj = newVersionInfo;
mHandler.sendMessage(message);
}
}
}
}
catch(Exception e)
{
android.util.Log.i("UpdateManager",e.toString());
}
}
};
new Thread(checkVersionRunnable).start();;
}
/* 显示进度条
* 外部类进行封装以便MHandler进行内部调用
*/
public void showProgress()
{
mProgress.setProgress(progress);
}
/*
* 显示版本更新提示框
*/
private void showUpdateDialog(JSONObject newVersionInfo){
final AlertDialog alg = new AlertDialog.Builder(mContext).create();
alg.show();
Window win = alg.getWindow();
win.setContentView(R.layout.common_dialog_update);
//显示新版本内容
TextView title_update = (TextView)win.findViewById(R.id.title_update);
TextView title_date = (TextView)win.findViewById(R.id.title_date);
TextView title_size = (TextView)win.findViewById(R.id.title_size);
TextView versionDesc1 = (TextView)win.findViewById(R.id.versionDesc1);
TextView versionDesc2 = (TextView)win.findViewById(R.id.versionDesc2);
TextView versionDesc3 = (TextView)win.findViewById(R.id.versionDesc3);
try{
title_update.setText(newVersionInfo.getString("versionName")+"版本升级提示");
title_date.setText("发布时间:"+newVersionInfo.getString("versionDate"));
title_size.setText("大小:"+newVersionInfo.getString("versionSize"));
//提示内容按";"进行整合,这里拆分到数组中
String desc[] = newVersionInfo.getString("versionDesc").split(";");
versionDesc1.setText(desc[0]);
versionDesc2.setText(desc[1]);
versionDesc3.setText(desc[2]);
Button positiveButton = (Button)win.findViewById(R.id.PositiveButton);
Button negativeButton = (Button)win.findViewById(R.id.NegativeButton);
positiveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
alg.dismiss();
showDownloadDialog();
}
});
negativeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
alg.dismiss();
}
});
}catch(Exception e){
e.printStackTrace();
}
}
/*
* 显示下载中界面
*/
private void showDownloadDialog(){
final AlertDialog alg = new AlertDialog.Builder(mContext).create();
alg.show();
Window win = alg.getWindow();
win.setContentView(R.layout.common_dialog_progress);
mProgress = (ProgressBar)win.findViewById(R.id.update_progress);
Button negativeButton = (Button)win.findViewById(R.id.NegativeButton);
negativeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
alg.dismiss();
interceptFlag = true; //中止下载
}
});
downloadApk();
}
/*
* 下载apk
* @param url
*/
private void downloadApk(){
Runnable mdownApkRunnable = new Runnable() {
@Override
public void run() {
try {
URL url = new URL(apkUrl);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.connect();
int length = conn.getContentLength();
InputStream is = conn.getInputStream();
File file = new File(savePath);
File ApkFile = new File(file,saveFileName);
FileOutputStream fos = new FileOutputStream(ApkFile);
int count = 0;
byte buf[] = new byte[1024];
do{
int numread = is.read(buf);
count += numread;
progress =(int)(((float)count / length) * 100);
//更新进度
mHandler.sendEmptyMessage(DOWN_UPDATE);
if(numread <= 0){
//下载完成通知安装
mHandler.sendEmptyMessage(DOWN_OVER);
break;
}
fos.write(buf,0,numread);
}while(!interceptFlag); //点击取消就停止下载.
fos.close();
is.close();
} catch (MalformedURLException e) {
android.util.Log.i("MalformedURLException",e.toString());
} catch(IOException e){
android.util.Log.i("IOException",e.toString());
}
}
};
new Thread(mdownApkRunnable).start();
}
/*
* 安装apk
* @param url
*/
private void installApk(){
File apkfile = new File(savePath+saveFileName);
if (!apkfile.exists()) {
return;
}
Intent i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
mContext.startActivity(i);
}
}
UpdateManager.java中有用到一个Utils.java工具类,里面有一个获取本机版本的方法,如下:
package com.example.updatedemo;
import android.content.Context;
public class Utils {
/*
* 获取当前app的versionCode
* return int
*/
public static int getversionCode(Context context) {
int verCode = -1;
try {
verCode = context.getPackageManager().getPackageInfo("com.com56ol.main", 0).versionCode;
} catch (Exception e) {
android.util.Log.e("mUtils-gerversionCode", e.getMessage());
}
return verCode;
}
}
然后就是实例化UpdateManger执行升级了,就两行代码,如下:
package com.example.updatedemo;
import com.example.updatedemo.UpdateManager;
import android.os.Bundle;
import android.app.Activity;
/**
* 在线升级demo
*
* @author yuanjiang 11.27.2013
*/
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//检测版本是否需要更新
UpdateManager mUpdateManager = new UpdateManager(this);
mUpdateManager.checkVersion();
}
}
资源下载地址:http://download.youkuaiyun.com/detail/eclothy/8222061
关于更新安装apk后,不能打开“完成、打开”的界面,而是直接返回桌面,需要修改UpdateManager.java中的installApk()方法,为实例化的intent增加intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),如下:
/*
* 安装apk
* @param url
*/
private void installApk(){
File apkfile = new File(savePath+saveFileName);
if (!apkfile.exists()) {
return;
}
Intent i = new Intent(Intent.ACTION_VIEW);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //设置flag,开启新任务
i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
mContext.startActivity(i);
}