欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

android 版本检测 Android程序的版本检测与更新实现介绍

程序员文章站 2023-12-02 19:49:40
做个网站的安卓客户端,用户安装到自己手机上,如果我出了新版本怎么办呢?要有版本更新功能。 本来版本检测最好可以自动进行。但如果每次开启程序,都要先检测一轮,是一种浪费,毕竟...
做个网站的安卓客户端,用户安装到自己手机上,如果我出了新版本怎么办呢?要有版本更新功能。
本来版本检测最好可以自动进行。但如果每次开启程序,都要先检测一轮,是一种浪费,毕竟版本更新是小概率的事情。或许可以程序开启的时候,判断一下时间,单日就检测,双日就不检测,或者随机什么的,降低一下检测的频率?

我采取的做法是将检测功能做到了菜单上,用户有需要,就手动打开自己检测一下。反正我们这个是网站客户端,有版本更新,在网站上发个通告就行了。
版本检测与更新有以下几个关键步骤
1、检测有无新版本
2、下载新版本
3、安装替换新版本
我处理的方案是
1、在assets文件夹新增一个文件:ver.cfg,记录版本信息,纯文本格式,内容只有一句话:
复制代码 代码如下:

version=1.0

android 版本检测 Android程序的版本检测与更新实现介绍 
这个会随安装包装到用户的手机上
然后在网站里面,设置一xml文件ver_apk.xml,内容也只有这么一点:
复制代码 代码如下:

<?xml version="1.0" encoding="utf-8" ?>
<string>1.0</string>

检测的时候,就先访问网站的这个xml,得到最新版本号,然后与手机上的ver.cfg文件里记录的进行比对,不同的话就可以认为存在新版本,提示进行更新。
2、下载的话就是直接下载的,我还不知道怎么弄断点续传
3、安装替换,关键在于签名。就是每个版本的签名要保持一致。否则新的无法替换旧的,提示安装未完成。
------------------- 天气太冷,咯咯咯 ------------------------------------
这个功能做在菜单上,触发代码如下:
复制代码 代码如下:

//==========================================================================
// 菜单
//==========================================================================
private static final string urlapk = "http://3g.***.com/tool/***.apk";
private static final string urlver = "http://3g.***.com/tool/ver_apk.xml";
@override
public boolean oncreateoptionsmenu(menu menu) {
menu.add(menu.none, menu.first + 1, 5, "检测更新").seticon(
android.r.drawable.ic_menu_upload);
menu.add(menu.none,menu.first+2,4,"退出").seticon(android.r.drawable.ic_lock_power_off);
return true;
}
@override
public boolean onoptionsitemselected(menuitem item) {
switch (item.getitemid()) {
case menu.first + 1:
toast.maketext(this, "正在检测版本", toast.length_long).show();
updatever uv = new updatever(urlapk,urlver,mainactivity.this);
uv.checkver();
break;
case menu.first + 2:
confirmexit();
break;
}
return false;
}

检测更新因为代码比较多,写成一个类进行封装
updatever.java
复制代码 代码如下:

package android.***;
import android.app.activity;
import android.app.alertdialog;
import android.app.dialog;
import android.app.progressdialog;
import android.content.context;
import android.content.dialoginterface;
import android.content.intent;
import android.net.uri;
import android.os.asynctask;
import android.util.log;
import android.webkit.urlutil;
import android.widget.toast;
import java.io.file;
import java.io.filenotfoundexception;
import java.io.fileoutputstream;
import java.io.ioexception;
import java.io.inputstream;
import java.net.malformedurlexception;
import java.net.url;
import java.net.urlconnection;
import java.util.properties;
import org.xml.sax.inputsource;
import java.text.simpledateformat;
import java.util.date;
public class updatever extends activity{
private static final string tag = "downloadapk";
private string pastversion;
private string nowversion;
public progressdialog pbar;
private string currentfilepath = "";
private string fileex="";
private string filena="";
private string strurl="";
private string versionuri ="";
private context mcontext;
private final string filever = "ver.cfg";
public updatever(string urlapk,string urlver,final context context){
simpledateformat df = new simpledateformat("yyyymmddhhmmss");
string ver = "?ver=" + df.format(new date());//主要是避开手机的缓存
strurl = urlapk + ver;
versionuri = urlver + ver;
mcontext = context;
}
public void checkver() {
// 解析version网页,获取版本号
getversionxml(versionuri);
}
private void comparever() {
load();

//当有最新版本的时候
if(pastversion != null && !pastversion.equals(nowversion)){
dialog dialog = new alertdialog.builder(mcontext).settitle("系统更新")
.setmessage(string.format("发现新版本%s,目前版本为%s,请更新!",nowversion,pastversion))// 设置内容
// 设置确定按钮
.setpositivebutton("确定"
,new dialoginterface.onclicklistener() {
@override
public void onclick(dialoginterface dialog,
int which) {
pbar = new progressdialog(mcontext);
pbar.settitle("正在下载");
pbar.setmessage("请稍候...");
pbar.setprogressstyle(progressdialog.style_spinner);
fileex = strurl.substring(strurl.lastindexof(".") + 1,strurl.length()).tolowercase();
fileex = fileex.substring(0,fileex.lastindexof("?"));
filena = strurl.substring(strurl.lastindexof("/") + 1,strurl.lastindexof("."));
getfile(strurl);
}
}).setnegativebutton("取消",
new dialoginterface.onclicklistener() {
@override
public void onclick(dialoginterface dialog,
int whichbutton) {
// 点击"取消"按钮之后退出程序
}
}).create();// 创建
// 显示对话框
dialog.show();
}
else{
toast.maketext(mcontext, string.format("当前为最新版本%s",pastversion), toast.length_long).show();
}
}
private void getfile(final string strpath)
{
pbar.show();
try{
if (strpath.equals(currentfilepath) ){
getdatasource(strpath);
}
currentfilepath = strpath;
runnable r = new runnable(){
@override
public void run()
{
try{
getdatasource(strpath);
}
catch (exception e){
log.e(tag, e.getmessage(), e);
}
}
};
new thread(r).start();
}
catch(exception e){
e.printstacktrace();
}
}
/*取得远程文件*/
private void getdatasource(string strpath) throws exception {
if (!urlutil.isnetworkurl(strpath)) {
log.d("tag","error");
}
else {
/*取得url*/
url myurl = new url(strpath);
/*建立联机*/
urlconnection conn = myurl.openconnection();
conn.connect();
/*inputstream 下载文件*/
inputstream is = conn.getinputstream();
if (is == null) {
log.d("tag","error");
throw new runtimeexception("没有读取到文件内容");
}
/*建立临时文件*/
file mytempfile = file.createtempfile(filena, "." + fileex);
mytempfile.getabsolutepath();
/*将文件写入临时盘*/
fileoutputstream fos = new fileoutputstream(mytempfile);
byte buf[] = new byte[128];
do{
int numread = is.read(buf);
if (numread <= 0) {
break;
}
fos.write(buf, 0, numread);
}while (true);

/*打开文件进行安装*/
openfile(mytempfile);
try {
is.close();
}
catch (exception ex){
log.d("tag","error");
log.e(tag, "error: " + ex.getmessage(), ex);
}
}
}
/* 在手机上打开文件 */
private void openfile(file f) {
pbar.cancel();
intent intent = new intent();
intent.addflags(intent.flag_activity_new_task);
intent.setaction(android.content.intent.action_view);
/* 调用getmimetype()来取得mimetype */
string type = getmimetype(f);
/* 设定intent的file与mimetype */
intent.setdataandtype(uri.fromfile(f),type);
mcontext.startactivity(intent);
}
/* 判断文件mimetype的method */
private string getmimetype(file f) {
string type = "";
string fname = f.getname();
/* 取得扩展名 */
string end = fname.substring(fname.lastindexof(".")+1,fname.length()).tolowercase();

/* 按扩展名的类型决定mimetype */
if(end.equals("m4a")
|| end.equals("mp3")
|| end.equals("mid")
|| end.equals("xmf")
|| end.equals("ogg")
|| end.equals("wav")){
type = "audio";
}
else if(end.equals("3gp") || end.equals("mp4")){
type = "video";
}
else if(end.equals("jpg")
|| end.equals("gif")
|| end.equals("png")
|| end.equals("jpeg")
|| end.equals("bmp")){
type = "image";
}
else if(end.equals("apk")){
/* android.permission.install_packages */
type = "application/vnd.android.package-archive";
}
else{
type = "*";
}
/*如果无法直接打开,就跳出软件清单给使用者选择 */
if(!end.equals("apk")){
type += "/*";
}
return type;
}
private void getversionxml(string resourceurl){
getver gv = new getver();
gv.execute(resourceurl);
}
private boolean load(){
properties properties = new properties();
try{
inputstream stream = mcontext.getassets().open(filever);
//fileinputstream stream = mcontext.openfileinput(filever);
//读取文件内容
properties.load(stream);
}
catch (filenotfoundexception e){
return false;
}
catch(ioexception e){
return false;
}
catch(exception e){
return false;
}
pastversion = string.valueof(properties.get("version").tostring());
return true;
}

//==========================================================================
// getver
//==========================================================================
class getver extends asynctask<string, integer, string> {
@override
protected string doinbackground(string... urlver) {
string db = null;
url url = null;

try {
url = new url(urlver[0]);
}
catch (malformedurlexception e) {
e.printstacktrace();
}
inputsource is = null;
try {
is = new inputsource(url.openstream());
is.setencoding("utf-8");
db = saxgetversionservice.readrssxml(is);
}
catch (exception e) {
e.printstacktrace();
}
return db;
}
@override
protected void oncancelled() {
super.oncancelled();
}
@override
protected void onpostexecute(string result) {
nowversion = result;
comparever();
}
}
}

androidmanifest.xml要加上几句
复制代码 代码如下:

<uses-permission android:name="android.permission.internet" />
<uses-permission android:name="android.permission.install_packages"/>
<uses-permission android:name="android.permission.mount_unmount_filesystems"/>
<uses-permission android:name="android.permission.write_external_storage"/>
<uses-permission android:name="android.permission.restart_packages" />
<uses-permission android:name="android.permission.read_phone_state" />
<uses-permission android:name="android.permission.access_network_state" />
<uses-permission android:name="android.permission.access_coarse_location" />
<uses-permission android:name="android.permission.access_wifi_state" />