Android 生成差分包

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

    }

}


         

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android OTA(Over-The-Air)升级是指通过无线网络(如Wi-Fi或移动数据网络)下载和安装设备的新软件版本。OTA更新可以让用户更加方便地获得软件更新,而不必手动下载和安装更新。 在 Android 中,OTA 更新是通过 OTA 更新实现的。OTA 更新是一个 ZIP 文件,其中含设备的完整系统映像。当设备收到更新通知时,系统会下载OTA 更新并在后台安装它。因为OTA 更新是非常大的,因此通常会提供差分,这些差分含新软件版本与旧软件版本之间的差异。 以下是Android OTA更新源码路径: - OTA更新系统框架代码:frameworks/base/services/core/java/com/android/server/ota/ - OTA更新应用代码:packages/apps/Updates/ 以下是Android OTA差分生成方法: - 使用repo 工具下载AOSP源代码,repo init 后,repo sync -j4 - 进入AOSP源代码根目录,执行 make otapackage 命令,如果想要加快编译速度,可以使用make -j4 otapackage 命令,其中 4 表示使用4个线程进行编译。 - 编译完成后,在 out/target/product/{device}/ 目录中会生成 OTA 更新,其中 {device} 表示设备名称。 如果需要生成差分,可以使用以下命令: ``` ./build/tools/releasetools/ota_from_target_files -k path_to_keys \ --block --backup=true target_files.zip fullota.zip ``` 其中,path_to_keys 是签名密钥的路径,target_files.zip 是完整的系统映像文件,fullota.zip 是已安装的旧版本系统映像文件。执行这个命令后,会生成一个差分,可以用于OTA升级。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值