android - 如何使用Android Gradle插件提供的Transform API?

标签 android gradle transform gradle-plugin

在将代码转换为 dex 文件之前,我使用 applicationVariants.dex.dependsOn 任务做了一些额外的工作,并且在 android gradle plugin 1.3 之前一切正常。但是从1.4开始,dex任务被禁止访问,会出现这样的错误提示: enter image description here

好的。我需要使用新的 Transform API 而不是 dex 任务。但问题是关于 Transform API 的文档真的很少。我能找到的是谷歌官方文档here , 但似乎不太好理解。

所以我尝试编写一个自定义转换,但我真的不知道我是否正确:

public class MyTransform extends Transform {

    @Override
    public String getName() {
        return "MyTransformImpl";
    }

    @Override
    public Set<QualifiedContent.ContentType> getInputTypes() {
        Set<QualifiedContent.ContentType> set = new HashSet<QualifiedContent.ContentType>();
        set.add(QualifiedContent.DefaultContentType.CLASSES);
        return set;
    }

    @Override
    public Set<QualifiedContent.Scope> getScopes() {
        Set<QualifiedContent.Scope> set = new HashSet<QualifiedContent.Scope>();
        set.add(QualifiedContent.Scope.PROJECT);
        return set;
    }

    @Override
    public boolean isIncremental() {
        return false;
    }

}

这是一个空的自定义转换。我没有添加转换逻辑,但这不是问题所在。 然后我使用我的 gradle 文件中记录的 api 注册了这个 Transform:

def transform = new MyTransform()
project.android.registerTransform(transform)

当我执行 assemble 任务时,我的自定义转换似乎有效。从正在执行的任务列表可以看出:

enter image description here

终于apk文件生成成功,一切正常。但是当我安装 apk 并启动应用程序时,它崩溃了。出现这样的错误:

enter image description here

这很奇怪。引发了 ClassNotFoundException,而我的 MainActivity 丢失了。怎么可能!然后我重新编译我的 apk 文件并在 jd-gui 中看到源代码,我完全糊涂了。

enter image description here

我的代码都不见了。仅保留支持库中的类。但实际上我的代码 .class 文件存在于 app/build/intermediates/classes/ 目录中。如果我在 gradle 中注释掉注册行:

// project.android.registerTransform(transform)

一切顺利。所以我想我写错了自定义转换,但我真的不知道如何写一个正确的。

有人能帮忙吗?衷心感谢。

最佳答案

当您实现Transform 时,您必须处理文件并将它们写入输出文件夹。即使您不处理类文件,您仍然必须将它们复制到输出文件夹。如果您不这样做,所有类文件都会被删除。

要使Transform 正常工作,您必须执行以下步骤。首先,您需要指定您的转换处理输入类文件并生成类文件。

  @Override
  Set<QualifiedContent.ContentType> getInputTypes() {
    return Collections.singleton(QualifiedContent.DefaultContentType.CLASSES)
  }

  @Override
  Set<QualifiedContent.ContentType> getOutputTypes() {
    return EnumSet.of(QualifiedContent.DefaultContentType.CLASSES)
  }

  @Override
  Set<QualifiedContent.Scope> getScopes() {
    return EnumSet.of(QualifiedContent.Scope.PROJECT)
  }

然后在 transform 方法中,您需要获取输入和输出文件夹。

final DirectoryInput directoryInput = inputs.first().directoryInputs.first()
final File input = directoryInput.file
final File output = outputProvider.getContentLocation(
    directoryInput.name, EnumSet.of(QualifiedContent.DefaultContentType.CLASSES),
    EnumSet.of(QualifiedContent.Scope.PROJECT), Format.DIRECTORY)

最后,您必须将所有文件从 input 复制到 output

这是一个 project实现了一个Transformation。也许通过一个真实的例子,您会更容易理解转换是如何工作的。

关于android - 如何使用Android Gradle插件提供的Transform API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36567473/

相关文章:

android - NullPointerException 在抽屉导航中启动新 Activity 时

java - 在单个页面上显示每个 child 的数据

android - MySQL数据不以表格形式显示

android - 当我设置 Custom buildTypes 时,我遇到了一些错误。谁能帮助我?

xml - XML 的 XSL 转换 - 简单的 .NET 示例?

css - 用 CSS 2d 变换定义一个点来缩放?

java - 我可以完全使用单一跨平台语言开发多平台项目 - Windows/Android - 吗?

android - 升级到 7.3.3 和 AGP 7.2.0 时 Gradle 同步失败,无法启动 V1 模型进行同步

rotation - 在处理中旋转、反转和平移 PShape 对象

android - Android Studio-Gradle Sync Project失败-找不到目标哈希字符串