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

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

[html] view plaincopy
  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 plaincopy
  1. public class ParseXmlService
  2. {
  3. public HashMap<String, String> parseXml(InputStream inStream) throws Exception
  4. {
  5. HashMap<String, String> hashMap = new HashMap<String, String>();
  6. // 实例化一个文档构建器工厂
  7. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  8. // 通过文档构建器工厂获取一个文档构建器
  9. DocumentBuilder builder = factory.newDocumentBuilder();
  10. // 通过文档通过文档构建器构建一个文档实例
  11. Document document = builder.parse(inStream);
  12. //获取XML文件根节点
  13. Element root = document.getDocumentElement();
  14. //获得所有子节点
  15. NodeList childNodes = root.getChildNodes();
  16. for (int j = 0; j < childNodes.getLength(); j++)
  17. {
  18. //遍历子节点
  19. Node childNode = (Node) childNodes.item(j);
  20. if (childNode.getNodeType() == Node.ELEMENT_NODE)
  21. {
  22. Element childElement = (Element) childNode;
  23. //版本号
  24. if ("version".equals(childElement.getNodeName()))
  25. {
  26. hashMap.put("version",childElement.getFirstChild().getNodeValue());
  27. }
  28. //软件名称
  29. else if (("name".equals(childElement.getNodeName())))
  30. {
  31. hashMap.put("name",childElement.getFirstChild().getNodeValue());
  32. }
  33. //下载地址
  34. else if (("url".equals(childElement.getNodeName())))
  35. {
  36. hashMap.put("url",childElement.getFirstChild().getNodeValue());
  37. }
  38. }
  39. }
  40. return hashMap;
  41. }
  42. }

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

[java] view plaincopy
  1. /**
  2. * 获取软件版本号
  3. *
  4. * @param context
  5. * @return
  6. */
  7. private int getVersionCode(Context context)
  8. {
  9. int versionCode = 0;
  10. try
  11. {
  12. // 获取软件版本号,
  13. versionCode = context.getPackageManager().getPackageInfo("com.szy.update", 0).versionCode;
  14. } catch (NameNotFoundException e)
  15. {
  16. e.printStackTrace();
  17. }
  18. return versionCode;
  19. }

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

处理流程


处理代码

[java] view plaincopy
  1. package com.szy.update;
  2. import java.io.File;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.net.HttpURLConnection;
  7. import java.net.MalformedURLException;
  8. import java.net.URL;
  9. import java.util.HashMap;
  10. import android.app.AlertDialog;
  11. import android.app.Dialog;
  12. import android.app.AlertDialog.Builder;
  13. import android.content.Context;
  14. import android.content.DialogInterface;
  15. import android.content.Intent;
  16. import android.content.DialogInterface.OnClickListener;
  17. import android.content.pm.PackageManager.NameNotFoundException;
  18. import android.net.Uri;
  19. import android.os.Environment;
  20. import android.os.Handler;
  21. import android.os.Message;
  22. import android.view.LayoutInflater;
  23. import android.view.View;
  24. import android.widget.ProgressBar;
  25. import android.widget.Toast;
  26. /**
  27. *@author coolszy
  28. *@date 2012-4-26
  29. *@blog http://blog.92coding.com
  30. */
  31. public class UpdateManager
  32. {
  33. /* 下载中 */
  34. private static final int DOWNLOAD = 1;
  35. /* 下载结束 */
  36. private static final int DOWNLOAD_FINISH = 2;
  37. /* 保存解析的XML信息 */
  38. HashMap<String, String> mHashMap;
  39. /* 下载保存路径 */
  40. private String mSavePath;
  41. /* 记录进度条数量 */
  42. private int progress;
  43. /* 是否取消更新 */
  44. private boolean cancelUpdate = false;
  45. private Context mContext;
  46. /* 更新进度条 */
  47. private ProgressBar mProgress;
  48. private Dialog mDownloadDialog;
  49. private Handler mHandler = new Handler()
  50. {
  51. public void handleMessage(Message msg)
  52. {
  53. switch (msg.what)
  54. {
  55. // 正在下载
  56. case DOWNLOAD:
  57. // 设置进度条位置
  58. mProgress.setProgress(progress);
  59. break;
  60. case DOWNLOAD_FINISH:
  61. // 安装文件
  62. installApk();
  63. break;
  64. default:
  65. break;
  66. }
  67. };
  68. };
  69. public UpdateManager(Context context)
  70. {
  71. this.mContext = context;
  72. }
  73. /**
  74. * 检测软件更新
  75. */
  76. public void checkUpdate()
  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. private boolean isUpdate()
  93. {
  94. // 获取当前软件版本
  95. int versionCode = getVersionCode(mContext);
  96. // 把version.xml放到网络上,然后获取文件信息
  97. InputStream inStream = ParseXmlService.class.getClassLoader().getResourceAsStream("version.xml");
  98. // 解析XML文件。 由于XML文件比较小,因此使用DOM方式进行解析
  99. ParseXmlService service = new ParseXmlService();
  100. try
  101. {
  102. mHashMap = service.parseXml(inStream);
  103. } catch (Exception e)
  104. {
  105. e.printStackTrace();
  106. }
  107. if (null != mHashMap)
  108. {
  109. int serviceCode = Integer.valueOf(mHashMap.get("version"));
  110. // 版本判断
  111. if (serviceCode > versionCode)
  112. {
  113. return true;
  114. }
  115. }
  116. return false;
  117. }
  118. /**
  119. * 获取软件版本号
  120. *
  121. * @param context
  122. * @return
  123. */
  124. private int getVersionCode(Context context)
  125. {
  126. int versionCode = 0;
  127. try
  128. {
  129. // 获取软件版本号,对应AndroidManifest.xml下android:versionCode
  130. versionCode = context.getPackageManager().getPackageInfo("com.szy.update", 0).versionCode;
  131. } catch (NameNotFoundException e)
  132. {
  133. e.printStackTrace();
  134. }
  135. return versionCode;
  136. }
  137. /**
  138. * 显示软件更新对话框
  139. */
  140. private void showNoticeDialog()
  141. {
  142. // 构造对话框
  143. AlertDialog.Builder builder = new Builder(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, new OnClickListener()
  148. {
  149. @Override
  150. public void onClick(DialogInterface dialog, int which)
  151. {
  152. dialog.dismiss();
  153. // 显示下载对话框
  154. showDownloadDialog();
  155. }
  156. });
  157. // 稍后更新
  158. builder.setNegativeButton(R.string.soft_update_later, new OnClickListener()
  159. {
  160. @Override
  161. public void onClick(DialogInterface dialog, int which)
  162. {
  163. dialog.dismiss();
  164. }
  165. });
  166. Dialog noticeDialog = builder.create();
  167. noticeDialog.show();
  168. }
  169. /**
  170. * 显示软件下载对话框
  171. */
  172. private void showDownloadDialog()
  173. {
  174. // 构造软件下载对话框
  175. AlertDialog.Builder builder = new Builder(mContext);
  176. builder.setTitle(R.string.soft_updating);
  177. // 给下载对话框增加进度条
  178. final LayoutInflater inflater = LayoutInflater.from(mContext);
  179. View v = 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, new OnClickListener()
  184. {
  185. @Override
  186. public void onClick(DialogInterface dialog, int which)
  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. private void downloadApk()
  202. {
  203. // 启动新线程下载软件
  204. new downloadApkThread().start();
  205. }
  206. /**
  207. * 下载文件线程
  208. *
  209. * @author coolszy
  210. *@date 2012-4-26
  211. *@blog http://blog.92coding.com
  212. */
  213. private class downloadApkThread extends Thread
  214. {
  215. @Override
  216. public void run()
  217. {
  218. try
  219. {
  220. // 判断SD卡是否存在,并且是否具有读写权限
  221. if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
  222. {
  223. // 获得存储卡的路径
  224. String sdpath = Environment.getExternalStorageDirectory() + "/";
  225. mSavePath = sdpath + "download";
  226. URL url = new URL(mHashMap.get("url"));
  227. // 创建连接
  228. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  229. conn.connect();
  230. // 获取文件大小
  231. int length = conn.getContentLength();
  232. // 创建输入流
  233. InputStream is = conn.getInputStream();
  234. File file = new File(mSavePath);
  235. // 判断文件目录是否存在
  236. if (!file.exists())
  237. {
  238. file.mkdir();
  239. }
  240. File apkFile = new File(mSavePath, mHashMap.get("name"));
  241. FileOutputStream fos = new FileOutputStream(apkFile);
  242. int count = 0;
  243. // 缓存
  244. byte buf[] = new byte[1024];
  245. // 写入到文件中
  246. do
  247. {
  248. int numread = 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 (MalformedURLException e)
  267. {
  268. e.printStackTrace();
  269. } catch (IOException e)
  270. {
  271. e.printStackTrace();
  272. }
  273. // 取消下载对话框显示
  274. mDownloadDialog.dismiss();
  275. }
  276. };
  277. /**
  278. * 安装APK文件
  279. */
  280. private void installApk()
  281. {
  282. File apkfile = new File(mSavePath, mHashMap.get("name"));
  283. if (!apkfile.exists())
  284. {
  285. return;
  286. }
  287. // 通过Intent安装APK文件
  288. Intent i = new Intent(Intent.ACTION_VIEW);
  289. i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
  290. mContext.startActivity(i);
  291. }
  292. }

效果图

检查模拟器SDCARD是否存在下载文件:

参考代码下载:

http://download.csdn.net/detail/coolszy/4262247

http://blog.csdn.net/furongkang/article/details/6886526

转载于:https://www.cnblogs.com/aituming/p/6391454.html

Android应用自动更新功能的代码实现相关推荐

  1. Android应用自动更新功能实现使用AsyncTask!

    为什么80%的码农都做不了架构师?>>>    我所开发应用不是面向大众的应用,所以无法放到应用市场去让大家下载,然后通过应用市场更新.所以我必要做一个应用自动更新功能.但是不难,T ...

  2. android自动更新demo,Android程序自动更新功能模块的实现方法【附完整demo源码下载】...

    本文实例讲述了Android程序自动更新功能模块的实现方法.分享给大家供大家参考,具体如下: 在程序启动的时候检测服务器上有没有对应版本更新,如果有更新,提示用户是否更新. 在程序启动的时候首先调用更 ...

  3. Android 程序自动更新功能模块实现

    2019独角兽企业重金招聘Python工程师标准>>> Android 程序自动更新功能模块实现 在程序启动的时候检测服务器上有没有对应版本更新,如果有更新,提示用户是否更新. 在程 ...

  4. android 360自动更新,Android应用自动更新功能的实现!!!

    大家好,发现半年没有更新博客了,最近一直都比较忙,决定在凌晨 英超 阿森纳VS富勒姆 中场休息的时候,给大家分享Android里应用版本更新功能这一块的实现. 一个好的应用软件都是需要好的维护,从初出 ...

  5. 安卓APP自动更新功能实现

    安卓APP自动更新功能实现 前言 代码实现 前言 安卓App自动更新基本上是每个App都需要具备的功能,接下来介绍一下实现自动更新的步骤. 代码实现 App自动更新主要分为新版本检测.升级弹窗.下载升 ...

  6. android app实现更新功能

    功能演示 Android App自动更新基本上是每个App都需具备的功能.网上有各种更新方式,但基本都是往年的了,最近刚查资料写完一个app更新功能,发现了许多app更新的博客内没有详细说明的小问题, ...

  7. Android APP 自动更新实现(适用Android9.0)

    Android App自动更新基本上是每个App都需具备的功能,参考网上各种资料,自己整理了下,先来看看大致的界面: 一.实现思路: 1.发布Android App时,都会生成output-metad ...

  8. android n 支持机型,Android N无缝更新功能不适于现有机型

    原标题:Android N无缝更新功能不适于现有机型 [天极网手机频道]谷歌在I/O大会中宣布AndroidN引入了Chrome OS中的"无缝更新"功能,该功能允许用户下载系统更 ...

  9. android通知栏应用程序更新,Android App自动更新之通知栏下载

    本文实例为大家分享了Android App自动更新通知栏下载的具体代码,供大家参考,具体内容如下 版本更新说明 这里有调用UpdateService启动服务检查下载安装包等 1. 文件下载,下完后写入 ...

最新文章

  1. 英语写作学习笔录 task1 body
  2. zabbix简单入门
  3. nil slice 和 空 slice
  4. Madplay移植到mini2440开发板【转】
  5. 牛客16662 津津的储蓄计划
  6. 计算机网络模拟校园,计算机网络课程设计-模拟校园网组网实验
  7. 关于c语言编写 顺序表 的创建、插入、修改、删除、显示、退出 的程序案例
  8. JRuby 1.6.5发布 Ruby语言的Java实现
  9. 数据治理--元数据--元数据的作用
  10. 计算机右键菜单太多,鼠标右键菜单选项太多?教你清理多余菜单选项的方法-win7右键菜单管理...
  11. 一碗泡面背后的努力,康师傅连续十次斩获“食安管理十强企业”
  12. mysql 1032 1062_MySQL 1032和1062跳过错误总结
  13. 小学生期末评语经典大全
  14. 5款OCR文字识别软件推荐_分享好用的OCR(图片转文字)工具
  15. Qt创建停靠悬浮窗口实例
  16. 18天精读掌握《费曼物理学讲义卷一》 第10天 2019/6/26
  17. 量化投资学习——股指期货研究(二)
  18. tp6查询某个字段不等于null
  19. 有道词典提示您的网络暂时不可用或受限,请检查您的网络设置
  20. 虚拟机里udp广播发送不出去问题

热门文章

  1. shell-grep命令详解(转)
  2. Spring+SpringMVC+Mybatis框架集成搭建教程
  3. zk reconnect
  4. 用java实现zip压缩
  5. JavaScript 数组详解
  6. MindManager 报错:Click to restart mindjet player 解决方法
  7. 什么是跨域?什么是CSRF?
  8. TWAIN协议学习笔记
  9. 张永伟 大数据会成为互联时代重要变革
  10. Android Wear 唤醒热词会比“你好,安卓”好吗?