Android应用自动更新功能的代码实现

<p>由于Android项目开源所致,市面上出现了N多安卓软件市场。为了让我们开发的软件有更多的用户使用,我们需要向N多市场发布,软件升级后,我们也必须到安卓市场上进行更新,给我们增加了工作量。因此我们有必要给我们的Android应用增加自动更新的功能。</p><p>既然实现自动更新,我们首先必须让我们的应用知道是否存在新版本的软件,因此我们可以在自己的网站上放置配置文件,存放软件的版本信息:</p><pre class="brush:as3;toolbar:false">&lt;update&gt; &lt;version&gt;2&lt;/version&gt; &lt;name&gt;baidu_xinwen_1.1.0&lt;/name&gt; &lt;url&gt;http://gdown.baidu.com/data/wisegame/f98d235e39e29031/baiduxinwen.apk&lt;/url&gt; &lt;/update&gt;</pre><p>在这里我使用的是XML文件,方便读取。由于XML文件内容比较少,因此可通过DOM方式进行文件的解析:</p><pre class="brush:as3;toolbar:false">publicclassParseXmlService { publicHashMap&lt;String,String&gt;parseXml(InputStreaminStream)throwsException { HashMap&lt;String,String&gt;hashMap=newHashMap&lt;String,String&gt;(); //实例化一个文档构建器工厂 DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance(); //通过文档构建器工厂获取一个文档构建器 DocumentBuilderbuilder=factory.newDocumentBuilder(); //通过文档通过文档构建器构建一个文档实例 Documentdocument=builder.parse(inStream); //获取XML文件根节点 Elementroot=document.getDocumentElement(); //获得所有子节点 NodeListchildNodes=root.getChildNodes(); for(intj=0;j&lt;childNodes.getLength();j++) { //遍历子节点 NodechildNode=(Node)childNodes.item(j); if(childNode.getNodeType()==Node.ELEMENT_NODE) { ElementchildElement=(Element)childNode; //版本号 if(&quot;version&quot;.equals(childElement.getNodeName())) { hashMap.put(&quot;version&quot;,childElement.getFirstChild().getNodeValue()); } //软件名称 elseif((&quot;name&quot;.equals(childElement.getNodeName()))) { hashMap.put(&quot;name&quot;,childElement.getFirstChild().getNodeValue()); } //下载地址 elseif((&quot;url&quot;.equals(childElement.getNodeName()))) { hashMap.put(&quot;url&quot;,childElement.getFirstChild().getNodeValue()); } } } returnhashMap; } } 通过parseXml()方法,我们可以获取服务器上应用的版本、文件名以及下载地址。紧接着我们就需要获取到我们手机上应用的版本信息: /** *获取软件版本号 * *@paramcontext *@return */ privateintgetVersionCode(Contextcontext) { intversionCode=0; try { //获取软件版本号, versionCode=context.getPackageManager().getPackageInfo(&quot;com.szy.update&quot;,0).versionCode; }catch(NameNotFoundExceptione) { e.printStackTrace(); } returnversionCode; }</pre><p>通过该方法我们获取到的versionCode对应AndroidManifest.xml下android:versionCode。android:versionCode和android:versionName两个属性分别表示版本号,版本名称。versionCode是整数型,而versionName是字符串。由于versionName是给用户看的,不太容易比较大小,升级检查时,就可以检查versionCode。把获取到的手机上应用版本与服务器端的版本进行比较,应用就可以判断处是否需要更新软件。</p><p>处理流程</p><p><img src="/up_pic/201805/290943387171.jpg" title="290943387171.jpg" alt="1.jpg"/></p><p>处理代码</p><pre class="brush:as3;toolbar:false">packagecom.szy.update; importjava.io.File; importjava.io.FileOutputStream; importjava.io.IOException; importjava.io.InputStream; importjava.net.HttpURLConnection; importjava.net.MalformedURLException; importjava.net.URL; importjava.util.HashMap; importandroid.app.AlertDialog; importandroid.app.Dialog; importandroid.app.AlertDialog.Builder; importandroid.content.Context; importandroid.content.DialogInterface; importandroid.content.Intent; importandroid.content.DialogInterface.OnClickListener; importandroid.content.pm.PackageManager.NameNotFoundException; importandroid.net.Uri; importandroid.os.Environment; importandroid.os.Handler; importandroid.os.Message; importandroid.view.LayoutInflater; importandroid.view.View; importandroid.widget.ProgressBar; importandroid.widget.Toast; /** *@authorcoolszy *@date2012-4-26 *@bloghttp://blog.92coding.com */ publicclassUpdateManager { /*下载中*/ privatestaticfinalintDOWNLOAD=1; /*下载结束*/ privatestaticfinalintDOWNLOAD_FINISH=2; /*保存解析的XML信息*/ HashMap&lt;String,String&gt;mHashMap; /*下载保存路径*/ privateStringmSavePath; /*记录进度条数量*/ privateintprogress; /*是否取消更新*/ privatebooleancancelUpdate=false; privateContextmContext; /*更新进度条*/ privateProgressBarmProgress; privateDialogmDownloadDialog; privateHandlermHandler=newHandler() { publicvoidhandleMessage(Messagemsg) { switch(msg.what) { //正在下载 caseDOWNLOAD: //设置进度条位置 mProgress.setProgress(progress); break; caseDOWNLOAD_FINISH: //安装文件 installApk(); break; default: break; } }; }; publicUpdateManager(Contextcontext) { this.mContext=context; } /** *检测软件更新 */ publicvoidcheckUpdate() { if(isUpdate()) { //显示提示对话框 showNoticeDialog(); }else { Toast.makeText(mContext,R.string.soft_update_no,Toast.LENGTH_LONG).show(); } } /** *检查软件是否有更新版本 * *@return */ privatebooleanisUpdate() { //获取当前软件版本 intversionCode=getVersionCode(mContext); //把version.xml放到网络上,然后获取文件信息 InputStreaminStream=ParseXmlService.class.getClassLoader().getResourceAsStream(&quot;version.xml&quot;); //解析XML文件。由于XML文件比较小,因此使用DOM方式进行解析 ParseXmlServiceservice=newParseXmlService(); try { mHashMap=service.parseXml(inStream); }catch(Exceptione) { e.printStackTrace(); } if(null!=mHashMap) { intserviceCode=Integer.valueOf(mHashMap.get(&quot;version&quot;)); //版本判断 if(serviceCode&gt;versionCode) { returntrue; } } returnfalse; } /** *获取软件版本号 * *@paramcontext *@return */ privateintgetVersionCode(Contextcontext) { intversionCode=0; try { //获取软件版本号,对应AndroidManifest.xml下android:versionCode versionCode=context.getPackageManager().getPackageInfo(&quot;com.szy.update&quot;,0).versionCode; }catch(NameNotFoundExceptione) { e.printStackTrace(); } returnversionCode; } /** *显示软件更新对话框 */ privatevoidshowNoticeDialog() { //构造对话框 AlertDialog.Builderbuilder=newBuilder(mContext); builder.setTitle(R.string.soft_update_title); builder.setMessage(R.string.soft_update_info); //更新 builder.setPositiveButton(R.string.soft_update_updatebtn,newOnClickListener() { @Override publicvoidonClick(DialogInterfacedialog,intwhich) { dialog.dismiss(); //显示下载对话框 showDownloadDialog(); } }); //稍后更新 builder.setNegativeButton(R.string.soft_update_later,newOnClickListener() { @Override publicvoidonClick(DialogInterfacedialog,intwhich) { dialog.dismiss(); } }); DialognoticeDialog=builder.create(); noticeDialog.show(); } /** *显示软件下载对话框 */ privatevoidshowDownloadDialog() { //构造软件下载对话框 AlertDialog.Builderbuilder=newBuilder(mContext); builder.setTitle(R.string.soft_updating); //给下载对话框增加进度条 finalLayoutInflaterinflater=LayoutInflater.from(mContext); Viewv=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,newOnClickListener() { @Override publicvoidonClick(DialogInterfacedialog,intwhich) { dialog.dismiss(); //设置取消状态 cancelUpdate=true; } }); mDownloadDialog=builder.create(); mDownloadDialog.show(); //现在文件 downloadApk(); } /** *下载apk文件 */ privatevoiddownloadApk() { //启动新线程下载软件 newdownloadApkThread().start(); } /** *下载文件线程 * *@authorcoolszy *@date2012-4-26 *@bloghttp://blog.92coding.com */ privateclassdownloadApkThreadextendsThread { @Override publicvoidrun() { try { //判断SD卡是否存在,并且是否具有读写权限 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { //获得存储卡的路径 Stringsdpath=Environment.getExternalStorageDirectory()+&quot;/&quot;; mSavePath=sdpath+&quot;download&quot;; URLurl=newURL(mHashMap.get(&quot;url&quot;)); //创建连接 HttpURLConnectionconn=(HttpURLConnection)url.openConnection(); conn.connect(); //获取文件大小 intlength=conn.getContentLength(); //创建输入流 InputStreamis=conn.getInputStream(); Filefile=newFile(mSavePath); //判断文件目录是否存在 if(!file.exists()) { file.mkdir(); } FileapkFile=newFile(mSavePath,mHashMap.get(&quot;name&quot;)); FileOutputStreamfos=newFileOutputStream(apkFile); intcount=0; //缓存 bytebuf[]=newbyte[1024]; //写入到文件中 do { intnumread=is.read(buf); count+=numread; //计算进度条位置 progress=(int)(((float)count/length)*100); //更新进度 mHandler.sendEmptyMessage(DOWNLOAD); if(numread&lt;=0) { //下载完成 mHandler.sendEmptyMessage(DOWNLOAD_FINISH); break; } //写入文件 fos.write(buf,0,numread); }while(!cancelUpdate);//点击取消就停止下载. fos.close(); is.close(); } }catch(MalformedURLExceptione) { e.printStackTrace(); }catch(IOExceptione) { e.printStackTrace(); } //取消下载对话框显示 mDownloadDialog.dismiss(); } }; /** *安装APK文件 */ privatevoidinstallApk() { Fileapkfile=newFile(mSavePath,mHashMap.get(&quot;name&quot;)); if(!apkfile.exists()) { return; } //通过Intent安装APK文件 Intenti=newIntent(Intent.ACTION_VIEW); i.setDataAndType(Uri.parse(&quot;file://&quot;+apkfile.toString()),&quot;application/vnd.android.package-archive&quot;); mContext.startActivity(i); } }</pre><p>效果图</p><p><img src="/up_pic/201805/290943467026.jpg" title="290943467026.jpg" alt="2.jpg"/></p><p><img src="/up_pic/201805/290944052712.jpg" title="290944052712.jpg" alt="3.jpg"/></p><p>检查模拟器SDCARD是否存在下载文件:</p><p><img src="/up_pic/201805/290943567493.jpg" title="290943567493.jpg" alt="4.jpg"/></p>
RangeTime:0.008571s
RangeMem:215.57 KB
返回顶部 留言