Android程序自动更新功能模块的实现方法【附完整demo源码下载】
本文实例讲述了Android程序自动更新功能模块的实现方法。分享给大家供大家参考,具体如下:
在程序启动的时候检测服务器上有没有对应版本更新,如果有更新,提示用户是否更新。
在程序启动的时候首先调用更新模块检测服务器上存放的版本号跟当前程序的版本号如果大于当前版本号,弹出更新对话框,如果用户选择更新,则显示当前更新状态,然后替换当前程序。
程序调用版本更新检测:
privateUpdateManagerupdateMan;
privateProgressDialogupdateProgressDialog;
/**Calledwhentheactivityisfirstcreated.*/
@Override
publicvoidonCreate(BundlesavedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//没有判断网路是否连接
//检查是否有更新
//如果有更新提示下载
updateMan=newUpdateManager(Update_TestActivity.this,appUpdateCb);
updateMan.checkUpdate();
}
执行检测版本号以及回调更新提示
下载更新文件等实现:
packageupdate.test;
importjava.io.File;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.net.HttpURLConnection;
importjava.net.MalformedURLException;
importjava.net.URL;
importorg.json.JSONArray;
importorg.json.JSONObject;
importcom.trinet.util.NetHelper;
importandroid.content.Context;
importandroid.content.Intent;
importandroid.content.pm.PackageInfo;
importandroid.content.pm.PackageManager.NameNotFoundException;
importandroid.net.Uri;
importandroid.os.Handler;
importandroid.os.Message;
importandroid.util.Log;
publicclassUpdateManager{
privateStringcurVersion;
privateStringnewVersion;
privateintcurVersionCode;
privateintnewVersionCode;
privateStringupdateInfo;
privateUpdateCallbackcallback;
privateContextctx;
privateintprogress;
privateBooleanhasNewVersion;
privateBooleancanceled;
//存放更新APK文件的路径
publicstaticfinalStringUPDATE_DOWNURL="http://www.baidu.com/update/update_test.apk";
//存放更新APK文件相应的版本说明路径
publicstaticfinalStringUPDATE_CHECKURL="http://www.baidu.com/update/update_verson.txt";
publicstaticfinalStringUPDATE_APKNAME="update_test.apk";
//publicstaticfinalStringUPDATE_VERJSON="ver.txt";
publicstaticfinalStringUPDATE_SAVENAME="updateapk.apk";
privatestaticfinalintUPDATE_CHECKCOMPLETED=1;
privatestaticfinalintUPDATE_DOWNLOADING=2;
privatestaticfinalintUPDATE_DOWNLOAD_ERROR=3;
privatestaticfinalintUPDATE_DOWNLOAD_COMPLETED=4;
privatestaticfinalintUPDATE_DOWNLOAD_CANCELED=5;
//从服务器上下载apk存放文件夹
privateStringsavefolder="/mnt/innerDisk/";
//privateStringsavefolder="/sdcard/";
//publicstaticfinalStringSAVE_FOLDER=Storage.//"/mnt/innerDisk";
publicUpdateManager(Contextcontext,UpdateCallbackupdateCallback){
ctx=context;
callback=updateCallback;
//savefolder=context.getFilesDir();
canceled=false;
getCurVersion();
}
publicStringgetNewVersionName()
{
returnnewVersion;
}
publicStringgetUpdateInfo()
{
returnupdateInfo;
}
privatevoidgetCurVersion(){
try{
PackageInfopInfo=ctx.getPackageManager().getPackageInfo(
ctx.getPackageName(),0);
curVersion=pInfo.versionName;
curVersionCode=pInfo.versionCode;
}catch(NameNotFoundExceptione){
Log.e("update",e.getMessage());
curVersion="1.1.1000";
curVersionCode=111000;
}
}
publicvoidcheckUpdate(){
hasNewVersion=false;
newThread(){
//***************************************************************
/**
*@bywainiwann
*
*/
@Override
publicvoidrun(){
Log.i("@@@@@",">>>>>>>>>>>>>>>>>>>>>>>>>>>getServerVerCode()");
try{
Stringverjson=NetHelper.httpStringGet(UPDATE_CHECKURL);
Log.i("@@@@",verjson
+"**************************************************");
JSONArrayarray=newJSONArray(verjson);
if(array.length()>0){
JSONObjectobj=array.getJSONObject(0);
try{
newVersionCode=Integer.parseInt(obj.getString("verCode"));
newVersion=obj.getString("verName");
updateInfo="";
Log.i("newVerCode",newVersionCode
+"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
Log.i("newVerName",newVersion
+"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
if(newVersionCode>curVersionCode){
hasNewVersion=true;
}
}catch(Exceptione){
newVersionCode=-1;
newVersion="";
updateInfo="";
}
}
}catch(Exceptione){
Log.e("update",e.getMessage());
}
updateHandler.sendEmptyMessage(UPDATE_CHECKCOMPLETED);
};
//***************************************************************
}.start();
}
publicvoidupdate(){
Intentintent=newIntent(Intent.ACTION_VIEW);
intent.setDataAndType(
Uri.fromFile(newFile(savefolder,UPDATE_SAVENAME)),
"application/vnd.android.package-archive");
ctx.startActivity(intent);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
publicvoiddownloadPackage()
{
newThread(){
@Override
publicvoidrun(){
try{
URLurl=newURL(UPDATE_DOWNURL);
HttpURLConnectionconn=(HttpURLConnection)url.openConnection();
conn.connect();
intlength=conn.getContentLength();
InputStreamis=conn.getInputStream();
FileApkFile=newFile(savefolder,UPDATE_SAVENAME);
if(ApkFile.exists())
{
ApkFile.delete();
}
FileOutputStreamfos=newFileOutputStream(ApkFile);
intcount=0;
bytebuf[]=newbyte[512];
do{
intnumread=is.read(buf);
count+=numread;
progress=(int)(((float)count/length)*100);
updateHandler.sendMessage(updateHandler.obtainMessage(UPDATE_DOWNLOADING));
if(numread<=0){
updateHandler.sendEmptyMessage(UPDATE_DOWNLOAD_COMPLETED);
break;
}
fos.write(buf,0,numread);
}while(!canceled);
if(canceled)
{
updateHandler.sendEmptyMessage(UPDATE_DOWNLOAD_CANCELED);
}
fos.close();
is.close();
}catch(MalformedURLExceptione){
e.printStackTrace();
updateHandler.sendMessage(updateHandler.obtainMessage(UPDATE_DOWNLOAD_ERROR,e.getMessage()));
}catch(IOExceptione){
e.printStackTrace();
updateHandler.sendMessage(updateHandler.obtainMessage(UPDATE_DOWNLOAD_ERROR,e.getMessage()));
}
}
}.start();
}
publicvoidcancelDownload()
{
canceled=true;
}
HandlerupdateHandler=newHandler()
{
@Override
publicvoidhandleMessage(Messagemsg){
switch(msg.what){
caseUPDATE_CHECKCOMPLETED:
callback.checkUpdateCompleted(hasNewVersion,newVersion);
break;
caseUPDATE_DOWNLOADING:
callback.downloadProgressChanged(progress);
break;
caseUPDATE_DOWNLOAD_ERROR:
callback.downloadCompleted(false,msg.obj.toString());
break;
caseUPDATE_DOWNLOAD_COMPLETED:
callback.downloadCompleted(true,"");
break;
caseUPDATE_DOWNLOAD_CANCELED:
callback.downloadCanceled();
default:
break;
}
}
};
publicinterfaceUpdateCallback{
publicvoidcheckUpdateCompleted(BooleanhasUpdate,
CharSequenceupdateInfo);
publicvoiddownloadProgressChanged(intprogress);
publicvoiddownloadCanceled();
publicvoiddownloadCompleted(Booleansucess,CharSequenceerrorMsg);
}
}
需要连接服务器模块:
packagecom.trinet.util;
importjava.io.BufferedReader;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.InputStreamReader;
importjava.net.MalformedURLException;
importjava.net.URI;
importjava.net.URL;
importorg.apache.http.HttpResponse;
importorg.apache.http.client.HttpClient;
importorg.apache.http.client.methods.HttpGet;
importorg.apache.http.impl.client.DefaultHttpClient;
importorg.apache.http.params.CoreProtocolPNames;
importorg.apache.http.params.HttpConnectionParams;
importorg.apache.http.params.HttpParams;
importandroid.content.Context;
importandroid.graphics.drawable.Drawable;
importandroid.net.ConnectivityManager;
importandroid.net.NetworkInfo;
importandroid.util.Log;
publicclassNetHelper{
publicstaticStringhttpStringGet(Stringurl)throwsException{
returnhttpStringGet(url,"utf-8");
}
/**
*
*
*@paramurl
*@return
*/
publicstaticDrawableloadImage(Stringurl){
try{
returnDrawable.createFromStream(
(InputStream)newURL(url).getContent(),"test");
}catch(MalformedURLExceptione){
Log.e("exception",e.getMessage());
}catch(IOExceptione){
Log.e("exception",e.getMessage());
}
returnnull;
}
publicstaticStringhttpStringGet(Stringurl,Stringenc)throwsException{
//ThismethodforHttpConnection
Stringpage="";
BufferedReaderbufferedReader=null;
try{
HttpClientclient=newDefaultHttpClient();
client.getParams().setParameter(CoreProtocolPNames.USER_AGENT,"android");
HttpParamshttpParams=client.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams,3000);
HttpConnectionParams.setSoTimeout(httpParams,5000);
HttpGetrequest=newHttpGet();
request.setHeader("Content-Type","text/plain;charset=utf-8");
request.setURI(newURI(url));
HttpResponseresponse=client.execute(request);
bufferedReader=newBufferedReader(newInputStreamReader(response
.getEntity().getContent(),enc));
StringBufferstringBuffer=newStringBuffer("");
Stringline="";
StringNL=System.getProperty("line.separator");
while((line=bufferedReader.readLine())!=null){
stringBuffer.append(line+NL);
}
bufferedReader.close();
page=stringBuffer.toString();
Log.i("page",page);
System.out.println(page+"page");
returnpage;
}finally{
if(bufferedReader!=null){
try{
bufferedReader.close();
}catch(IOExceptione){
Log.d("BBB",e.toString());
}
}
}
}
publicstaticbooleancheckNetWorkStatus(Contextcontext){
booleanresult;
ConnectivityManagercm=(ConnectivityManager)context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfonetinfo=cm.getActiveNetworkInfo();
if(netinfo!=null&&netinfo.isConnected()){
result=true;
Log.i("NetStatus","Thenetwasconnected");
}else{
result=false;
Log.i("NetStatus","Thenetwasbad!");
}
returnresult;
}
}
以及提示对话框:
packagecom.trinet.util;
importjava.lang.reflect.Field;
importandroid.app.AlertDialog;
importandroid.app.AlertDialog.Builder;
importandroid.content.Context;
importandroid.content.DialogInterface;
importandroid.content.DialogInterface.OnClickListener;
importandroid.view.View;
publicclassDialogHelper{
publicstaticvoidAlert(Contextctx,CharSequencetitle,CharSequencemessage,
CharSequenceokText,OnClickListeneroklistener){
AlertDialog.Builderbuilder=createDialog(ctx,title,message);
builder.setPositiveButton(okText,oklistener);
builder.create().show();
}
publicstaticvoidAlert(Contextctx,inttitleId,intmessageId,
intokTextId,OnClickListeneroklistener){
Alert(ctx,ctx.getText(titleId),ctx.getText(messageId),ctx.getText(okTextId),oklistener);
}
publicstaticvoidConfirm(Contextctx,CharSequencetitle,CharSequencemessage,
CharSequenceokText,OnClickListeneroklistener,CharSequencecancelText,
OnClickListenercancellistener){
AlertDialog.Builderbuilder=createDialog(ctx,title,message);
builder.setPositiveButton(okText,oklistener);
builder.setNegativeButton(cancelText,cancellistener);
builder.create().show();
}
publicstaticvoidConfirm(Contextctx,inttitleId,intmessageId,
intokTextId,OnClickListeneroklistener,intcancelTextId,
OnClickListenercancellistener){
Confirm(ctx,ctx.getText(titleId),ctx.getText(messageId),ctx.getText(okTextId),oklistener,ctx.getText(cancelTextId),cancellistener);
}
privatestaticAlertDialog.BuildercreateDialog(Contextctx,CharSequencetitle,
CharSequencemessage){
AlertDialog.Builderbuilder=newBuilder(ctx);
builder.setMessage(message);
if(title!=null)
{
builder.setTitle(title);
}
returnbuilder;
}
@SuppressWarnings("unused")
privatestaticAlertDialog.BuildercreateDialog(Contextctx,inttitleId,intmessageId){
AlertDialog.Builderbuilder=newBuilder(ctx);
builder.setMessage(messageId);
builder.setTitle(titleId);
returnbuilder;
}
publicstaticvoidViewDialog(Contextctx,CharSequencetitle,Viewview,
CharSequenceokText,OnClickListeneroklistener,CharSequencecancelText,
OnClickListenercancellistener){
}
publicstaticvoidViewDialog(Contextctx,inttitleId,Viewview,
intokTextId,OnClickListeneroklistener,intcancelTextId,
OnClickListenercancellistener){
ViewDialog(ctx,ctx.getText(titleId),view,ctx.getText(okTextId),oklistener,ctx.getText(cancelTextId),cancellistener);
}
//
publicstaticvoidSetDialogShowing(DialogInterfacedialog,booleanshowing)
{
try{
Fieldfield=dialog.getClass().getSuperclass().getDeclaredField("mShowing");
field.setAccessible(true);
field.set(dialog,showing);
}catch(Exceptione){
e.printStackTrace();
}
}
}
下面是又更新的话执行回调函数提示用户:
//自动更新回调函数
UpdateManager.UpdateCallbackappUpdateCb=newUpdateManager.UpdateCallback()
{
publicvoiddownloadProgressChanged(intprogress){
if(updateProgressDialog!=null
&&updateProgressDialog.isShowing()){
updateProgressDialog.setProgress(progress);
}
}
publicvoiddownloadCompleted(Booleansucess,CharSequenceerrorMsg){
if(updateProgressDialog!=null
&&updateProgressDialog.isShowing()){
updateProgressDialog.dismiss();
}
if(sucess){
updateMan.update();
}else{
DialogHelper.Confirm(Update_TestActivity.this,
R.string.dialog_error_title,
R.string.dialog_downfailed_msg,
R.string.dialog_downfailed_btnnext,
newDialogInterface.OnClickListener(){
publicvoidonClick(DialogInterfacedialog,
intwhich){
updateMan.downloadPackage();
}
},R.string.dialog_downfailed_btnnext,null);
}
}
publicvoiddownloadCanceled()
{
//TODOAuto-generatedmethodstub
}
publicvoidcheckUpdateCompleted(BooleanhasUpdate,
CharSequenceupdateInfo){
if(hasUpdate){
DialogHelper.Confirm(Update_TestActivity.this,
getText(R.string.dialog_update_title),
getText(R.string.dialog_update_msg).toString()
+updateInfo+
getText(R.string.dialog_update_msg2).toString(),
getText(R.string.dialog_update_btnupdate),
newDialogInterface.OnClickListener(){
publicvoidonClick(DialogInterfacedialog,
intwhich){
updateProgressDialog=newProgressDialog(
Update_TestActivity.this);
updateProgressDialog
.setMessage(getText(R.string.dialog_downloading_msg));
updateProgressDialog.setIndeterminate(false);
updateProgressDialog
.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
updateProgressDialog.setMax(100);
updateProgressDialog.setProgress(0);
updateProgressDialog.show();
updateMan.downloadPackage();
}
},getText(R.string.dialog_update_btnnext),null);
}
}
};
要记得给程序添加权限:
<uses-permissionandroid:name="android.permission.INTERNET"></uses-permission> <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
完整实例代码点击此处本站下载。
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android视图View技巧总结》、《Android编程之activity操作技巧总结》、《Android操作SQLite数据库技巧总结》、《Android操作json格式数据技巧总结》、《Android数据库操作技巧总结》、《Android文件操作技巧汇总》、《Android编程开发之SD卡操作方法汇总》、《Android开发入门与进阶教程》、《Android资源操作技巧汇总》及《Android控件用法总结》
希望本文所述对大家Android程序设计有所帮助。