溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Android應(yīng)用升級(jí),檢測(cè)更新,下載,檢驗(yàn),安裝

發(fā)布時(shí)間:2020-06-19 04:30:07 來(lái)源:網(wǎng)絡(luò) 閱讀:6024 作者:年少的風(fēng) 欄目:移動(dòng)開(kāi)發(fā)

應(yīng)用升級(jí)大致步驟:

  1. 檢測(cè)是否有更新(讀取服務(wù)器config文件,比對(duì)版本號(hào))

  2. 若發(fā)現(xiàn)高版本則讀取更新文件updateinfo.xml獲取下載更新相關(guān)信息

  3. 校驗(yàn)信息確認(rèn)升級(jí)后,下載apk

  4. 下載完apk后,進(jìn)行MD5檢驗(yàn)apk的完整性

  5. 安裝apk



升級(jí)入口

	private void upgrade() {
		//需要訪問(wèn)網(wǎng)絡(luò),避免主線程堵塞
		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();
		}

		//獲取當(dāng)前apk的版本號(hào)
		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"));
		
		//服務(wù)器端apk版本高于現(xiàn)在的版本,則讀取updateinfo.xml文件
		if(updateVCode > packageInfo.versionCode){
			
			url = PATH_SERVER+"upgrade/updateinfo.xml";
			
			try {
				updateInfoMap.putAll(ParseXmlUtil.parseXml(url));
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			//輸出讀取結(jié)果
			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));
			}
			//檢查信息合法性,通過(guò)則發(fā)送可更新消息
			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()主要校驗(yàn)信息的合法性

	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)//檢測(cè)是否可訪問(wèn)
				&& versionCode.equals(updateVCode)//config和updateinfoxml文件中版本號(hào)是否一致
				&& packageName.equals(getPackageName())) {//包名
			return true;
		}
		return false;
	}


下載文件到設(shè)備需要權(quán)限

<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();//創(chuàng)建文件夾
				}
				
				String fileName = downLoadDir + downLoadPath.substring(downLoadPath.lastIndexOf("/")+1);
				
				File file = new File(fileName);
				if (file.exists()) {
					file.delete();//先刪除之前已存在的文件
				}
				
				try {
					file.createNewFile();
					
					URL url = new URL(downLoadPath);// 構(gòu)造URL
					
					URLConnection con = url.openConnection();// 打開(kāi)連接
					
					int contentLength = con.getContentLength();// 獲得文件的長(zhǎng)度
					System.out.println("長(zhǎng)度 :" + contentLength);
					
					InputStream is = con.getInputStream();// 輸入流
					
					byte[] bs = new byte[1024];// 1K的數(shù)據(jù)緩沖
					
					int len;// 讀取到的數(shù)據(jù)長(zhǎng)度
					
					OutputStream os = new FileOutputStream(fileName);// 輸出的文件流
					// 開(kāi)始讀取
					while ((len = is.read(bs)) != -1) {
						os.write(bs, 0, len);
					}
					
					// 完畢,關(guān)閉所有鏈接
					os.close();
					is.close();
					
					//保存文件路徑,方便升級(jí)時(shí)使用
					updateInfoMap.put("fileName", fileName);
					
				} catch (Exception e) {
					e.printStackTrace();
					handler.sendEmptyMessage(22);//下載失敗
				}
				handler.sendEmptyMessage(21);//通知界面下載完成
			};

		}.start();
		
	}


下載完成后核對(duì)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);//轉(zhuǎn)為大寫(xiě)
		} 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);
	}

安裝時(shí)會(huì)提示“解析包時(shí)出現(xiàn)問(wèn)題”,經(jīng)過(guò)測(cè)試發(fā)現(xiàn)是下載到設(shè)備的apk文件的權(quán)限問(wèn)題

故而在安裝前先修改apk的權(quán)限

	private void update(String filePath) {
		
		String cmd = "chmod 755 " + filePath;
		try {
			Runtime.getRuntime().exec(cmd);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	    Intent intent = new Intent(Intent.ACTION_VIEW);
	    intent.setDataAndType(Uri.fromFile(new File(filePath)), "application/vnd.android.package-archive");
	    startActivity(intent);
	}

安裝完成后進(jìn)入應(yīng)用

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI