Android开发应用异步检查更新代码
16lz
2021-01-25
开发环境:android studio sdk 4.0及以上
场景:用户点击检查更新按钮进行检查服务器版本号,若有新版本则进行下载更新。异步检测版本号
1 package com.example.qurenwu.qurenwu_2.util; 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 import java.util.Map; 12 13 import android.app.AlertDialog; 14 import android.app.AlertDialog.Builder; 15 import android.app.Dialog; 16 import android.content.Context; 17 import android.content.DialogInterface; 18 import android.content.DialogInterface.OnClickListener; 19 import android.content.Intent; 20 import android.content.pm.PackageManager; 21 import android.content.pm.PackageManager.NameNotFoundException; 22 import android.net.Uri; 23 import android.os.Environment; 24 import android.os.Handler; 25 import android.os.Message; 26 import android.util.Log; 27 import android.view.LayoutInflater; 28 import android.view.View; 29 import android.widget.ProgressBar; 30 import android.widget.Toast; 31 32 import com.example.qurenwu.qurenwu_2.R; 33 import com.example.qurenwu.qurenwu_2.custom.GotaskGlobalVal; 34 35 import org.w3c.dom.Document; 36 import org.w3c.dom.Element; 37 import org.w3c.dom.Node; 38 import org.w3c.dom.NodeList; 39 40 import javax.xml.parsers.DocumentBuilder; 41 import javax.xml.parsers.DocumentBuilderFactory; 42 43 /** 44 * Created by Administrator on 2014/12/3. 45 */ 46 public class UpdateManager { 47 GotaskGlobalVal globalVal; //全局 48 /* 下载中 */ 49 private static final int DOWNLOAD = 1; 50 /* 下载结束 */ 51 private static final int DOWNLOAD_FINISH = 2; 52 /*检查是否有更新*/ 53 private static final int CHECK_APK_VERSION= 3; 54 /* 保存解析的XML信息 */ 55 HashMap<String, String> mHashMap; 56 /* 下载保存路径 */ 57 private String mSavePath; 58 /* 记录进度条数量 */ 59 private int progress; 60 /* 是否取消更新 */ 61 private boolean cancelUpdate = false; 62 63 private Context mContext; 64 65 private int mFlag; // 0:自启动检测 1:手动检测,区别在于前者若无更新则不提示,后者若无更新需要提示 66 /* 更新进度条 */ 67 private ProgressBar mProgress; 68 private Dialog mDownloadDialog; 69 70 private Handler mHandler = new Handler() 71 { 72 public void handleMessage(Message msg) 73 { 74 switch (msg.what) 75 { 76 // 正在下载 77 case DOWNLOAD: 78 // 设置进度条位置 79 mProgress.setProgress(progress); 80 break; 81 case DOWNLOAD_FINISH: 82 // 安装文件 83 installApk(); 84 break; 85 case CHECK_APK_VERSION: //检查版本更新 86 mHashMap = (HashMap<String,String>)msg.obj; 87 // 获取当前软件版本 88 int versionCode = getVersionCode(mContext); 89 if (null != mHashMap) 90 { 91 int serviceCode = Integer.valueOf(mHashMap.get("version")); 92 // 版本判断 93 Log.v("isUpdate","serviceCode:"+serviceCode+";versionCode:"+versionCode); 94 if (serviceCode > versionCode) 95 { 96 //需要更新 97 showNoticeDialog(); 98 } 99 else100 {101 if(mFlag == 1)102 {Toast.makeText(mContext, R.string.soft_update_no, Toast.LENGTH_LONG).show();}103 }104 }105 break;106 default:107 break;108 }109 };110 };111 112 public UpdateManager(Context context)113 {114 this.mContext = context;115 globalVal = (GotaskGlobalVal)context.getApplicationContext();116 mFlag = 0;117 }118 119 /**120 * 检测软件更新121 * @param flag 0:启动时检测 1:手动检测,区别在于前者若无更新则不提示,后者若无更新需要提示122 */123 public void checkUpdate(int flag)124 {125 mFlag = flag;126 CheckVersionHttpThread checkthread = new CheckVersionHttpThread(mHandler,CHECK_APK_VERSION);127 new Thread(checkthread).start();128 }129 /**130 * 检查软件是否有更新版本131 *132 * @return133 */134 private boolean isUpdate()135 {136 // 获取当前软件版本137 int versionCode = getVersionCode(mContext);138 // 把version.xml放到网络上,然后获取文件信息139 //InputStream inStream = ParseXmlService.class.getClassLoader().getResourceAsStream("version.xml");140 // 解析XML文件。 由于XML文件比较小,因此使用DOM方式进行解析141 ParseXmlService service = new ParseXmlService();142 try143 {144 //String path = "http://192.168.1.146:8080/picweb/xml/version.xml";145 String path = globalVal.BASE_URL+"/xml/version.xml";146 URL url = new URL(path);147 HttpURLConnection conn = (HttpURLConnection)url.openConnection();148 conn.setReadTimeout(5*1000);149 conn.setRequestMethod("GET");150 InputStream inStream = conn.getInputStream();151 mHashMap = service.parseXml(inStream);152 } catch (Exception e)153 {154 e.printStackTrace();155 }156 if (null != mHashMap)157 {158 int serviceCode = Integer.valueOf(mHashMap.get("version"));159 // 版本判断160 Log.v("isUpdate","serviceCode:"+serviceCode+";versionCode:"+versionCode);161 if (serviceCode > versionCode)162 {163 return true;164 }165 }166 return false;167 }168 169 /**170 * 获取软件版本号171 *172 * @param context173 * @return174 */175 private int getVersionCode(Context context)176 {177 int versionCode = 0;178 try179 {180 // 获取软件版本号,对应AndroidManifest.xml下android:versionCode181 versionCode = context.getPackageManager().getPackageInfo("com.example.qurenwu.qurenwu_2", 0).versionCode;182 } catch (PackageManager.NameNotFoundException e)183 {184 e.printStackTrace();185 }186 return versionCode;187 }188 189 /**190 * 显示软件更新对话框191 */192 private void showNoticeDialog()193 {194 // 构造对话框195 AlertDialog.Builder builder = new Builder(mContext);196 builder.setTitle(R.string.soft_update_title);197 builder.setMessage(R.string.soft_update_info);198 // 更新199 builder.setPositiveButton(R.string.soft_update_updatebtn, new OnClickListener()200 {201 @Override202 public void onClick(DialogInterface dialog, int which)203 {204 dialog.dismiss();205 // 显示下载对话框206 showDownloadDialog();207 }208 });209 // 稍后更新210 builder.setNegativeButton(R.string.soft_update_later, new OnClickListener()211 {212 @Override213 public void onClick(DialogInterface dialog, int which)214 {215 dialog.dismiss();216 }217 });218 Dialog noticeDialog = builder.create();219 noticeDialog.show();220 }221 222 /**223 * 显示软件下载对话框224 */225 private void showDownloadDialog()226 {227 // 构造软件下载对话框228 AlertDialog.Builder builder = new Builder(mContext);229 builder.setTitle(R.string.soft_updating);230 // 给下载对话框增加进度条231 final LayoutInflater inflater = LayoutInflater.from(mContext);232 View v = inflater.inflate(R.layout.softupdate_progress, null);233 mProgress = (ProgressBar) v.findViewById(R.id.update_progress);234 builder.setView(v);235 // 取消更新236 builder.setNegativeButton(R.string.soft_update_cancel, new OnClickListener()237 {238 @Override239 public void onClick(DialogInterface dialog, int which)240 {241 dialog.dismiss();242 // 设置取消状态243 cancelUpdate = true;244 }245 });246 mDownloadDialog = builder.create();247 mDownloadDialog.show();248 // 现在文件249 downloadApk();250 }251 252 /**253 * 下载apk文件254 */255 private void downloadApk()256 {257 // 启动新线程下载软件258 new downloadApkThread().start();259 }260 261 /**262 * 下载文件线程263 */264 private class downloadApkThread extends Thread265 {266 @Override267 public void run()268 {269 try270 {271 // 判断SD卡是否存在,并且是否具有读写权限272 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))273 {274 // 获得存储卡的路径275 String sdpath = Environment.getExternalStorageDirectory() + "/";276 mSavePath = sdpath + "download";277 URL url = new URL(mHashMap.get("url"));278 // 创建连接279 HttpURLConnection conn = (HttpURLConnection) url.openConnection();280 conn.connect();281 // 获取文件大小282 int length = conn.getContentLength();283 // 创建输入流284 InputStream is = conn.getInputStream();285 286 File file = new File(mSavePath);287 // 判断文件目录是否存在288 if (!file.exists())289 {290 file.mkdir();291 }292 File apkFile = new File(mSavePath, mHashMap.get("name"));293 FileOutputStream fos = new FileOutputStream(apkFile);294 int count = 0;295 // 缓存296 byte buf[] = new byte[1024];297 // 写入到文件中298 do299 {300 int numread = is.read(buf);301 count += numread;302 // 计算进度条位置303 progress = (int) (((float) count / length) * 100);304 // 更新进度305 mHandler.sendEmptyMessage(DOWNLOAD);306 if (numread <= 0)307 {308 // 下载完成309 mHandler.sendEmptyMessage(DOWNLOAD_FINISH);310 break;311 }312 // 写入文件313 fos.write(buf, 0, numread);314 } while (!cancelUpdate);// 点击取消就停止下载.315 fos.close();316 is.close();317 }318 } catch (MalformedURLException e)319 {320 e.printStackTrace();321 } catch (IOException e)322 {323 e.printStackTrace();324 }325 // 取消下载对话框显示326 mDownloadDialog.dismiss();327 }328 };329 330 /**331 * 安装APK文件332 */333 private void installApk()334 {335 File apkfile = new File(mSavePath, mHashMap.get("name"));336 if (!apkfile.exists())337 {338 return;339 }340 // 通过Intent安装APK文件341 Intent i = new Intent(Intent.ACTION_VIEW);342 i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");343 mContext.startActivity(i);344 }345 class ParseXmlService346 {347 public HashMap<String, String> parseXml(InputStream inStream) throws Exception348 {349 HashMap<String, String> hashMap = new HashMap<String, String>();350 351 // 实例化一个文档构建器工厂352 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();353 // 通过文档构建器工厂获取一个文档构建器354 DocumentBuilder builder = factory.newDocumentBuilder();355 // 通过文档通过文档构建器构建一个文档实例356 Document document = builder.parse(inStream);357 //获取XML文件根节点358 Element root = document.getDocumentElement();359 //获得所有子节点360 NodeList childNodes = root.getChildNodes();361 for (int j = 0; j < childNodes.getLength(); j++)362 {363 //遍历子节点364 Node childNode = (Node) childNodes.item(j);365 if (childNode.getNodeType() == Node.ELEMENT_NODE)366 {367 Element childElement = (Element) childNode;368 //版本号369 if ("version".equals(childElement.getNodeName()))370 {371 hashMap.put("version",childElement.getFirstChild().getNodeValue());372 }373 //软件名称374 else if (("name".equals(childElement.getNodeName())))375 {376 hashMap.put("name",childElement.getFirstChild().getNodeValue());377 }378 //下载地址379 else if (("url".equals(childElement.getNodeName())))380 {381 hashMap.put("url",childElement.getFirstChild().getNodeValue());382 }383 }384 }385 return hashMap;386 }387 }388 /**389 * 检测线程390 */391 class CheckVersionHttpThread implements Runnable{392 private Handler handler;393 int requestCode;394 /**395 * @param _handler396 * @param _requestCode 若一个activity有多个此请求,那么activity中的handle的msg .what也不同,用该字段区分397 */398 public CheckVersionHttpThread(Handler _handler,int _requestCode)399 {400 this.handler = _handler;401 this.requestCode = _requestCode;402 }403 @Override404 public void run() {405 HashMap<String, String> result= null;406 // 把version.xml放到网络上,然后获取文件信息407 //InputStream inStream = ParseXmlService.class.getClassLoader().getResourceAsStream("version.xml");408 // 解析XML文件。 由于XML文件比较小,因此使用DOM方式进行解析409 ParseXmlService service = new ParseXmlService();410 try411 {412 //String path = "http://192.168.1.146:8080/picweb/xml/version.xml";413 String path = globalVal.BASE_URL+"/xml/version.xml";414 URL url = new URL(path);415 HttpURLConnection conn = (HttpURLConnection)url.openConnection();416 conn.setReadTimeout(5*1000);417 conn.setRequestMethod("GET");418 InputStream inStream = conn.getInputStream();419 result = service.parseXml(inStream);420 } catch (Exception e)421 {422 e.printStackTrace();423 }424 Message msg = new Message();425 msg.what = requestCode;426 msg.obj = result;427 handler.sendMessage(msg);428 }429 }430 }
主界面中调用:
//检测新版本 UpdateManager manager = new UpdateManager(MyActivity.this);// 检查软件更新 manager.checkUpdate(0); //0:表示启动时检测 1:手动检测,区别在于前者若无更新则不提示,后者若无更新需要提示
mainfest.xml 中需要配置版本号
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.qurenwu.qurenwu_2" android:versionCode="1" android:versionName="1.0" >
string.xml需要增加字符串
<string name="soft_update_no">已经是最新版本</string> <string name="soft_update_title">软件更新</string> <string name="soft_update_info">检测到新版本,立即更新吗</string> <string name="soft_update_updatebtn">更新</string> <string name="soft_update_later">稍后更新</string> <string name="soft_updating">正在更新</string> <string name="soft_update_cancel">取消</string>
服务器端需要在目录如:http://192.168.11.1/xml/ 目录下增加文件 version.xml 内容如下:
<?xml version="1.0" encoding="UTF-8"?> <update> <version>1</version> <!-- 必须是整数 --> <name>gotask.1.0</name> <url>http://192.168.11.6/download/gotask.apk</url> </update>
ok! 大功告成!
更多相关文章
- 一款常用的 Squid 日志分析工具
- GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
- RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
- Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
- Android课堂练习——图文显示
- Android(安卓)xmlpull 方式解析xml文件
- android studio打包导出未签名apk
- Android文件上传与下载
- Android(安卓)Activity切换动画