您的位置:首页 > 移动开发 > Android开发

Android软件自动更新

2013-03-15 09:28 288 查看
  所有好的手机应用程序都会有这项功能实现。所以我想做一个工具类UpdateManager.java ,然后在activity中直接调用方法 checkUpdate() 检测是否有更新。这样就可以一劳永逸了O(∩_∩)O!

  先说说软件自动更新做的好处:

  1、开发者不需要每次都去各个市场平台发布新版本的软件,可以省去很多时间,金钱;

  2、用户不需要去关注软件是否有更新,可以提高用户满意度。

  再说说其实现原理,这里以流程图展现给大家:

UpdateManager.java

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;

import com.tq365.android.activity.R;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;

public class UpdateManager {

private Context mContext;
// 更新进度条
private ProgressBar mUpdateProgressBar;
// 记录进度条数量
private int progress;
// 保存解析的XML信息
private HashMap<String, String> mHashMap;
// 是否取消更新
private boolean cancelUpdate = false;
// 下载状态--下载中
private static final int DOWNLOAD_ING = 1;
// 下载状态--下载成功
private static final int DOWNLOAD_SUCCESS = 2;
// 下载状态--下载失败
private static final int DOWNLOAD_FAIL = 3;
// 下载保存路径
private String mSavePath;
//下载对话框
private Dialog mDownloadDialog;

private Handler mHandler;

private boolean isLoop;

public UpdateManager(Context context) {
super();
this.mContext = context;
mHandler = new Handler(){

@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case DOWNLOAD_ING:
mUpdateProgressBar.setProgress(progress);
break;
case DOWNLOAD_SUCCESS:
//安装APK
installApk();
break;
case DOWNLOAD_FAIL:
Toast.makeText(mContext, "文件下载失败!", Toast.LENGTH_LONG).show();
break;
}
}

};
}

/**
* 检测软件更新
*
* @param isAuto
*            为true:软件自动检测更新;false:用户手动检测更新。
*/
public void checkUpdate(boolean isAuto) {
try {
if (isUpdate()) {
// 显示提示对话框
showNoticeDialog();
} else if (!isAuto) {
// 告诉用户已是最新版本,不需要更新。
Toast.makeText(mContext, "您的软件已是最新版本,不需要更新!", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 检测软件是否有更新
*
* @return
* @throws Exception
*/
private boolean isUpdate() throws Exception {
//获取当前软件版本
int versionCode = getVersionVode(mContext);
//获取我们之前放在服务器端的app_version.xml的文件信息
//Android 3.0(含)之后访问网络都不能在主线程中
isLoop = true;
new Thread(){

@Override
public void run() {
try {
InputStream inStream = HttpUtil.getInputStream("apks/app_version.xml", null, HttpUtil.METHOD_GET);
//解析xml文件。由于XML文件较小,我们采用DOM方式进行解析
ParseXmlService service = new ParseXmlService();//这个类是自己写的解析XML的工具类
try {
mHashMap = service.parseXml(inStream);
} catch (Exception e) {
e.printStackTrace();
}finally{
isLoop = false;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
while (isLoop) {
Thread.sleep(1000);
}
if (null != mHashMap) {
int serviceCode = Integer.valueOf(mHashMap.get("version"));
//判断版本号
if (serviceCode > versionCode) {
return true;
}
}
return false;
}

/**
* 获取软件当前版本号
*
* @param context
* @return
*/
private int getVersionVode(Context context){
int versionCode = 0;
// 获取软件版本号,对应AndroidManifest.xml下android:versionCode
try {
versionCode = context.getPackageManager().getPackageInfo("com.tq365.android.activity", 0).versionCode;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return versionCode;
}

/**
* 显示软件更新对话框
*/
private void showNoticeDialog() {
AlertDialog.Builder builder = new Builder(mContext);
builder.setTitle("软件更新")
.setMessage("软件有新版本,要更新吗?")
.setPositiveButton("立即更新", new OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
//显示软件下载对话框
showDownloadDialog();
}
})
.setNegativeButton("稍后再说", new OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).create().show();
}

/**
* 显示软件下载对话框
*/
private void showDownloadDialog() {
AlertDialog.Builder builder = new Builder(mContext);
builder.setTitle("正在更新");
//给对话框增加进度条
LayoutInflater inflater = LayoutInflater.from(mContext);
View v = inflater.inflate(R.layout.update_progress, null);
mUpdateProgressBar = (ProgressBar) v.findViewById(R.id.update_progressBar);
mDownloadDialog = builder.setView(v)
.setNegativeButton("取消更新", new OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
//设置取消状态
cancelUpdate = true;
}
}).create();
mDownloadDialog.show();
//下载APK文件
downloadApk();
}

/**
* 下载APK文件
*/
private void downloadApk() {
//启动下载APK线程
new DownloadApkThread().start();
}

/**
* 下载APK文件线程
*/
private class DownloadApkThread extends Thread {

@Override
public void run() {
try {
// 判断SD卡是否存在,并且是否有读写权限
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
// 获取SD卡路径
String sdPadth = Environment.getExternalStorageDirectory()+ "";
mSavePath = sdPadth + "/download";
URL url = new URL(mHashMap.get("url"));
// 创建连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.connect();
// 获取文件大小
int fileSize = conn.getContentLength();
// 创建输入流
InputStream inStream = conn.getInputStream();
File file = new File(mSavePath);
// 判断文件目录是否存在,不存在则创建该目录
if (!file.exists()) {
file.mkdir();
}
File apkFile = new File(mSavePath, mHashMap.get("name"));
FileOutputStream fos = new FileOutputStream(apkFile);
int count = 0;
// 缓存
byte[] b = new byte[1024];
do {
int numRead = inStream.read(b);
count += numRead;
// 计算进度条位置
progress = (int) (((float) count / fileSize) * 100);
// 更新进度
mHandler.sendEmptyMessage(DOWNLOAD_ING);
if (numRead <= 0) {// 下载完成
mHandler.sendEmptyMessage(DOWNLOAD_SUCCESS);
break;
}
// 写入文件
fos.write(b, 0, numRead);
} while (!cancelUpdate);
}
} catch (Exception e) {
mHandler.sendEmptyMessage(DOWNLOAD_FAIL);
} finally {
mDownloadDialog.dismiss();
}
}
}

/**
* 安装APK
*/
private void installApk() {
File apk = new File(mSavePath,mHashMap.get("name"));
if (!apk.exists()) {
return;
}
//通过Intent安装APK文件
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://"+apk.toString()), "application/vnd.android.package-archive");
mContext.startActivity(intent);
}
}


如果转载请尊重作者的劳动果实,附上http://www.cnblogs.com/small-bai/archive/2013/03/12/2955852.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: