Tinker gradle plugin tinkerPatchRelease

分析命令行里面调用tinkerPatchRelease过程

1、 tinker-sample-android 中build.gradle

if (buildWithTinker()) {
    apply plugin: 'com.tencent.tinker.patch'

2、tinker-patch-gradle-plugin 中 TinkerPatchPlugin.groovy

执行 TinkerPatchPlugin.apply(Project project)

TinkerPatchSchemaTask tinkerPatchBuildTask = mProject.tasks.create("tinkerPatch${variantName}", TinkerPatchSchemaTask)

tinkerPatchBuildTask.signConfig = variantData.variantConfiguration.signingConfig

variant.outputs.each { output ->
    setPatchNewApkPath(configuration, output, variant, tinkerPatchBuildTask)
    setPatchOutputFolder(configuration, output, variant, tinkerPatchBuildTask)
}

3、TinkerPatchSchemaTask.groovy 

配置上一个apk路径、新的apk构建路径
builder.setOldApk(configuration.oldApk)
       .setNewApk(buildApkPath)
       .setOutBuilder(outputFolder)
       .setIgnoreWarning(configuration.ignoreWarning)
       .setAllowLoaderInAnyDex(configuration.allowLoaderInAnyDex)
       .setRemoveLoaderForAllDex(configuration.removeLoaderForAllDex)
       .setDexFilePattern(new ArrayList<String>(configuration.dex.pattern))
       .setIsProtectedApp(configuration.buildConfig.isProtectedApp)
       .setIsComponentHotplugSupported(configuration.buildConfig.supportHotplugComponent)
       .setDexLoaderPattern(new ArrayList<String>(configuration.dex.loader))
       .setDexIgnoreWarningLoaderPattern(new ArrayList<String>(configuration.dex.ignoreWarningLoader))
       .setDexMode(configuration.dex.dexMode)
       .setSoFilePattern(new ArrayList<String>(configuration.lib.pattern))
       .setResourceFilePattern(new ArrayList<String>(configuration.res.pattern))
       .setResourceIgnoreChangePattern(new ArrayList<String>(configuration.res.ignoreChange))
       .setResourceIgnoreChangeWarningPattern(new ArrayList<String>(configuration.res.ignoreChangeWarning))
       .setResourceLargeModSize(configuration.res.largeModSize)
       .setUseApplyResource(configuration.buildConfig.usingResourceMapping)
       .setConfigFields(new HashMap<String, String>(configuration.packageConfig.getFields()))
       .setSevenZipPath(configuration.sevenZip.path)
       .setUseSign(configuration.useSign)

InputParam inputParam = builder.create()
Runner.gradleRun(inputParam);

4、tinker-patch-lib Runner.java 来到了java的世界

protected void tinkerPatch() {
    Logger.d("-----------------------Tinker patch begin-----------------------");

    Logger.d(config.toString());
    try {
        //gen patch
        ApkDecoder decoder = new ApkDecoder(config);
        decoder.onAllPatchesStart();
        decoder.patch(config.mOldApkFile, config.mNewApkFile);
        decoder.onAllPatchesEnd();

        //gen meta file and version file
        PatchInfo info = new PatchInfo(config);
        info.gen();

        //build patch
        PatchBuilder builder = new PatchBuilder(config);
        builder.buildPatch();

    } catch (Throwable e) {
        e.printStackTrace();
        goToError();
    }

    Logger.d("Tinker patch done, total time cost: %fs", diffTimeFromBegin());
    Logger.d("Tinker patch done, you can go to file to find the output %s", config.mOutFolder);
    Logger.d("-----------------------Tinker patch end-------------------------");
}

5、decoder.patch(config.mOldApkFile, config.mNewApkFile);

public boolean patch(File oldFile, File newFile) throws Exception {
    writeToLogFile(oldFile, newFile);
    //check manifest change first
    manifestDecoder.patch(oldFile, newFile);

    unzipApkFiles(oldFile, newFile);

    Files.walkFileTree(mNewApkDir.toPath(), new ApkFilesVisitor(config, mNewApkDir.toPath(), mOldApkDir.toPath(), dexPatchDecoder, soPatchDecoder, resPatchDecoder));

    // get all duplicate resource file
    for (File duplicateRes : resDuplicateFiles) {
        // resPatchDecoder.patch(duplicateRes, null);
        Logger.e("Warning: res file %s is also match at dex or library pattern, "
            + "we treat it as unchanged in the new resource_out.zip", getRelativePathStringToOldFile(duplicateRes));
    }

    soPatchDecoder.onAllPatchesEnd();
    dexPatchDecoder.onAllPatchesEnd();
    manifestDecoder.onAllPatchesEnd();
    resPatchDecoder.onAllPatchesEnd();

    //clean resources
    dexPatchDecoder.clean();
    soPatchDecoder.clean();
    resPatchDecoder.clean();
    return true;
}

6、跟踪dex patch 来到 ApkFilesVisitor  ApkDecoder.java

Files.walkFileTree(mNewApkDir.toPath(), new ApkFilesVisitor(config, mNewApkDir.toPath(), mOldApkDir.toPath(), dexPatchDecoder, soPatchDecoder, resPatchDecoder));

@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {

    Path relativePath = newApkPath.relativize(file);

    Path oldPath = oldApkPath.resolve(relativePath);

    File oldFile = null;
    //is a new file?!
    if (oldPath.toFile().exists()) {
        oldFile = oldPath.toFile();
    }
    String patternKey = relativePath.toString().replace("\\", "/");

    if (Utils.checkFileInPattern(config.mDexFilePattern, patternKey)) {
        //also treat duplicate file as unchanged
        if (Utils.checkFileInPattern(config.mResFilePattern, patternKey) && oldFile != null) {
            resDuplicateFiles.add(oldFile);
        }

        try {
            dexDecoder.patch(oldFile, file.toFile());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return FileVisitResult.CONTINUE;
    }
    if (Utils.checkFileInPattern(config.mSoFilePattern, patternKey)) {
        //also treat duplicate file as unchanged
        if (Utils.checkFileInPattern(config.mResFilePattern, patternKey) && oldFile != null) {
            resDuplicateFiles.add(oldFile);
        }
        try {
            soDecoder.patch(oldFile, file.toFile());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return FileVisitResult.CONTINUE;
    }

7、分别进行 soDecoder.patch(oldFile, file.toFile());   dexDecoder.patch(oldFile, file.toFile()); resDecoder.patch(oldFile, file.toFile());

public ApkDecoder(Configuration config) throws IOException {
    super(config);
    this.mNewApkDir = config.mTempUnzipNewDir;
    this.mOldApkDir = config.mTempUnzipOldDir;

    this.manifestDecoder = new ManifestDecoder(config);

    //put meta files in assets
    String prePath = TypedValue.FILE_ASSETS + File.separator;
    dexPatchDecoder = new UniqueDexDiffDecoder(config, prePath + TypedValue.DEX_META_FILE, TypedValue.DEX_LOG_FILE);
    soPatchDecoder = new BsDiffDecoder(config, prePath + TypedValue.SO_META_FILE, TypedValue.SO_LOG_FILE);
    resPatchDecoder = new ResDiffDecoder(config, prePath + TypedValue.RES_META_TXT, TypedValue.RES_LOG_FILE);
    resDuplicateFiles = new ArrayList<>();
}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值