微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

我使用applicationVariants.dex.dependsOn任务在代码转换为dex文件之前做了一些额外的工作,并且在android gradle插件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)

他们执行汇编任务时,我的自定义转换似乎有效.我可以从执行任务列表中看到它:

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)
  }

然后在转换方法中,您需要获取输入和输出文件夹.

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)

最后,您必须将所有文件从输入复制到输出.

这是一个实现转型的project.也许你会更容易理解变换如何与一个真实的例子一起工作.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐