gradle android:后期处理APK

时间:2014-03-25 23:39:53

标签: android gradle android-gradle build.gradle

我需要通过添加第二个签名来后处理我的APK,所以我试图了解如何在此时挂钩构建过程。我的第一次尝试,

task doubleSign {
  if (signing.androidBuildExists) {
    android.buildTypes.all { type ->
      tasks.("assemble${type.name.capitalize()}").finalizedBy doDoubleSign
    }
  }
}
好的,好的。但是如果执行了任何install*任务,那么令我惊讶的是,assemble*不在依赖关系树中。所以接下来我尝试添加这一行,

tasks.("install${type.name.capitalize()}").dependsOn doDoubleSign
然而,gradle告诉我任务不存在!

> Could not find property 'installDebug' on task set.

感谢。

编辑:添加完整的解决方案以供参考。

class DoubleSign extends DefaultTask {
  DoubleSign() {
    outputs.upToDateWhen { false }
  }

  File signScript = new File(project.androidBuild + '/sign.sh')

  File inputFile
  File keystore;

  @TaskAction
  void sign() {
    List<String> args = new ArrayList<String>();
    args.add(signScript.toString());
    args.add(inputFile.toString());
    args.add(keystore.toString());


    Process process = new ProcessBuilder(args).redirectErrorStream(true).start();
    BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
    String line;
    while ((line = input.readLine()) != null) {
      System.out.println(line);
    }
    input.close();
  }
}

...

afterEvaluate {
  android.applicationVariants.all { variant ->
    println "outputFile=" + variant.outputFile
    if (variant.name.equals("debug")) {
        // only do for debug builds
        def signingTask = tasks.create(name: "double${variant.name.capitalize()}Sign", type: DoubleSign)
        signingTask.inputFile = new File(variant.outputFile.toString().replace(".apk", "-unaligned.apk"))
        signingTask.keystore = new File(project.androidBuild + '/keystore.jks')

        signingTask.dependsOn variant.packageApplication
        variant.zipAlign.dependsOn signingTask
    }
  }
}

2 个答案:

答案 0 :(得分:4)

执行该代码时,

installDebug将不存在,因为android插件会在afterEvaluate阶段创建其任务。

你应该做什么:

android {
  applicationVariants.all { variant ->
    if (!variant.isSigningReady()) {
      // only add double signing on variants that are signed with
      // default signing method.
      return
    }

    // get output file
    def outputFile = variant.outputFile

    // add new signing task.
    def signingTask = project.tasks.create("double${variant.name}Sign", MyCustomSigning)
    // configure task
    signingTask.inputFile = outputFile
    // create the final apk name using baseName to guarantee it's unique.
    signingTask.outputFile = new File(project.buildDir, "apks/${project.name}-${variant.baseName}-2sign.apk")

    // configure the task to be run after the default signing task.
    signingTask.dependsOn variant.packageApplication

    // configure zip align task to use the output of the 2nd signing task,
    // and also to run after 2nd signing task.
    variant.zipAlign.inputFile = signingTask.outputFile
    variant.zipAlign.dependsOn signingTask
  }
}

请注意,如果您没有运行zipalign(但实际上您应该),则必须调整结束以使variant.assemble取决于您的签名任务,并将签名任务的输出设置为{ {1}}以便从命令行或IDE部署仍然有效。

对于实际签名,您将使用注释执行自定义任务,以便仅在输入文件实际更改时才会运行。

variant.outputFile

答案 1 :(得分:0)

尽管这个问题已经得到解答,但我想分享最适合我的解决方案。

我需要的只是一个合适的钩子来后处理一个完全完成的apk。为此我使用了钩子“assemble.doLast”:

android {
    /* ... */

    applicationVariants.all { variant ->
        variant.assemble.doLast {
            variant.outputs.each { output ->
                File apk = output.outputFile
                // Post process apk
            }
        }
    }
}