转:Android应用的自动升级、更新模块的实现

Android应用的自动升级、更新模块的实现

我们看到很多Android应用都具有自动更新功能,用户一键就可以完成软件的升级更新。得益于Android系统的软件包管理和安装机制,这一功能实现起来相当简单,下面我们就来实践一下。首先给出界面效果:

1.准备知识

在AndroidManifest.xml里定义了每个Androidapk的版本标识:

<manifestxmlns:android="http://schemas.android.com/apk/res/android"

package="com.myapp"

android:versionCode="1"

android:versionname="1.0.0">

<application></application>

</manifest>

复制代码

其中,android:versionCode和android:versionName两个字段分别表示版本代码,版本名称。versionCode是整型数字,versionName是字符串。由于version是给用户看的,不太容易比较大小,升级检查时,可以以检查versionCode为主,方便比较出版本的前后大小。

那么,在应用中如何读取AndroidManifest.xml中的versionCode和versionName呢?可以使用PackageManager的API,参考以下代码:

publicstaticintgetVerCode(Contextcontext){

intverCode=-1;

try{

verCode=context.getPackageManager().getPackageInfo(

"com.myapp",0).versionCode;

}catch(NameNotFoundExceptione){

Log.e(TAG,e.getMessage());

}

returnverCode;

}

publicstaticStringgetVerName(Contextcontext){

Stringvername="";

try{

verName=context.getPackageManager().getPackageInfo(

"com.myapp",0).versionName;

}catch(NameNotFoundExceptione){

Log.e(TAG,e.getMessage());

}

returnverName;

}

复制代码

或者在AndroidManifest中将android:versionname="1.2.0"写成android:versionname="@string/app_versionName",然后在values/strings.xml中添加对应字符串,这样实现之后,就可以使用如下代码获得版本名称:

publicstaticStringgetVerName(Contextcontext){

StringverName=context.getResources()

.getText(R.string.app_versionName).toString();

returnverName;

}

复制代码

同理,apk的应用名称可以这样获得:

publicstaticStringgetAppName(Contextcontext){

StringverName=context.getResources()

.getText(R.string.app_name).toString();

returnverName;

}

复制代码

2.流程框架

3.版本检查

在服务端放置最新版本的apk文件,如:http://localhost/myapp/myapp.apk

同时,在服务端放置对应此apk的版本信息调用接口或者文件,如:http://localhost/myapp/ver.json

ver.json中的内容为:

[{"appname":"jtapp12","apkname":"jtapp-12-updateapksamples.apk","verName":1.0.1,"verCode":2}]

复制代码

然后,在手机客户端上进行版本读取和检查:

privatebooleangetServerVer(){

try{

Stringverjson=NetworkTool.getContent(Config.UPDATE_SERVER

+Config.UPDATE_VERJSON);

JSONArrayarray=newJSONArray(verjson);

if(array.length()>0){

JSONObjectobj=array.getJSONObject(0);

try{

newVerCode=Integer.parseInt(obj.getString("verCode"));

newVerName=obj.getString("verName");

}catch(Exceptione){

newVerCode=-1;

newVername="";

returnfalse;

}

}

}catch(Exceptione){

Log.e(TAG,e.getMessage());

returnfalse;

}

returntrue;

}

复制代码

比较服务器和客户端的版本,并进行更新操作。

if(getServerVerCode()){

intvercode=Config.getVerCode(this);//用到前面第一节写的方法

if(newVerCode>vercode){

doNewVersionUpdate();//更新新版本

}else{

notNewVersionShow();//提示当前为最新版本

}

}

复制代码

详细方法:

privatevoidnotNewVersionShow(){

intverCode=Config.getVerCode(this);

StringverName=Config.getVerName(this);

StringBuffersb=newStringBuffer();

sb.append("当前版本:");

sb.append(verName);

sb.append("Code:");

sb.append(verCode);

sb.append(",/n已是最新版,无需更新!");

Dialogdialog=newAlertDialog.Builder(Update.this).setTitle("软件更新")

.setMessage(sb.toString())//设置内容

.setPositiveButton("确定",//设置确定按钮

newDialogInterface.OnClickListener(){

@Override

publicvoidonClick(DialogInterfacedialog,

intwhich){

finish();

}

}).create();//创建

//显示对话框

dialog.show();

}

privatevoiddoNewVersionUpdate(){

intverCode=Config.getVerCode(this);

StringverName=Config.getVerName(this);

StringBuffersb=newStringBuffer();

sb.append("当前版本:");

sb.append(verName);

sb.append("Code:");

sb.append(verCode);

sb.append(",发现新版本:");

sb.append(newVerName);

sb.append("Code:");

sb.append(newVerCode);

sb.append(",是否更新?");

Dialogdialog=newAlertDialog.Builder(Update.this)

.setTitle("软件更新")

.setMessage(sb.toString())

//设置内容

.setPositiveButton("更新",//设置确定按钮

newDialogInterface.OnClickListener(){

@Override

publicvoidonClick(DialogInterfacedialog,

intwhich){

pBar=newProgressDialog(Update.this);

pBar.setTitle("正在下载");

pBar.setMessage("请稍候...");

pBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);

downFile(Config.UPDATE_SERVER+Config.UPDATE_APKNAME);

}

})

.setNegativeButton("暂不更新",

newDialogInterface.OnClickListener(){

publicvoidonClick(DialogInterfacedialog,

intwhichButton){

//点击"取消"按钮之后退出程序

finish();

}

}).create();//创建

//显示对话框

dialog.show();

}

复制代码

4.下载模块

注,本部分参考了前人的相关实现,

importjava.io.File;

importjava.io.FileOutputStream;

importjava.io.IOException;

importjava.io.InputStream;

importorg.apache.http.HttpEntity;

importorg.apache.http.HttpResponse;

importorg.apache.http.client.ClientProtocolException;

importorg.apache.http.client.HttpClient;

importorg.apache.http.client.methods.HttpGet;

importorg.apache.http.impl.client.DefaultHttpClient;

importandroid.app.AlertDialog;

importandroid.app.Dialog;

importandroid.app.ProgressDialog;

importandroid.content.DialogInterface;

importandroid.content.Intent;

importandroid.net.Uri;

importandroid.os.Bundle;

importandroid.os.Environment;

importandroid.os.Handler;

publicclassUpdateextendsBaseActivity{

publicProgressDialogpBar;

privateHandlerhandler=newHandler();

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.update);

Dialogdialog=newAlertDialog.Builder(Update.this).setTitle("系统更新")

.setMessage("发现新版本,请更新!")//设置内容

.setPositiveButton("确定",//设置确定按钮

newDialogInterface.OnClickListener(){

@Override

publicvoidonClick(DialogInterfacedialog,

intwhich){

pBar=newProgressDialog(Update.this);

pBar.setTitle("正在下载");

pBar.setMessage("请稍候...");

pBar

.setProgressStyle(ProgressDialog.STYLE_SPINNER);

downFile("http://url:8765/OA.apk");

}

}).setNegativeButton("取消",

newDialogInterface.OnClickListener(){

publicvoidonClick(DialogInterfacedialog,

intwhichButton){

//点击"取消"按钮之后退出程序

}

}).create();//创建

//显示对话框

dialog.show();

}

voiddownFile(finalStringurl){

pBar.show();

newThread(){

publicvoidrun(){

HttpClientclient=newDefaultHttpClient();

//params[0]代表连接的url

HttpGetget=newHttpGet(url);

HttpResponseresponse;

try{

response=client.execute(get);

HttpEntityentity=response.getEntity();

longlength=entity.getContentLength();

InputStreamis=entity.getContent();

FileOutputStreamfileOutputStream=null;

if(is!=null){

Filefile=newFile(Environment

.getExternalStorageDirectory(),"OA.apk");

fileOutputStream=newFileOutputStream(file);

byte[]buf=newbyte[1024];

intch=-1;

intcount=0;

while((ch=is.read(buf))!=-1){

//baos.write(buf,0,ch);

fileOutputStream.write(buf,0,ch);

count+=ch;

if(length>0){

}

}

}

fileOutputStream.flush();

if(fileOutputStream!=null){

fileOutputStream.close();

}

down();

}catch(ClientProtocolExceptione){

//TODOAuto-generatedcatchblock

e.printStackTrace();

}catch(IOExceptione){

//TODOAuto-generatedcatchblock

e.printStackTrace();

}

}

}.start();

}

voiddown(){

handler.post(newRunnable(){

publicvoidrun(){

pBar.cancel();

update();

}

});

}

voidupdate(){

Intentintent=newIntent(Intent.ACTION_VIEW);

intent.setDataAndType(Uri.fromFile(newFile("/sdcard/OA.apk")),

"application/vnd.android.package-archive");

startActivity(intent);

}

}

复制代码

```````````````````````

voiddownFile(finalStringurl){

pBar.show();

newThread(){

publicvoidrun(){

HttpClientclient=newDefaultHttpClient();

HttpGetget=newHttpGet(url);

HttpResponseresponse;

try{

response=client.execute(get);

HttpEntityentity=response.getEntity();

longlength=entity.getContentLength();

InputStreamis=entity.getContent();

FileOutputStreamfileOutputStream=null;

if(is!=null){

Filefile=newFile(

Environment.getExternalStorageDirectory(),

Config.UPDATE_SAVENAME);

fileOutputStream=newFileOutputStream(file);

byte[]buf=newbyte[1024];

intch=-1;

intcount=0;

while((ch=is.read(buf))!=-1){

fileOutputStream.write(buf,0,ch);

count+=ch;

if(length>0){

}

}

}

fileOutputStream.flush();

if(fileOutputStream!=null){

fileOutputStream.close();

}

down();

}catch(ClientProtocolExceptione){

e.printStackTrace();

}catch(IOExceptione){

e.printStackTrace();

}

}

}.start();

}

复制代码

下载完成,通过handler通知主ui线程将下载对话框取消。

voiddown(){

handler.post(newRunnable(){

publicvoidrun(){

pBar.cancel();

update();

}

});

}

复制代码

5.安装应用

voidupdate(){

Intentintent=newIntent(Intent.ACTION_VIEW);

intent.setDataAndType(Uri.fromFile(newFile(Environment

.getExternalStorageDirectory(),Config.UPDATE_SAVENAME)),

"application/vnd.android.package-archive");

startActivity(intent);

}

复制代码

果你将apk应用发布到market上,那么,你会发现market内建了类似的模块,可以自动更新或者提醒你是否更新应用。那么,对于你自己的应用需要自动更新的话,自己内建一个是不是更加方便了呢?本文提到的代码大多是在UpdateActivity.java中实现,为了能够使更新过程更加友好,可以在最初launcher的Activity中建立一个线程,用来检查服务端是否有更新。有更新的时候就启动UpdateActivity,这样的使用体验更加平滑。

本文例程源码查看/下载:

相关推荐