Android 生成差分包
阿新 • • 發佈:2019-02-13
原部落格地址:http://blog.csdn.net/u013705351/article/details/22722499
如果沒用增量升級,我們的升級流程是這樣的:
1、打包好apk上傳到伺服器,設定apk版本
2、客戶端發現伺服器端有高版本apk。
3、直接下載最新版本apk提示安裝
這個過程中,在伺服器端只是儲存一個歷史版本的記錄,這樣的確也簡單。
但是直接下載apk,發現有個問題就是apk很大的時候,下載的時間比較長,所以才會有了查分升級
如果採用查分升級,我們的升級流程就變成這樣了:
1、打包好apk上傳至伺服器,設定版本號。
2、對所有舊版本都生成對應的patch(差分)檔案,如果上傳之前已經有n個版本,要對這n個版本都要生成差分包
3、客戶端發現服務端有高版本apk。
4、客戶端通過當前版本找到對應的patch檔案下載。
5、客戶端對patch檔案和舊的apk進行合併。
6、合併之後提示安裝
package redis; import java.io.BufferedOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.security.MessageDigest; import com.nothome.delta.Delta; import com.nothome.delta.DiffWriter; import com.nothome.delta.GDiffPatcher; import com.nothome.delta.GDiffWriter; public class DiffTool { private final static char[] hexChar = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; private static String toHexString(byte[] b) { StringBuilder sb = new StringBuilder(b.length * 2); for (int i = 0; i < b.length; i++) { sb.append(hexChar[((b[i] & 0xF0) >>> 4)]); sb.append(hexChar[(b[i] & 0xF)]); } return sb.toString(); } public static String getMD5(File file) { InputStream fis = null; String str = null; try { fis = new FileInputStream(file); byte[] buffer = new byte[1024]; MessageDigest md5 = MessageDigest.getInstance("MD5"); int numRead = 0; while ((numRead = fis.read(buffer)) > 0) { md5.update(buffer, 0, numRead); } str = toHexString(md5.digest()); } catch (Exception e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (Exception e) { } } } return str; } private static File mergeFile(final String source, final String patch, String target) throws Exception { GDiffPatcher patcher = new GDiffPatcher(); File deffFile = new File(patch); File updatedFile = new File(target); patcher.patch(new File(source), deffFile, updatedFile); return updatedFile; } public static File mergeApk(final String source, final String patch, final String target, String newApkMd5) throws Exception { File updateFile = mergeFile(source, patch, target); String ufpMd5 = getMD5(updateFile); System.out .println("服務端下發的md5:" + newApkMd5 + ",新合併後的apk MD5:" + ufpMd5); if (ufpMd5 == null || !newApkMd5.equalsIgnoreCase(ufpMd5)) { if (updateFile.exists()) { updateFile.delete(); } throw new Exception("MD5錯誤,不能成功合併!"); } return updateFile; } /** * 生成差分包:old_new.patch = diff(old.apk, old.apk) * * */ private static void createPatch(String oldApkName, String newApkName, String patchName) { System.out.println("開始生成差分包"); long start = System.currentTimeMillis(); try { File newApk = new File("Max1.0.1040.apk"); File oldApk = new File("Max1.0.0000.apk"); File patchFile = new File("old_new.patch"); DiffWriter output = null; output = new GDiffWriter(new DataOutputStream( new BufferedOutputStream(new FileOutputStream(patchFile)))); if (oldApk.length() > Integer.MAX_VALUE || newApk.length() > Integer.MAX_VALUE) { System.err .println("source or target is too large, max length is " + Integer.MAX_VALUE); System.err.println("aborting.."); } Delta d = new Delta(); d.compute(oldApk, newApk, output); System.out.println("差分包生成完成,完成耗時:" + (System.currentTimeMillis() - start) + "ms"); } catch (Exception e) { e.printStackTrace(); } } public static void main(String args[]) throws Exception { String newApkName = "Max1.0.1040.apk"; String oldApkName = "Max1.0.0000.apk"; String patchName = "old_new.patch"; String targetApkName = "new.apk"; try { createPatch(oldApkName, newApkName, patchName); String newApkMd5 = getMD5(new File(newApkName)); mergeApk(oldApkName, patchName, targetApkName, newApkMd5); } catch (Exception ioe) { // gls031504a System.err.println("error while patching: " + ioe); } } }