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

由于Android项目开源所致,市面上出现了N多安卓软件市场。为了让我们开发的软件有更多的用户使用,我们需要向N多市场发布,软件升级后,我们也必须到安卓市场上进行更新,给我们增加了工作量。因此我们有必要给我们的Android应用增加自动更新的功能。

既然实现自动更新,我们首先必须让我们的应用知道是否存在新版本的软件,因此我们可以在自己的网站上放置配置文件,存放软件的版本信息:

[html] view plain copy
  1. <update>
  2. <version>2</version>
  3. <name>baidu_xinwen_1.1.0</name>
  4. <url>http://gdown.baidu.com/data/wisegame/f98d235e39e29031/baiduxinwen.apk</url>
  5. </update>

在这里我使用的是XML文件,方便读取。由于XML文件内容比较少,因此可通过DOM方式进行文件的解析:

[java] view plain copy
  1. publicclassParseXmlService
  2. {
  3. publicHashMap<String,String>parseXml(InputStreaminStream)throwsException
  4. {
  5. HashMap<String,String>hashMap=newHashMap<String,String>();
  6. //实例化一个文档构建器工厂
  7. DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance();
  8. //通过文档构建器工厂获取一个文档构建器
  9. DocumentBuilderbuilder=factory.newDocumentBuilder();
  10. //通过文档通过文档构建器构建一个文档实例
  11. Documentdocument=builder.parse(inStream);
  12. //获取XML文件根节点
  13. Elementroot=document.getDocumentElement();
  14. //获得所有子节点
  15. NodeListchildNodes=root.getChildNodes();
  16. for(intj=0;j<childNodes.getLength();j++)
  17. {
  18. //遍历子节点
  19. NodechildNode=(Node)childNodes.item(j);
  20. if(childNode.getNodeType()==Node.ELEMENT_NODE)
  21. {
  22. ElementchildElement=(Element)childNode;
  23. //版本号
  24. if("version".equals(childElement.getNodeName()))
  25. {
  26. hashMap.put("version",childElement.getFirstChild().getNodeValue());
  27. }
  28. //软件名称
  29. elseif(("name".equals(childElement.getNodeName())))
  30. {
  31. hashMap.put("name",childElement.getFirstChild().getNodeValue());
  32. }
  33. //下载地址
  34. elseif(("url".equals(childElement.getNodeName())))
  35. {
  36. hashMap.put("url",childElement.getFirstChild().getNodeValue());
  37. }
  38. }
  39. }
  40. returnhashMap;
  41. }
  42. }

通过parseXml()方法,我们可以获取服务器上应用的版本、文件名以及下载地址。紧接着我们就需要获取到我们手机上应用的版本信息:

[java] view plain copy
  1. /**
  2. *获取软件版本号
  3. *
  4. *@paramcontext
  5. *@return
  6. */
  7. privateintgetVersionCode(Contextcontext)
  8. {
  9. intversionCode=0;
  10. try
  11. {
  12. //获取软件版本号,
  13. versionCode=context.getPackageManager().getPackageInfo("com.szy.update",0).versionCode;
  14. }catch(NameNotFoundExceptione)
  15. {
  16. e.printStackTrace();
  17. }
  18. returnversionCode;
  19. }

通过该方法我们获取到的versionCode对应AndroidManifest.xml下android:versionCode。android:versionCode和android:versionName两个属性分别表示版本号,版本名称。versionCode是整数型,而versionName是字符串。由于versionName是给用户看的,不太容易比较大小,升级检查时,就可以检查versionCode。把获取到的手机上应用版本与服务器端的版本进行比较,应用就可以判断处是否需要更新软件。

处理流程


处理代码

[java] view plain copy
  1. packagecom.szy.update;
  2. importjava.io.File;
  3. importjava.io.FileOutputStream;
  4. importjava.io.IOException;
  5. importjava.io.InputStream;
  6. importjava.net.HttpURLConnection;
  7. importjava.net.MalformedURLException;
  8. importjava.net.URL;
  9. importjava.util.HashMap;
  10. importandroid.app.AlertDialog;
  11. importandroid.app.Dialog;
  12. importandroid.app.AlertDialog.Builder;
  13. importandroid.content.Context;
  14. importandroid.content.DialogInterface;
  15. importandroid.content.Intent;
  16. importandroid.content.DialogInterface.OnClickListener;
  17. importandroid.content.pm.PackageManager.NameNotFoundException;
  18. importandroid.net.Uri;
  19. importandroid.os.Environment;
  20. importandroid.os.Handler;
  21. importandroid.os.Message;
  22. importandroid.view.LayoutInflater;
  23. importandroid.view.View;
  24. importandroid.widget.ProgressBar;
  25. importandroid.widget.Toast;
  26. /**
  27. *@authorcoolszy
  28. *@date2012-4-26
  29. *@bloghttp://blog.92coding.com
  30. */
  31. publicclassUpdateManager
  32. {
  33. /*下载中*/
  34. privatestaticfinalintDOWNLOAD=1;
  35. /*下载结束*/
  36. privatestaticfinalintDOWNLOAD_FINISH=2;
  37. /*保存解析的XML信息*/
  38. HashMap<String,String>mHashMap;
  39. /*下载保存路径*/
  40. privateStringmSavePath;
  41. /*记录进度条数量*/
  42. privateintprogress;
  43. /*是否取消更新*/
  44. privatebooleancancelUpdate=false;
  45. privateContextmContext;
  46. /*更新进度条*/
  47. privateProgressBarmProgress;
  48. privateDialogmDownloadDialog;
  49. privateHandlermHandler=newHandler()
  50. {
  51. publicvoidhandleMessage(Messagemsg)
  52. {
  53. switch(msg.what)
  54. {
  55. //正在下载
  56. caseDOWNLOAD:
  57. //设置进度条位置
  58. mProgress.setProgress(progress);
  59. break;
  60. caseDOWNLOAD_FINISH:
  61. //安装文件
  62. installApk();
  63. break;
  64. default:
  65. break;
  66. }
  67. };
  68. };
  69. publicUpdateManager(Contextcontext)
  70. {
  71. this.mContext=context;
  72. }
  73. /**
  74. *检测软件更新
  75. */
  76. publicvoidcheckUpdate()
  77. {
  78. if(isUpdate())
  79. {
  80. //显示提示对话框
  81. showNoticeDialog();
  82. }else
  83. {
  84. Toast.makeText(mContext,R.string.soft_update_no,Toast.LENGTH_LONG).show();
  85. }
  86. }
  87. /**
  88. *检查软件是否有更新版本
  89. *
  90. *@return
  91. */
  92. privatebooleanisUpdate()
  93. {
  94. //获取当前软件版本
  95. intversionCode=getVersionCode(mContext);
  96. //把version.xml放到网络上,然后获取文件信息
  97. InputStreaminStream=ParseXmlService.class.getClassLoader().getResourceAsStream("version.xml");
  98. //解析XML文件。由于XML文件比较小,因此使用DOM方式进行解析
  99. ParseXmlServiceservice=newParseXmlService();
  100. try
  101. {
  102. mHashMap=service.parseXml(inStream);
  103. }catch(Exceptione)
  104. {
  105. e.printStackTrace();
  106. }
  107. if(null!=mHashMap)
  108. {
  109. intserviceCode=Integer.valueOf(mHashMap.get("version"));
  110. //版本判断
  111. if(serviceCode>versionCode)
  112. {
  113. returntrue;
  114. }
  115. }
  116. returnfalse;
  117. }
  118. /**
  119. *获取软件版本号
  120. *
  121. *@paramcontext
  122. *@return
  123. */
  124. privateintgetVersionCode(Contextcontext)
  125. {
  126. intversionCode=0;
  127. try
  128. {
  129. //获取软件版本号,对应AndroidManifest.xml下android:versionCode
  130. versionCode=context.getPackageManager().getPackageInfo("com.szy.update",0).versionCode;
  131. }catch(NameNotFoundExceptione)
  132. {
  133. e.printStackTrace();
  134. }
  135. returnversionCode;
  136. }
  137. /**
  138. *显示软件更新对话框
  139. */
  140. privatevoidshowNoticeDialog()
  141. {
  142. //构造对话框
  143. AlertDialog.Builderbuilder=newBuilder(mContext);
  144. builder.setTitle(R.string.soft_update_title);
  145. builder.setMessage(R.string.soft_update_info);
  146. //更新
  147. builder.setPositiveButton(R.string.soft_update_updatebtn,newOnClickListener()
  148. {
  149. @Override
  150. publicvoidonClick(DialogInterfacedialog,intwhich)
  151. {
  152. dialog.dismiss();
  153. //显示下载对话框
  154. showDownloadDialog();
  155. }
  156. });
  157. //稍后更新
  158. builder.setNegativeButton(R.string.soft_update_later,newOnClickListener()
  159. {
  160. @Override
  161. publicvoidonClick(DialogInterfacedialog,intwhich)
  162. {
  163. dialog.dismiss();
  164. }
  165. });
  166. DialognoticeDialog=builder.create();
  167. noticeDialog.show();
  168. }
  169. /**
  170. *显示软件下载对话框
  171. */
  172. privatevoidshowDownloadDialog()
  173. {
  174. //构造软件下载对话框
  175. AlertDialog.Builderbuilder=newBuilder(mContext);
  176. builder.setTitle(R.string.soft_updating);
  177. //给下载对话框增加进度条
  178. finalLayoutInflaterinflater=LayoutInflater.from(mContext);
  179. Viewv=inflater.inflate(R.layout.softupdate_progress,null);
  180. mProgress=(ProgressBar)v.findViewById(R.id.update_progress);
  181. builder.setView(v);
  182. //取消更新
  183. builder.setNegativeButton(R.string.soft_update_cancel,newOnClickListener()
  184. {
  185. @Override
  186. publicvoidonClick(DialogInterfacedialog,intwhich)
  187. {
  188. dialog.dismiss();
  189. //设置取消状态
  190. cancelUpdate=true;
  191. }
  192. });
  193. mDownloadDialog=builder.create();
  194. mDownloadDialog.show();
  195. //现在文件
  196. downloadApk();
  197. }
  198. /**
  199. *下载apk文件
  200. */
  201. privatevoiddownloadApk()
  202. {
  203. //启动新线程下载软件
  204. newdownloadApkThread().start();
  205. }
  206. /**
  207. *下载文件线程
  208. *
  209. *@authorcoolszy
  210. *@date2012-4-26
  211. *@bloghttp://blog.92coding.com
  212. */
  213. privateclassdownloadApkThreadextendsThread
  214. {
  215. @Override
  216. publicvoidrun()
  217. {
  218. try
  219. {
  220. //判断SD卡是否存在,并且是否具有读写权限
  221. if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
  222. {
  223. //获得存储卡的路径
  224. Stringsdpath=Environment.getExternalStorageDirectory()+"/";
  225. mSavePath=sdpath+"download";
  226. URLurl=newURL(mHashMap.get("url"));
  227. //创建连接
  228. HttpURLConnectionconn=(HttpURLConnection)url.openConnection();
  229. conn.connect();
  230. //获取文件大小
  231. intlength=conn.getContentLength();
  232. //创建输入流
  233. InputStreamis=conn.getInputStream();
  234. Filefile=newFile(mSavePath);
  235. //判断文件目录是否存在
  236. if(!file.exists())
  237. {
  238. file.mkdir();
  239. }
  240. FileapkFile=newFile(mSavePath,mHashMap.get("name"));
  241. FileOutputStreamfos=newFileOutputStream(apkFile);
  242. intcount=0;
  243. //缓存
  244. bytebuf[]=newbyte[1024];
  245. //写入到文件中
  246. do
  247. {
  248. intnumread=is.read(buf);
  249. count+=numread;
  250. //计算进度条位置
  251. progress=(int)(((float)count/length)*100);
  252. //更新进度
  253. mHandler.sendEmptyMessage(DOWNLOAD);
  254. if(numread<=0)
  255. {
  256. //下载完成
  257. mHandler.sendEmptyMessage(DOWNLOAD_FINISH);
  258. break;
  259. }
  260. //写入文件
  261. fos.write(buf,0,numread);
  262. }while(!cancelUpdate);//点击取消就停止下载.
  263. fos.close();
  264. is.close();
  265. }
  266. }catch(MalformedURLExceptione)
  267. {
  268. e.printStackTrace();
  269. }catch(IOExceptione)
  270. {
  271. e.printStackTrace();
  272. }
  273. //取消下载对话框显示
  274. mDownloadDialog.dismiss();
  275. }
  276. };
  277. /**
  278. *安装APK文件
  279. */
  280. privatevoidinstallApk()
  281. {
  282. Fileapkfile=newFile(mSavePath,mHashMap.get("name"));
  283. if(!apkfile.exists())
  284. {
  285. return;
  286. }
  287. //通过Intent安装APK文件
  288. Intenti=newIntent(Intent.ACTION_VIEW);
  289. i.setDataAndType(Uri.parse("file://"+apkfile.toString()),"application/vnd.android.package-archive");
  290. mContext.startActivity(i);
  291. }
  292. }

效果图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值