Android Gradle插件中的新API

Co-authored with Jerome Dochez

Jerome Dochez 合着

The Android Gradle Plugin is the supported build system for Android applications and includes support for compiling many different types of sources and linking them together into an application that you can run on a physical Android device or an emulator.

Android Gradle插件是Android应用程序受支持的构建系统,并且支持编译许多不同类型的源并将它们链接到可以在物理Android设备或仿真器上运行的应用程序中。

The Android Gradle Plugin is decoupled from Android Studio — Android Studio can open projects that use the corresponding Android Gradle Plugin or any previous stable version, currently down all the way to Android Gradle Plugin 1.1.

Android Gradle插件与Android Studio脱钩-Android Studio可以打开使用相应的Android Gradle插件或任何以前的稳定版本的项目,目前一直到Android Gradle Plugin 1.1。

Gradle and the Android Gradle Plugin provide the ability to configure and extend the build in different ways depending on the use case.

Gradle和Android Gradle插件提供了根据用例以不同方式配置和扩展构建的功能。

For simple projects where the configuration is mostly declarative, the Android Gradle Plugin can be configured in build.gradle files which are written with Gradle Build Language, or Domain Specific Language (DSL) which is built on top of Groovy script, or build.gradle.kts files that are written using Gradle Kotlin DSL, which was introduced more recently.

对于配置主要是声明性的简单项目,可以在build.gradle文件中配置Android Gradle插件,该文件使用Gradle Build Language或基于Groovy脚本或build.gradle.kts 构建的特定领域语言(DSL) build.gradle.kts使用最近引入的Gradle Kotlin DSL编写的build.gradle.kts文件。

The Android Gradle Plugin DSL was written before the Gradle Kotlin DSL was introduced, and needed a refresh to work well with the Gradle Kotlin DSL. Android Gradle Plugin 4.1 now fully supports the new Kotlin DSL.

Android Gradle插件DSL是在引入Gradle Kotlin DSL之前编写的,并且需要进行更新才能与Gradle Kotlin DSL良好配合。 Android Gradle插件4.1现在完全支持新的Kotlin DSL。

The DSL is not the only way to extend the build. For reuse within a project, scripts can be written in Groovy or Kotlin and applied in multiple build files, but often a better place for custom imperative logic is buildSrc, which can use Java, Groovy and Kotlin, and for reuse by separate projects or the build can be customized by binary plugins written in Java, Groovy or Kotlin. The Android Gradle Plugin is a binary plugin itself.

DSL不是扩展构建的唯一方法。 为了在项目中重用,可以用Groovy或Kotlin编写脚本并将其应用到多个构建文件中,但是对于自定义命令式逻辑来说,更好的地方通常是buildSrc ,它可以使用Java,Groovy和Kotlin,并可以由单独的项目或可以通过用Java,Groovy或Kotlin编写的二进制插件来自定义构建。 Android Gradle插件本身就是一个二进制插件。

Many build authors want to extend the Android Gradle Plugin, such as by configuring specific variants in a fine grained way, generating additional artifacts that contribute to the final artifact or transforming intermediate artifacts. The Android Gradle Plugin already had APIs for all of these use cases, but they needed a refresh to be compatible with Gradle’s lazy configuration and to be less coupled to internal implementation details of the Android Gradle Plugin to provide a better foundation for more flexibility in the future.

许多构建作者希望扩展Android Gradle插件,例如通过以细粒度的方式配置特定变体,生成有助于最终工件或转换中间工件的其他工件。 Android Gradle插件已经具有适用于所有这些用例的API,但是它们需要进行更新以与Gradle的惰性配置兼容,并减少与Android Gradle插件的内部实现细节的耦合,从而为更好的灵活性提供了基础。未来。

Android Gradle插件的新功能:DSL接口和文档 (New in Android Gradle Plugin: DSL interfaces and documentation)

  • Android Gradle Plugin 4.1 includes new DSL interfaces extracted from the existing implementation.

    Android Gradle Plugin 4.1包括从现有实现中提取的新DSL接口。
  • From those interfaces, we have published new documentation for the DSL and API of the Android Gradle Plugin

    通过这些接口,我们发布了有关Android Gradle插件的DSL和API的新文档

  • The API and DSL Interfaces are now in Kotlin for better Kotlin script support, which resulted in us making some breaking changes for existing Kotlin script users.

    API和DSL接口现在位于Kotlin中,以提供更好的Kotlin脚本支持,这使我们对现有Kotlin脚本用户进行了一些重大更改。

As the ecosystem around the Android Gradle Plugin had grown, our existing DSL definitions hadn’t kept up. There wasn’t a clear definition of which APIs were stable, which were experimental, and worse, some internal implementation details leaked into the apparent API of DSL and plugin implementation classes. Also, our documentation generator was an old fork from Gradle and was missing support for Java 8 language features and Kotlin.

随着Android Gradle插件周围的生态系统的发展,我们现有的DSL定义并没有跟上。 对于哪些API是稳定的,哪些是实验性的,还没有明确的定义,更糟糕的是,一些内部实现细节泄漏到了DSL和插件实现类的表观API中。 同样,我们的文档生成器是Gradle的旧分支,并且缺少对Java 8语言功能和Kotlin的支持。

Cleaning all this up was made more challenging by the different compatibility requirements of the various ways build authors interact with the APIs of the Android Gradle Project. Simple projects might only use the Groovy DSL, some projects have already adopted the Kotlin DSL, some projects use buildSrc, with both Java and Kotlin, and many projects bring in binary plugins. In cleaning this up we ideally want to avoid breaking compatibility with any of those use cases, especially Groovy DSL compatibility and binary compatibility for plugins.

由于构建作者与Android Gradle Project的API交互的各种方式的兼容性要求不同,清理所有这些工作变得更具挑战性。 简单的项目可能仅使用Groovy DSL,一些项目已经采用了Kotlin DSL,一些项目使用了Java和Kotlin的buildSrc,许多项目引入了二进制插件。 在清理过程中,我们理想地希望避免破坏与任何这些用例的兼容性,尤其是Groovy DSL兼容性和插件的二进制兼容性。

We had to preserve the existing DSL implementation classes in order to keep binary compatibility. We decided to create interfaces in Kotlin in the gradle-api artifact that define all the public functions of the DSL and are implemented by the existing implementation classes with the goal of this being the sole source of truth for what the APIs of the Android Gradle Plugin are. The documentation for Android Gradle Plugin is now directly generated from those Kotlin interfaces, giving a single set of documentation that should be helpful for everyone using or extending the Android Gradle Plugin, whether writing Groovy or Kotlin script, buildSrc or binary plugins that add functionality.

为了保留二进制兼容性,我们必须保留现有的DSL实现类。 我们决定在gradle-api工件中的Kotlin中创建接口,该接口定义DSL的所有公共功能,并由现有的实现类实现,目的是成为Android Gradle插件的API的唯一真实来源。是。 现在可以直接从这些Kotlin界面直接生成Android Gradle插件的文档 ,从而提供一组文档,这对使用或扩展Android Gradle插件的每个人都应该有所帮助,无论是编写Groovy或Kotlin脚本,buildSrc还是添加功能的二进制插件。

In defining the interfaces in Kotlin, we forced several decisions about nullability and mutability to be made explicit. This is very helpful long term, but has the unfortunate side effect of potentially being a source-level breaking change for existing projects where the build authors had already embraced Gradle’s Kotlin script support, and while most breakages result in source compatibility breakages for certain errors that would have manifest as run-time errors in previous releases, there are some cases where we had to decide to make a breaking change for something that would have worked before. We hope by landing these changes now we can avoid making these sorts of breaking changes going forward.

在Kotlin中定义接口时,我们强制做出了一些关于可空性和可变性的决定。 从长远来看,这是非常有用的,但是不幸的是,它可能会对现有项目的源代码级重大更改产生影响,在现有项目中,构建作者已经接受了Gradle的Kotlin脚本支持,而大多数损坏会导致某些错误的源代码兼容性损坏。在以前的版本中会表现为运行时错误,在某些情况下,我们不得不决定对以前可以使用的功能进行重大更改。 我们希望现在着陆这些更改,就可以避免今后进行此类重大更改。

The most challenging choice we were forced to make was around how to express collection types that are designed to be mutated in the DSL. These types are now uniformly defined as val collection: MutableCollectionType.

我们被迫做出的最具挑战性的选择是如何表达设计为在DSL中突变的收集类型。 这些类型现在统一定义为val collection: MutableCollectionType

This means that it is no longer possible to assign collections in Kotlin scripts for some collections that previously supported it, collection = collectionTypeOf(...)

这意味着不再可能在Kotlin脚本中为以前支持它的某些集合分配集合, collection = collectionTypeOf(...)

However, mutating the collection is supported uniformly so collection += …and collection.add(...) should now work everywhere.

但是,统一支持对集合进行突变,因此collection += …collection.add(...)现在应可在任何地方使用。

While Gradle Kotlin DSL and Gradle Groovy DSL can look very similar, there are some constructs which were ergonomic in Groovy that don’t work well in Kotlin Script. A common example of this is what use of the = operator does. Most Android projects use an integer Android compileSdkVersion, and in Groovy script writing compileSdkVersion = 30 results in a call to setCompileSdkVersion(30). However, for some use cases with preview and add-ons compile sdk is a string, for example compileSdkVersion = "android-R". While in Groovy that simply maps to a different setCompileSdkVersion(...) method, in Kotlin we are forced to assign a type to the property.

虽然Gradle Kotlin DSL和Gradle Groovy DSL看起来非常相似,但是Groovy中有些符合人体工程学的构造在Kotlin Script中无法很好地工作。 一个常见的例子是=运算符的用法。 大多数Android项目使用整数Android compileSdkVersion ,并且在Groovy脚本中,编写compileSdkVersion = 30导致对setCompileSdkVersion(30)的调用。 但是,对于某些带有预览和附加组件的用例,compile sdk是字符串,例如compileSdkVersion = "android-R" 。 在Groovy中,它只是映射到其他setCompileSdkVersion(...)方法,而在Kotlin中,我们被迫为属性分配类型。

In Android Gradle Plugin 4.1 we’ve introduced some new properties to make this easier to write in Kotlin script. We expect most builds to simply use var compileSdk: Int, and for the more specialized cases we have introduced var compileSdkPreview: String and the helper method compileSdkAddon(vendor: String, name: String, version: Int): Unit. We aim for these new properties to eventually replace compileSdkVersion, but until the community has migrated they will continue to work side-by-side.

在Android Gradle Plugin 4.1中,我们引入了一些新属性,以使其更易于用Kotlin脚本编写。 我们希望大多数构建简单地使用var compileSdk: Int ,对于更特殊的情况,我们引入了var compileSdkPreview: String和辅助方法compileSdkAddon(vendor: String , name: String , version: Int ): Unit 。 我们希望这些新属性最终取代compileSdkVersion ,但是在社区迁移之前,它们将继续并行工作。

新的变体API (New variant APIs)

The Android Gradle Plugin already has a variant API, but it has some limitations from its design choices. Rather than continue building up technical debt by adding new extensibility to the existing API, we decided to introduce a new API that addresses those issues, providing a clearer extension model that is decoupled from the internals of the Android Gradle Plugin. The existing API will be retained for now, and we will work to help migrate plugins and authors to the new system. We have also published a library of samples of use of the new variant and artifact APIs which we will continue to expand.

Android Gradle插件已经具有变体API,但在设计选择上有一些限制。 我们没有通过在现有API中添加新的可扩展性来继续增加技术负担,而是决定引入一种新的API来解决这些问题,从而提供一种更清晰的扩展模型,该模型与Android Gradle插件的内部结构分离。 现有的API将暂时保留,我们将努力帮助将插件和作者迁移到新系统。 我们还发布了一个示例库,该示例库将使用我们将继续扩展的新变体和工件API。

The new variant API runs much earlier during configuration than the previous API. This allows the variants to be modified in ways that affect the build flow, unlike the previous API where those decisions had already been made by the time the API ran. These changes can be both explicit, allowing setting properties that affect the build flow, but also implicit, if there is an optimization that is incompatible with something exposed in the variant API, it can simply be done conditionally on the use of that API.

新的变体API在配置过程中的运行时间比以前的API要早得多。 这样就可以以影响构建流程的方式修改变体,这与以前的API有所不同,之前的API在运行API时就已经做出了这些决定。 这些更改既可以是显式的(允许设置影响构建流程的属性),也可以是隐式的(如果存在与变量API中所公开内容不兼容的优化,则可以仅在使用该API的条件下完成)。

The new API further split into two callbacks, onVariants and onVariantProperties. onVariants runs the given action for each variant that will be created. Build authors and plugin authors can use it to customize properties that affect the build flow, such as whether a particular variant is enabled or whether it has tests. After that, the onVariantProperties callbacks are called, allowing build authors and plugin authors to create custom logic and register tasks that consume or modify intermediates of the build.

新的API进一步分为两个回调, onVariantsonVariantPropertiesonVariants为将要创建的每个变体运行给定操作。 构建作者和插件作者可以使用它来自定义影响构建流程的属性,例如是否启用了特定变体或是否具有测试。 之后,将onVariantProperties回调,使构建作者和插件作者可以创建自定义逻辑并注册消耗或修改构建中间件的任务。

Here’s an overview of the stages that an Android project build goes through:

这是一个Android项目构建所经历的阶段的概述:

  1. Build scripts are run, allowing the build and plugins to configure the Android Gradle Plugin DSL objects as well as registering variant callbacks.

    运行构建脚本,从而允许构建和插件配置Android Gradle插件DSL对象以及注册变体回调。
  2. The Android Gradle Plugin combines build types and product flavors to create variants and test components.

    Android Gradle插件结合了构建类型和产品风格来创建变体和测试组件。
  3. The onVariants API is invoked for each variant, allowing the customization of variant settings, and the onTestComponent API is invoked for each test component.

    将为每个变体调用onVariants API,从而允许自定义变体设置,并为每个测试组件均调用onTestComponent API。

  4. The onVariantProperties API is invoked for each variant that was enabled and the onTestComponentProperties API is invoked for each enabled test component allowing the registration of tasks that consume or modify intermediates of the build.

    所述onVariantProperties API被调用用于启用,每个变体和onTestComponentProperties API被调用用于每个已启用的测试部件,允许消耗或修改构建的中间体的任务的登记。

  5. The Android Gradle Plugin registers tasks for the variants after both the onVariants and the onVariantProperties callbacks have been called.

    onVariantsonVariantProperties回调后,Android Gradle插件会为变体注册任务。

  6. The previous variant API is called for each variant, using the registered tasks.

    使用已注册的任务,将为每个变体调用先前的变体API。
  7. Gradle calculates the task graph, and the build can begin executing.

    Gradle计算任务图,构建即可开始执行。

The onVariantProperties API makes use of Gradle Properties and Providers. Properties allow lazy computation of the value and track dependency information in the same place, allowing the use of the API without having to worry about when the value of any particular property will be known. The onVariant API doesn’t use properties since the values are used at configuration time, and so does not benefit from laziness. It does benefit from running much earlier during configuration, which is why it can offer much more flexibility than the previous API, which ran after the tasks were created.

onVariantProperties API使用Gradle属性和提供程序 。 属性允许在同一位置延迟计算值和跟踪依赖项信息,从而允许使用API​​,而不必担心何时会知道任何特定属性的值。 onVariant API不使用属性,因为这些值是在配置时使用的,因此不会从懒惰中受益。 它确实受益于在配置过程中更早地运行,这就是为什么它可以提供比以前的API(在创建任务之后运行)更大的灵活性的原因。

工件API (Artifact APIs)

The previous variant API of the Android Gradle Plugin exposed tasks of the build in order to allow consumption or extension of the build. For example, in Android Gradle Plugin 4.0 to apply the AAR output of a library to a custom task a build author or plugin author might have written something along the lines of:

Android Gradle Plugin的先前变体API公开了构建任务,以允许使用或扩展构建。 例如,在Android Gradle Plugin 4.0中,将库的AAR输出应用于自定义任务,构建作者或插件作者可能已经按照以下方式编写了一些东西:

android {
    ...
    libraryVariants.all {
        project.tasks.register<AarUploadTask>("${name}AarUpload") {
            aarLocation.set(packageLibraryProvider.flatMap { it.archiveFile })
        }
    }
}

While that might look simple, especially in this small example where the output was already available as a provider with dependency information attached, this is strongly coupled to the implementation of the task that produces the final AAR. If that code were compiled into a binary plugin, it would prevent the Android Gradle Plugin from ever removing a public method from a task, changing the type of the task or splitting it up in order to improve the build flow. For example, we considered switching from using the inbuilt Gradle Zip task to a custom one for building AARs, but we haven’t yet as it breaks commonly used binary plugins.

尽管这看起来很简单,但是在这个小示例中,输出已经可以作为提供程序并附加了依赖项信息,这似乎很简单,但这与生成最终AAR的任务的实现紧密相关。 如果将这些代码编译成二进制插件,则会阻止Android Gradle插件从任务中删除公共方法,更改任务的类型或将其拆分以改善构建流程。 例如,我们考虑过从使用内置的Gradle Zip任务切换到用于构建AAR的自定义任务,但是我们还没有,因为它破坏了常用的二进制插件。

The above example only gets the artifact for consumption by a custom task. Using the previous API for replacing or transforming an artifact was generally very brittle, if possible at all, as it required coordinating multiple tasks and updating every consumer of an artifact.

上面的示例仅获取供自定义任务使用的工件。 如果可能的话,使用以前的API替换或转换工件通常非常脆弱,因为它需要协调多个任务并更新工件的每个使用者。

With the new artifact API in Android Gradle Plugin 4.2 you can now write:

借助Android Gradle Plugin 4.2中的新工件API,您现在可以编写:

android {
    ...
    onVariantProperties {
        project.tasks.register<AarUploadTask>("${name}AarUpload") {
            aarLocation.set(artifacts.get(ArtifactType.AAR))
        }
    }
}

The difference here, the reference to the task is gone: the API provides more flexibility while also being decoupled from the internal implementation in the Android Gradle Plugin.

区别在于,对任务的引用消失了:API提供了更大的灵活性,同时还与Android Gradle插件中的内部实现脱钩。

The Android Gradle Plugin manages a registry of artifacts attached to each variant for all the input, output and intermediate files, expressed as providers with dependency information attached. This registry is used throughout the Android Gradle Plugin to replace the manual wiring of tasks, and manages the locations of the artifacts to avoid accidental clashes and inconsistencies.

Android Gradle插件管理所有输入,输出和中间文件的附加到每个变体的工件的注册表,这些文件表示为附带有依赖项信息的提供程序。 该注册表在整个Android Gradle插件中用于替换任务的手动接线,并管理工件的位置,以避免意外冲突和不一致。

A subset of those artifacts are exposed through the new variant properties API.

这些工件的子集通过新的变体属性API公开。

The keys to this registry are instances of Artifact. Whether the artifact is a file or a directory is represented as part of its type. When writing custom tasks it is important to use the right corresponding Property, i.e. DirectoryProperty or RegularFileProperty. The cardinality of the artifact is also encoded in its type and specific APIs must be used to interact with ListProperty when dealing with a MultipleArtifact type.

该注册表的关键是Artifact实例。 工件是文件还是目录都表示为其类型的一部分。 在编写自定义任务时,重要的是使用正确的相应Property ,即DirectoryPropertyRegularFileProperty 。 工件的基数也以其类型编码,并且在处理MultipleArtifact类型时,必须使用特定的API与ListProperty进行交互。

Other interfaces that decorate artifacts indicate the type of operations that can be performed on the artifact. Such operations allow custom tasks to participate in the Android build process by either replacing, transforming or appending an artifact, all that without specific knowledge about how the items are either produced or consumed by the other tasks participating in the build process.

装饰工件的其他接口指示可以在工件上执行的操作的类型。 此类操作允许自定义任务通过替换转换附加工件来参与Android构建过程,而所有这些操作都没有关于参与构建过程的其他任务如何生产或消费物品的特定知识。

Operations that are now possible on artifacts include:

现在可以对工件进行的操作包括:

得到 (Get)

This operation gets the final version of an artifact. Irrespective of how the artifact is produced and sometimes transformed by Tasks, calling get (or getAll for MultipleArtifacts) will always ensure the final version of the artifact is provided. It is a read-only value: modifying the artifact obtained by a get is not allowed. For that reason, the return type of the get method is a Provider and not a Property. This Provider can only be used as a task input.

此操作获取工件的最终版本。 无论工件是如何产生工件的,有时是由Tasks转换的,调用get (或对MultipleArtifactgetAll )都将始终确保提供工件的最终版本。 这是一个只读值:不允许修改通过get的工件。 因此, get方法的返回类型是Provider而不是Property 。 此Provider只能用作任务输入。

For instance, you might be interested in having access to the merged manifest, not to modify it but maybe to ensure that the permissions have not changed:

例如,您可能有兴趣访问合并的清单,而不是对其进行修改,但可能要确保权限未更改:

abstract class VerifyManifestTask: DefaultTask() {
    @get:InputFile
    abstract val mergedManifest: RegularFileProperty


    @TaskAction
    fun taskAction() {
        val mergedManifestFile = mergedManifest.get().asFile 
        // ... verify manifest file content ...
    }
}

Now you can wire your task :

现在,您可以连接任务:

android {
    onVariantProperties { 
        project.tasks.register<VerifyManifestTask>("${name}VerifyManifest") {
            mergedManifest.set(artifacts.get(ArtifactType.MERGED_MANIFEST))
        }
    }
}

转型 (Transformation)

This operation modifies the artifact in some way. The original artifact is provided as an input to the given task along with a new location to output the transformed artifact.

此操作以某种方式修改了工件。 提供原始工件作为给定任务的输入,并提供新位置以输出转换后的工件。

Let’s look at a Task that transforms the merged manifest by setting the version to git head value.

让我们看一下通过将版本设置为git head值来转换合并清单的任务。

First, let’s define the Task that will calculate the git head:

首先,让我们定义将计算git head的Task:

abstract class GitVersionTask: DefaultTask() {


    @get:OutputFile
    abstract val gitVersionOutputFile: RegularFileProperty


    @TaskAction
    fun taskAction() {
        val process = ProcessBuilder("git", "rev-parse --short HEAD")
                .start()
        val error = process.errorStream.readBytes().decodeToString()
        if (error.isNotBlank()) {
            throw RuntimeException("Git error : ${'$'}error")
        }
        var gitVersion = process.inputStream.readBytes().decodeToString()
        gitVersionOutputFile.get().asFile.writeText(gitVersion)
    }
}

Now, create the task that will transform the manifest file using the git version calculated by the previous task.

现在,创建一个任务,该任务将使用上一个任务计算的git版本来转换清单文件。

abstract class ManifestTransformerTask: DefaultTask() {


    @get:InputFile
    abstract val gitInfoFile: RegularFileProperty


    @get:InputFile
    abstract val mergedManifest: RegularFileProperty


    @get:OutputFile
    abstract val updatedManifest: RegularFileProperty


    @TaskAction
    fun taskAction() {
        val gitVersion = gitInfoFile.get().asFile.readText()
        var manifest = mergedManifest.get().asFile.readText()
        manifest = manifest.replace(
                "android:versionCode=\"1\"", 
                "android:versionCode=\"${gitVersion}\"")
        updatedManifest.get().asFile.writeText(manifest)
    }
}

The wiring clearly states the intent :

接线明确说明了意图:

android {
    onVariantProperties {
        // create the task to provide the git version.
        val gitVersion = tasks.register<GitVersionTask>("gitVersion") {
            gitVersionOutputFile.set(
                    File(project.buildDir, "intermediates/git/output"))
        }


        // create the task that transforms the manifest with that version
        val manifestUpdater = tasks
            .register<ManifestTransformerTask>("${name}ManifestUpdater") {       
                // set the input from another task writing the git head
                // into a file.                   
                gitInfoFile.set(
                    gitVersion.flatMap(GitVersionTask::gitVersionOutputFile)
                )
        }


        // and wire things up with the Android Gradle Plugin    
        artifacts.use(manifestUpdater)
            .wiredWithFiles(
                    ManifestTransformerTask::mergedManifest,
                    ManifestTransformerTask::updatedManifest)
           .toTransform(ArtifactType.MERGED_MANIFEST)  
    }
}

附加 (Append)

Append is only relevant for artifact types that are decorated with MultipleArtifact. Because such types are represented as a List of either Directory or RegularFile, a task can declare an output that will be appended to the list.

追加仅与用MultipleArtifact装饰的工件类型相关。 由于此类类型表示为Directory或RegularFile的List,因此任务可以声明将添加到列表的输出。

abstract class SomeProducer: DefaultTask() {


    @get:OutputFile
    abstract val output: RegularFileProperty


    @TaskAction
    fun taskAction() {
        val outputFile = output.get().asFile 
        // … write file content …
    }
}

The wiring is similar to other operations:

接线与其他操作类似:

android {
    onVariantProperties { 
        val someProducer = project.tasks.register<SomeProducer>("${name}SomeProducer") {
              // ... configure your task as needed ...
        }
        artifacts.use(someProducer)
            .wiredWith(SomeProducerTask::output)
            .toAppendTo(ArtifactType.MANY_ARTIFACT)
    }
}

Note that at this point, we have not released a public MultipleArtifact artifact so this API will only become useful in the future.

请注意,目前我们还没有发布公共的MultipleArtifact工件,因此该API仅在将来有用。

创建 (Creation)

This operation replaces the current provider of an Artifact with a new one, discarding all previous producers. It is an ‘out’ operation where a task declares itself to be the sole provider of the artifact. If there is more than one task declaring itself as the artifact provider, the last one wins.

此操作将使用新的人工物品替换当前的人工物品提供者,并丢弃所有先前的生产者。 这是一项“输出”操作,其中任务声明自己是工件的唯一提供者。 如果有多个任务宣布自己为工件提供者,则最后一个任务获胜。

For instance, a custom task may not use the built-in manifest merger but instead relies on a manually merged manifest checked into the source code management tool.

例如,自定义任务可能不使用内置清单合并,而是依赖于检查到源代码管理工具中的手动合并清单。

abstract class ManifestFileProducer: DefaultTask() {


    @get:OutputFile
    abstract val outputManifest: RegularFileProperty


    @TaskAction
    fun taskAction() {
        val mergedManifestFile = outputManifest.get().asFile 
        // ... write manifest file content ...
    }
}

Wired with:

连线:

android {
    onVariantProperties { 
        val manifestProducer = project.tasks.register<ManifestProducerTask>("${name}ManifestProducer") {
            //… configure your task as needed ...
        }
        artifacts.use(manifestProducer)
            .wiredWith(ManifestProducerTask::outputManifest)
            .toCreate(ArtifactType.MERGED_MANIFEST)
    }
}

When a custom task is creating an artifact, all original producers/transformers of that artifact will not be part of the build process unless needed to produce another artifact. We don’t expect many builds to use this as the majority of the use cases we’ve considered will be served better by Transformation. If you find yourself working around a limitation in the Android Gradle Plugin using creation, please file an issue or feature request.

当定制任务创建工件时,除非需要产生另一个工件,否则该工件的所有原始生产者/变形者都不会成为构建过程的一部分。 我们不希望有许多构建版本可以使用此功能,因为我们已经考虑过的大多数用例都可以通过Transformation更好地使用。 如果您发现自己使用创作方法解决了Android Gradle插件中的限制,请提出问题或功能请求

By focusing on artifacts rather than tasks, custom plugins or build scripts can safely extend the Android Gradle Plugin without being at the mercy of build flow changes or private details like task implementations, and we hope that these changes mean build authors can upgrade their Gradle Plugin more easily in the future.

通过专注于工件而不是任务,自定义插件或构建脚本可以安全地扩展Android Gradle插件,而不必担心构建流程更改或任务实现等私有细节,我们希望这些更改意味着构建作者可以升级其Gradle插件将来更容易。

We plan to allow more configuration of the variants and make more artifacts available as public types in upcoming releases, and we will continue to add more examples.

我们计划允许对变体进行更多配置,并在即将发布的版本中提供更多工件作为公共类型,并且我们将继续添加更多示例

翻译自: https://medium.com/androiddevelopers/new-apis-in-the-android-gradle-plugin-f5325742e614

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值