博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android应用更新自动检测下载
阅读量:6199 次
发布时间:2019-06-21

本文共 12305 字,大约阅读时间需要 41 分钟。

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

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

1 
2
2
3
baidu_xinwen_1.1.0
4
http://gdown.baidu.com/data/wisegame/f98d235e39e29031/baiduxinwen.apk
5

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

1 public class ParseXmlService 2 { 3     public HashMap
parseXml(InputStream inStream) throws Exception 4 { 5 HashMap
hashMap = new HashMap
(); 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     try11     {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。把获取 到的手机上应用版本与服务器端的版本进行比较,应用就可以判断处是否需要更新软件。

处理流程

Android应用更新自动检测下载

处理代码

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
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 * @return100 */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 try110 {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 context132 * @return133 */134 private int getVersionCode(Context context)135 {136 int versionCode = 0;137 try138 {139 // 获取软件版本号,对应AndroidManifest.xml下android:versionCode140 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 @Override161 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 @Override172 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 @Override198 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 coolszy224 *@date 2012-4-26225 *@blog http://blog.92coding.com226 */227 private class downloadApkThread extends Thread228 {229 @Override230 public void run()231 {232 try233 {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 do262 {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 }

效果图

Android应用更新自动检测下载

Android应用更新自动检测下载

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

Android应用更新自动检测下载

参考代码下载:

 

转载地址:http://zdtca.baihongyu.com/

你可能感兴趣的文章
模拟光链路 动态范围
查看>>
20天时间,一个人怎么搞定这个后台管理项目
查看>>
go并发基础数据加锁解锁
查看>>
6-SpringIOC原理
查看>>
北大教授邱泽奇:农村电商,为什么是菏泽?
查看>>
黄仁勋打响CES第一枪:全球最强芯DRIVE Xavier武装自动驾驶
查看>>
Tengine TLSv1.3最佳实践
查看>>
利用redis缓存对 list集合中的数据 进行分页操作
查看>>
云效(原RDC)如何构建一个基于Maven的Java项目
查看>>
RabbitMQ消息反序列化失败问题回顾
查看>>
Oracle 中实现查找树形结构节点功能
查看>>
aliyun 搭建redis集群
查看>>
java算法-二维极点算法
查看>>
总结-HttpClient-RetryHandler重试
查看>>
Java回调机制如何理解?
查看>>
mybatis mapper里面>= ,<=转义
查看>>
Android实时监听网络状态
查看>>
9.2 grep(中)
查看>>
11.32 php扩展模块装安装
查看>>
Java内存分析
查看>>