另一种方式实现Android自动检测版本及自动升级
由于Android项目开源所致,市面上出现了N多安卓软件市场。为了让我们开发的软件有更多的用户使用,我们需要向N多市场发布,软件升级后,我们也必须到安卓市场上进行更新,给我们增加了工作量。因此我们有必要给我们的Android应用增加自动更新的功能。
既然实现自动更新,我们首先必须让我们的应用知道是否存在新版本的软件,因此我们可以在自己的网站上放置配置文件,存放软件的版本信息:
-
<update>
-
<version>2</version>
-
<name>baidu_xinwen_1.1.0</name>
-
<url>http://gdown.baidu.com/data/wisegame/f98d235e39e29031/baiduxinwen.apk</url>
-
</update>
在这里我使用的是XML文件,方便读取。由于XML文件内容比较少,因此可通过DOM方式进行文件的解析:
-
public class ParseXmlService
-
{
-
public HashMap<String, String> parseXml(InputStream inStream) throws Exception
-
{
-
HashMap<String, String> hashMap = new HashMap<String, String>();
-
-
// 实例化一个文档构建器工厂
-
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-
// 通过文档构建器工厂获取一个文档构建器
-
DocumentBuilder builder = factory.newDocumentBuilder();
-
// 通过文档通过文档构建器构建一个文档实例
-
Document document = builder.parse(inStream);
-
//获取XML文件根节点
-
Element root = document.getDocumentElement();
-
//获得所有子节点
-
NodeList childNodes = root.getChildNodes();
-
for (int j = 0; j < childNodes.getLength(); j++)
-
{
-
//遍历子节点
-
Node childNode = (Node) childNodes.item(j);
-
if (childNode.getNodeType() == Node.ELEMENT_NODE)
-
{
-
Element childElement = (Element) childNode;
-
//版本号
-
if ("version".equals(childElement.getNodeName()))
-
{
-
hashMap.put("version",childElement.getFirstChild().getNodeValue());
-
}
-
//软件名称
-
else if (("name".equals(childElement.getNodeName())))
-
{
-
hashMap.put("name",childElement.getFirstChild().getNodeValue());
-
}
-
//下载地址
-
else if (("url".equals(childElement.getNodeName())))
-
{
-
hashMap.put("url",childElement.getFirstChild().getNodeValue());
-
}
-
}
-
}
-
return hashMap;
-
}
-
}
通过parseXml()方法,我们可以获取服务器上应用的版本、文件名以及下载地址。紧接着我们就需要获取到我们手机上应用的版本信息:
-
/**
-
* 获取软件版本号
-
*
-
* @param context
-
* @return
-
*/
-
private int getVersionCode(Context context)
-
{
-
int versionCode = 0;
-
try
-
{
-
// 获取软件版本号,
-
versionCode = context.getPackageManager().getPackageInfo("com.szy.update", 0).versionCode;
-
} catch (NameNotFoundException e)
-
{
-
e.printStackTrace();
-
}
-
return versionCode;
-
}
通过该方法我们获取到的versionCode对应AndroidManifest.xml下android:versionCode。android:versionCode和android:versionName两个属性分别表示版本号,版本名称。versionCode是整数型,而versionName是字符串。由于versionName是给用户看的,不太容易比较大小,升级检查时,就可以检查versionCode。把获取到的手机上应用版本与服务器端的版本进行比较,应用就可以判断处是否需要更新软件。
处理流程
处理代码
-
package com.szy.update;
-
-
import java.io.File;
-
import java.io.FileOutputStream;
-
import java.io.IOException;
-
import java.io.InputStream;
-
import java.net.HttpURLConnection;
-
import java.net.MalformedURLException;
-
import java.net.URL;
-
import java.util.HashMap;
-
-
import android.app.AlertDialog;
-
import android.app.Dialog;
-
import android.app.AlertDialog.Builder;
-
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;
-
-
/**
-
*@author coolszy
-
*@date 2012-4-26
-
*@blog http://blog.92coding.com
-
*/
-
-
public class UpdateManager
-
{
-
/* 下载中 */
-
private static final int DOWNLOAD = 1;
-
/* 下载结束 */
-
private static final int DOWNLOAD_FINISH = 2;
-
/* 保存解析的XML信息 */
-
HashMap<String, String> mHashMap;
-
/* 下载保存路径 */
-
private String mSavePath;
-
/* 记录进度条数量 */
-
private int progress;
-
/* 是否取消更新 */
-
private boolean cancelUpdate = false;
-
-
private Context mContext;
-
/* 更新进度条 */
-
private ProgressBar mProgress;
-
private Dialog mDownloadDialog;
-
-
private Handler mHandler = new Handler()
-
{
-
public void handleMessage(Message msg)
-
{
-
switch (msg.what)
-
{
-
// 正在下载
-
case DOWNLOAD:
-
// 设置进度条位置
-
mProgress.setProgress(progress);
-
break;
-
case DOWNLOAD_FINISH:
-
// 安装文件
-
installApk();
-
break;
-
default:
-
break;
-
}
-
};
-
};
-
-
public UpdateManager(Context context)
-
{
-
this.mContext = context;
-
}
-
-
/**
-
* 检测软件更新
-
*/
-
public void checkUpdate()
-
{
-
if (isUpdate())
-
{
-
// 显示提示对话框
-
showNoticeDialog();
-
} else
-
{
-
Toast.makeText(mContext, R.string.soft_update_no, Toast.LENGTH_LONG).show();
-
}
-
}
-
-
/**
-
* 检查软件是否有更新版本
-
*
-
* @return
-
*/
-
private boolean isUpdate()
-
{
-
// 获取当前软件版本
-
int versionCode = getVersionCode(mContext);
-
// 把version.xml放到网络上,然后获取文件信息
-
InputStream inStream = ParseXmlService.class.getClassLoader().getResourceAsStream("version.xml");
-
// 解析XML文件。 由于XML文件比较小,因此使用DOM方式进行解析
-
ParseXmlService service = new ParseXmlService();
-
try
-
{
-
mHashMap = service.parseXml(inStream);
-
} catch (Exception e)
-
{
-
e.printStackTrace();
-
}
-
if (null != mHashMap)
-
{
-
int serviceCode = Integer.valueOf(mHashMap.get("version"));
-
// 版本判断
-
if (serviceCode > versionCode)
-
{
-
return true;
-
}
-
}
-
return false;
-
}
-
-
/**
-
* 获取软件版本号
-
*
-
* @param context
-
* @return
-
*/
-
private int getVersionCode(Context context)
-
{
-
int versionCode = 0;
-
try
-
{
-
// 获取软件版本号,对应AndroidManifest.xml下android:versionCode
-
versionCode = context.getPackageManager().getPackageInfo("com.szy.update", 0).versionCode;
-
} catch (NameNotFoundException e)
-
{
-
e.printStackTrace();
-
}
-
return versionCode;
-
}
-
-
/**
-
* 显示软件更新对话框
-
*/
-
private void showNoticeDialog()
-
{
-
// 构造对话框
-
AlertDialog.Builder builder = new Builder(mContext);
-
builder.setTitle(R.string.soft_update_title);
-
builder.setMessage(R.string.soft_update_info);
-
// 更新
-
builder.setPositiveButton(R.string.soft_update_updatebtn, new OnClickListener()
-
{
-
@Override
-
public void onClick(DialogInterface dialog, int which)
-
{
-
dialog.dismiss();
-
// 显示下载对话框
-
showDownloadDialog();
-
}
-
});
-
// 稍后更新
-
builder.setNegativeButton(R.string.soft_update_later, new OnClickListener()
-
{
-
@Override
-
public void onClick(DialogInterface dialog, int which)
-
{
-
dialog.dismiss();
-
}
-
});
-
Dialog noticeDialog = builder.create();
-
noticeDialog.show();
-
}
-
-
/**
-
* 显示软件下载对话框
-
*/
-
private void showDownloadDialog()
-
{
-
// 构造软件下载对话框
-
AlertDialog.Builder builder = new Builder(mContext);
-
builder.setTitle(R.string.soft_updating);
-
// 给下载对话框增加进度条
-
final LayoutInflater inflater = LayoutInflater.from(mContext);
-
View v = inflater.inflate(R.layout.softupdate_progress, null);
-
mProgress = (ProgressBar) v.findViewById(R.id.update_progress);
-
builder.setView(v);
-
// 取消更新
-
builder.setNegativeButton(R.string.soft_update_cancel, new OnClickListener()
-
{
-
@Override
-
public void onClick(DialogInterface dialog, int which)
-
{
-
dialog.dismiss();
-
// 设置取消状态
-
cancelUpdate = true;
-
}
-
});
-
mDownloadDialog = builder.create();
-
mDownloadDialog.show();
-
// 现在文件
-
downloadApk();
-
}
-
-
/**
-
* 下载apk文件
-
*/
-
private void downloadApk()
-
{
-
// 启动新线程下载软件
-
new downloadApkThread().start();
-
}
-
-
/**
-
* 下载文件线程
-
*
-
* @author coolszy
-
*@date 2012-4-26
-
*@blog http://blog.92coding.com
-
*/
-
private class downloadApkThread extends Thread
-
{
-
@Override
-
public void run()
-
{
-
try
-
{
-
// 判断SD卡是否存在,并且是否具有读写权限
-
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
-
{
-
// 获得存储卡的路径
-
String sdpath = Environment.getExternalStorageDirectory() + "/";
-
mSavePath = sdpath + "download";
-
URL url = new URL(mHashMap.get("url"));
-
// 创建连接
-
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
-
conn.connect();
-
// 获取文件大小
-
int length = conn.getContentLength();
-
// 创建输入流
-
InputStream is = 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 buf[] = new byte[1024];
-
// 写入到文件中
-
do
-
{
-
int numread = is.read(buf);
-
count += numread;
-
// 计算进度条位置
-
progress = (int) (((float) count / length) * 100);
-
// 更新进度
-
mHandler.sendEmptyMessage(DOWNLOAD);
-
if (numread <= 0)
-
{
-
// 下载完成
-
mHandler.sendEmptyMessage(DOWNLOAD_FINISH);
-
break;
-
}
-
// 写入文件
-
fos.write(buf, 0, numread);
-
} while (!cancelUpdate);// 点击取消就停止下载.
-
fos.close();
-
is.close();
-
}
-
} catch (MalformedURLException e)
-
{
-
e.printStackTrace();
-
} catch (IOException e)
-
{
-
e.printStackTrace();
-
}
-
// 取消下载对话框显示
-
mDownloadDialog.dismiss();
-
}
-
};
-
-
/**
-
* 安装APK文件
-
*/
-
private void installApk()
-
{
-
File apkfile = new File(mSavePath, mHashMap.get("name"));
-
if (!apkfile.exists())
-
{
-
return;
-
}
-
// 通过Intent安装APK文件
-
Intent i = new Intent(Intent.ACTION_VIEW);
-
i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
-
mContext.startActivity(i);
-
}
-
}
效果图
检查模拟器SDCARD是否存在下载文件:
参考代码下载:
http://files.cnblogs.com/coolszy/UpdateSoftDemo.rar