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程序设计有所帮助。