Android应用升级,检测更新,下载,检验,安装

应用升级大致步骤:

  1. 检测是否有更新(读取服务器config文件,比对版本号)
  2. 若发现高版本则读取更新文件updateinfo.xml获取下载更新相关信息
  3. 校验信息确认升级后,下载apk
  4. 下载完apk后,进行MD5检验apk的完整性
  5. 安装apk

升级入口

	private void upgrade() {
		//需要访问网络,避免主线程堵塞
		new Thread(){
			public void run() {
				if(checkUpdate()){//检查更新
					handler.sendEmptyMessage(20);//通知界面提示有版本更新
				}
			};
		}.start();
	}

	private boolean checkUpdate(){

		String url = PATH_SERVER + "upgrade/config";

		//从config文件读取Version信息,和UpdateInfo.xml文件地址
		try {
			updateInfoMap = ParseUpdateFile.getConfigInfo(url);
		} catch (Exception e) {
			e.printStackTrace();
		}

		//获取当前apk的版本号
		PackageInfo packageInfo = null;
		try {
			packageInfo = MainActivity.this.getPackageManager().getPackageInfo(MainActivity.this.getPackageName(), 0);
		} catch (Exception e) {
			e.printStackTrace();
		}

		int updateVCode = Integer.valueOf(updateInfoMap.get("Version"));

		//服务器端apk版本高于现在的版本,则读取updateinfo.xml文件
		if(updateVCode > packageInfo.versionCode){

			url = PATH_SERVER+"upgrade/updateinfo.xml";

			try {
				updateInfoMap.putAll(ParseXmlUtil.parseXml(url));
			} catch (Exception e) {
				e.printStackTrace();
			}

			//输出读取结果
			Set<String> set = updateInfoMap.keySet();
			System.out.println("map.size():"+updateInfoMap.size());
			for (Iterator<String> iterator = set.iterator(); iterator.hasNext();) {
				String string = (String) iterator.next();
				System.out.println(string + "——>" + updateInfoMap.get(string));
			}
			//检查信息合法性,通过则发送可更新消息
			return checkUpdateInfo(updateInfoMap);
		}
		return false;
	}

解析config文件

	public static Map<String,String> getConfigInfo(String strURL) throws Exception {
		Map<String,String> configMap = new HashMap<String, String>();

		URL url = new URL(strURL);
		URLConnection conn = url.openConnection();
		if (conn == null) {
			return configMap;
		}
		InputStream inputStream = conn.getInputStream();
		InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
		BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
		String str = null;
		while (null != (str=bufferedReader.readLine())) {

			if (str != null) {

				if (str.contains("Version=")) {
					configMap.put("Version", str.substring(str.indexOf("=")+1));
				}
				if (str.contains("VersionServer")) {
					configMap.put("VersionServer", str.substring(str.indexOf("::")+2));
				}
			}

		}
		bufferedReader.close();
		return configMap;
	}

checkUpdateInfo()主要校验信息的合法性

	private boolean checkUpdateInfo(Map<String, String> updateInfoMap){

		String downloadPath = updateInfoMap.get("DownloadPath");
		String packageName = updateInfoMap.get("packageName");
		String versionCode = updateInfoMap.get("versionCode");
		String updateVCode = updateInfoMap.get("Version");

		if (checkUrl(downloadPath)//检测是否可访问
				&& versionCode.equals(updateVCode)//config和updateinfoxml文件中版本号是否一致
				&& packageName.equals(getPackageName())) {//包名
			return true;
		}
		return false;
	}

下载文件到设备需要权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
	private void downLoadAPK(){

		new Thread() {
			public void run() {

				String downLoadPath = updateInfoMap.get("DownloadPath");
				String downLoadDir = "/acfg/";

				File fileDir = new File(downLoadDir);
				if (!fileDir.exists()) {
					fileDir.mkdir();
				}

				String fileName = downLoadDir + downLoadPath.substring(downLoadPath.lastIndexOf("/")+1);

				File file = new File(fileName);
				if (file.exists()) {
					file.delete();
				}

				try {
					file.createNewFile();
					// 构造URL
					URL url = new URL(downLoadPath);
					// 打开连接
					URLConnection con = url.openConnection();
					// 获得文件的长度
					int contentLength = con.getContentLength();
					System.out.println("长度 :" + contentLength);
					// 输入流
					InputStream is = con.getInputStream();
					// 1K的数据缓冲
					byte[] bs = new byte[1024];
					// 读取到的数据长度
					int len;
					// 输出的文件流
					OutputStream os = new FileOutputStream(fileName);
					// 开始读取
					while ((len = is.read(bs)) != -1) {
						os.write(bs, 0, len);
					}
					// 完毕,关闭所有链接
					os.close();
					is.close();

					updateInfoMap.put("fileName", fileName);

				} catch (Exception e) {
					e.printStackTrace();
					handler.sendEmptyMessage(22);
				}
				handler.sendEmptyMessage(21);//通知界面下载完成
			};

		}.start();

	}

下载完成后核对apk的MD5值

File file = new File(fileName);
String fileMD5 = MD5Util.getMD5OfFile(file);

if (fileMD5.equals(activity.updateInfoMap.get("md5sum"))) {
    Toast.makeText(activity, "Download Finished. It‘s ready to update!", Toast.LENGTH_LONG).show();
    activity.update(fileName);
}

获取文件的MD5值

        public static String getMD5OfFile(File file) {
		String value = null;
		FileInputStream in = null;
		try {
			in = new FileInputStream(file);
			MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			md5.update(byteBuffer);
			BigInteger bi = new BigInteger(1, md5.digest());
			value = bi.toString(16).toUpperCase(Locale.ENGLISH);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (null != in) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return value;
	}

安装下载好的apk

	private void update(String filePath) {
	    Intent intent = new Intent(Intent.ACTION_VIEW);
	    intent.setDataAndType(Uri.fromFile(new File(filePath)), "application/vnd.android.package-archive");
	    startActivity(intent);
	}

安装完成后进入应用

时间: 2024-10-14 00:50:41

Android应用升级,检测更新,下载,检验,安装的相关文章

Android程序版本更新--通知栏更新下载安装(转)

Android应用检查版本更新后,在通知栏下载,更新下载进度,下载完成自动安装,效果图如下: 检查当前版本号 AndroidManifest文件中的versionCode用来标识版本,在服务器放一个新版本的apk,versioncode大于当前版本,下面代码用来获取versioncode的值 PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); int

Android Studio系列教程一--下载与安装

Android Studio系列教程一--下载与安装 背景 相信大家对Android Studio已经不陌生了,Android Studio是Google于2013 I/O大会针对Android开发推出的新的开发工具,目前很多开源项目都已经在采用,Google的更新速度也很快,明显能感觉到这是Android开发的未来,那么我们还有什么理由不去拥抱未来呢? 虽然推出了很久,但是国内貌似普及的程度并不高,鉴于很多朋友求studio的详细教程,那么今天我就手把手教大家下载.安装.使用,Studio之路

史上最详细的Android Studio系列教程一--下载和安装

链接地址:http://segmentfault.com/a/1190000002401964#articleHeader4 原文链接:http://stormzhang.com/devtools/2014/11/25/android-studio-tutorial1/ 背景 相信大家对Android Studio已经不陌生了,Android Studio是Google于2013 I/O大会针对Android开发推出的新的开发工具,目前很多开源项目都已经在采用,Google的更新速度也很快,明显

【转】Android Studio系列教程一--下载与安装

原文网址:http://stormzhang.com/devtools/2014/11/25/android-studio-tutorial1/ 背景 相信大家对Android Studio已经不陌生了,Android Studio是Google于2013 I/O大会针对Android开发推出的新的开发工具,目前很多开源项目都已经在采用,Google的更新速度也很快,明显能感觉到这是Android开发的未来,那么我们还有什么理由不去拥抱未来呢? 虽然推出了很久,但是国内貌似普及的程度并不高,鉴于

(转)Android Studio系列教程一下载与安装 背景Android Studio VS Eclipse准备下载创建HelloWorld项目

背景 相信大家对Android Studio已经不陌生了,Android Studio是Google于2013 I/O大会针对Android开发推出的新的开发工具,目前很多开源项目都已经在采用,Google的更新速度也很快,明显能感觉到这是Android开发的未来,那么我们还有什么理由不去拥抱未来呢? 虽然推出了很久,但是国内貌似普及的程度并不高,鉴于很多朋友求studio的详细教程,那么今天我就手把手教大家下载.安装.使用,Studio之路从这里开始. Android Studio VS Ec

Android App内检测更新新版本APK

Rayland主板虽然作为一块基于Android的工控板,但是很多设备厂商并不想让用户看到Android系统信息.所以APK默认设置为开机启动项.img去除了Android头部和底部菜单.但是随之带来了APK更新的问题,传统的插入u盘,sd卡手动安装新版本APK的方式已经不够用了.所以我们需要点自动的东西. App内检测更新新版本APK 检测新版本APK 我们使用 四大组件之一的BroadcastReceiver来检测 sd卡或是u盘设备的接入. public class StorageMoun

Android开发平台Android Studio学习之一(下载及安装)

偶然所得,除了配置好的Eclipse平台可以开发做Android开发,google又推出了专门用以开发Android程序的平台--Android Studio. Android Studio的优势是:不需要手动配置SDK和AVD Manager,就是说它已经集成了Android 的SDK和虚拟机管理 器,只要你电脑上配置好了JDK,就可以直接开发了. 1简介 Android Studio 是一个全新的 Android 开发环境,基于IntelliJ IDEA. 类似 Eclipse ADT,An

Android SDK Manage 无法更新下载内容

启用 Android SDK Manager 更新内容的时候,Log Window 会显示“Download interrupted: peer not authenticated”,就知道肯定是被墙了,解决方法: 1.启动 Android SDK Manager: 2.打开主界面,打开设置窗口,在「HTTP Proxy Server」和「HTTP Proxy Port」输入框内填入mirrors.neusoft.edu.cn(如个别内容无法下载请使用203.208.46.146)和80,并且选

Android Studio设置代理更新下载SDK

代理主机和端口号按下图设置即可,便可以轻松的下载更新SDK啦~~~

IIS7上设置MIME让其支持android和Iphone的更新下载

Android APP的MIME: 文件扩展名:.apk MIME类型:application/vnd.android.package-archive iPhone APP的MIME: 文件扩展名:.ipa MIME类型:application/octet-stream.ipa