`

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

阅读更多

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

 

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

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

  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方式进行文件的解析:

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

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

  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。把获取到的手机上应用版本与服务器端的版本进行比较,应用就可以判断处是否需要更新软件。

处理流程


处理代码

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

 

效果图

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

分享到:
评论

相关推荐

    Android应用自动更新代码实现

    Android应用自动更新代码实现,完美实现代码的自动更新。

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

    本篇文章主要介绍了Android应用APP自动更新功能的代码实现,想要实现这个效果的同学可以了解一下。

    Android代码-安卓应用自动更新库

    一个操作简单、支持断点续传、安全性能较高的安卓应用更新库 特点 步骤简单,几行代码就搞定 用户实现是否更新接口,有助于用户自定义 断点续传,断网后,当启动网络后继续下载 安全,代码操作进行大量捕获异常,...

    Android代码-应用程序自动更新源码.zip

    应用程序自动更新源码.zip

    android studio实现简单考试应用程序实例代码详解

    主要介绍了android studio实现简单考试应用程序,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

    Android代码-安卓自动更新

    安卓自动更新,静默更新,可以在通知栏里显示更新下载进度,几行代码快速实现Android下载更新 之前用的友盟更新,但是友盟最近自动跟新业务要停止服务了,所以就自己写了这套自动更新的代码 使用起来特别简单,几行...

    Android开发应用实战详解源代码

    1.1.4 android应用程序框架 1.1.5 android的竞争优势 1.1.6 android模拟器 1.2 搭建android开发环境 1.2.1 准备工作 1.2.2 windows系统下的搭建过程 1.2.3 linux系统下的搭建过程 1.3 常见问题汇总 1.4 使用本书的...

    《Android应用开发揭秘》附带光盘代码.

    《Android应用开发揭秘》全部实例源代码,配合《Android应用开发揭秘》使用 前言  第一部分 准备篇  第1章 Android开发简介  1.1 Android基本概念  1.1.1 Android简介  1.1.2 Android的系统构架  1.1.3 ...

    android应用下载安装apk升级版本实现demo适配Android10

    这个demo实现了android开发应用内下载安装apk升级版本的功能,非常简便轻量集成,完全原生代码即可实现,无需第三方框架。。。

    Android自动更新源码

    Android自动更新源码,调试通过,可用。

    Android 应用软件自动更新源码.zip

    这是一款android平台应用软件自动更新源代码,android平台提供了很好的软件更新借口,通过以上代码,可以非常简单地完成android下一键软件更新功能。 

    Android应用开机自动启动

    Android应用开机自动启动代码Demo,下载后直接放在Android Studio里运行就可以

    Android图片自动滑动功能示例代码.rar

    Android界面图片自动滑动功能示例代码,安卓UI开发的一个小例子,仿优酷视频的客户端应用的图片滑动效果,仿优酷Android客户端图片左右滑动特效,采用android-support-v4中的滑动组件,滑动切换所有的图片,每次滚动...

    Android高级编程--源代码

    3.1 Android应用程序的组成部分 43 3.2 程序清单简介 44 3.3 使用清单编辑器 47 3.4 Android应用程序生命周期 48 3.5 理解应用程序的优先级和进程状态 49 3.6 分离资源 50 3.6.1 创建资源 50 3.6.2 使用资源...

    简单的android应用升级、更新源代码

    很多Android应用都具有自动更新功能,用户一键就可以完成软件的升级更新。得益于Android系统的软件包管理和安装机制,这一功能实现起来相当简单。用了最简单的技术。包括客户端和服务器端。服务器端的返回可以根据...

    Android实例源码-应用启动应用退出&网络判断类安卓源代码(12例).zip

    android程序的自动更新 和 基于GPS定位的轨迹存储 app更新,实现service下载 ViewPager+Fragment侧滑选项卡,浏览器控件,两次退出 【手机安全卫士02】连接服务器获取更新信息 快捷图标的创建与移除 网络判断,界面...

    Android studio 使用自带DownloadManager实现更新app

    使用android 自带的DownloadManager实现文件下载,兼容性强,代码简单,注释详细

    android 程序自动检测更新

    用于android程序自动检测更新,里面包含检测是否有更新,有更新可以选择更新

    Android入门到精通源代码.

    《Android从入门到精通》 第1章 初识Android 1.1 什么是Android 1.1.1 移动信息设备分类 1.1.2 Open Handset Alliance和 Android 1.2 Android简介 ...13.3 俄罗斯方块游戏功能实现 13.4 俄罗斯方块游戏演示

Global site tag (gtag.js) - Google Analytics