原博客地址: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);
}
}
}