Android Gradle 2:配置构建变体

Android Gradle 2:配置构建变体,第1张

概述本博文以AndroidGradle1:基本介绍为基础,介绍如何配置构建变体。包括:版本类型(BuildType)、产品变种(ProductFlavors)、版本变体(版本变体)、依赖项等内容。配置版本类型(BuildType)可以在模块级build.gradle文件的android块内的创建和配置版本类型(BuildType)。配置代

本博文以Android Gradle 1:基本介绍为基础,介绍如何配置构建变体。包括:版本类型(Build Type)、产品变种(Product Flavors)、版本变体(版本变体)、依赖项等内容。

配置版本类型(Build Type)

可以在模块级 build.gradle 文件的 androID 块内的创建和配置版本类型(Build Type)。配置代码包含在 buildTypes 代码块内。当创建新模块时,AndroID Studio 会自动创建 "deBUG" 和 "release" 两种版本类型。虽然 "deBUG" 类型没有显示在构建配置文件中,但 AndroID Studio 会使用 deBUGgable true 配置它。

如果要添加或更改某些设置,可以将 "deBUG" 类型添加到配置中。以下示例为调试 Build 类型指定了 applicationIDSuffix,并配置了一个 "test" 版本类型。

androID {    // 默认配置    defaultConfig {        manifestPlaceholders = [hostname:"www.example.com"]        ...    }    buildTypes {        // 发布版本的配置        release {            // 开启混淆和压缩            MinifyEnabled true            proguardfiles getDefaultProguardfile('proguard-androID.txt'), 'proguard-rules.pro'        }    // 调试版本的配置        deBUG {            applicationIDSuffix ".deBUG"            deBUGgable true        }        // 测试版本的配置        test {            // 赋值 deBUG 版本的属性进行初始化 *** 作            initWith deBUG            manifestPlaceholders = [hostname:"internal.example.com"]            applicationIDSuffix ".deBUGTest"        }    }}

要详细了解 Build Type 配置的所有属性,请参阅版本类型(BuildType) DSL 参考文档

配置产品变种(Product Flavors)基本应用

创建产品变种(Product Flavors)与创建版本类型(Build Type)类似:配置位置在 androID 代码块的 productFlavors 子代码块中。产品变种支持与 defaultConfig 相同的属性,这是因为 defaultConfig 实际上属于 ProductFlavor 类。这意味着,可以在 defaultConfig 代码块中,提供所有类型的基本配置。并且每种产品变种均可更改任何这些默认值。

所有产品变种都必须属于一个指定的维度,即一个产品变种组。必须将所有产品变种分配给某个维度;否则,将被提示构建错误。错误如下:

Error:All flavors must Now belong to a named flavor dimension.The flavor 'flavor_name' is not assigned to a flavor dimension.

以下代码示例创建了一个名为 "version" 的维度,并添加了 "demo" 和 "full" 产品变种。这些变种自行提供其 applicationIDSuffix 和 versionnameSuffix:

androID {    ...    defaultConfig {...}    // 配置版本类型    buildTypes {        deBUG{...}        release{...}    }    // 配置产品变种    // 指定维度,即产品变种组    flavorDimensions "version"    productFlavors {        demo {            // 如果所有维度只有一个,这个设置可要可不要,构建系统会自动指定维度为 "version",建议写上            dimension "version"            applicationIDSuffix ".demo"            versionnameSuffix "-demo"        }        full {            dimension "version"            applicationIDSuffix ".full"            versionnameSuffix "-full"        }    }}

同样的,要详细了解通过产品变种(Product Flavors)配置的所有属性,请参阅产品变种(Product Flavors) DSL 参考文档

根据维度划分(配置版本变体(Build Variant))

先看个问题:对于同一个 APK,已经构建了 "demo" 和 "full" 两个变种 APK,但是来了个新需求。需要进一步根据 API 级别划分 APK。这怎么办?

此时就需要用上维度了。

可以使用 Gradle 创建多组维度。在构建应用时,Gradle 会结合使用您定义的每个维度的产品变种配置以及版本类型配置,以创建最终的变种 APK。Gradle 不会将属于同一维度的产品变种组合在一起。

以下代码示例使用 flavorDimensions 属性来创建 "mode" 类型维度和 "API" 类型维度,前者用于对 "full" 和 "demo" 产品类型进行分组,后者用于根据 API 级别对产品类型配置进行分组。

androID {    ...    buildTypes {        deBUG {...}        release {...}    }        // 指定两个维度,维度的优先级取决于被列举出来的顺序,从高到低,在配置产品变种时,需要确保每一个变种都被指定了一个维度    flavorDimensions "API", "mode"    productFlavors {        demo {            dimension "mode"            ...        }        full {            dimension "mode"            ...        }                // API 维度中的配置会覆盖 demo 中的同名配置,高优先级覆盖低优先级        minAPI24 {            dimension "API"            minSdkVersion 24            versionCode 30000 + androID.defaultConfig.versionCode            versionnameSuffix "-minAPI24"            ...        }                minAPI23 {            dimension "API"            minSdkVersion 23            versionCode 20000  + androID.defaultConfig.versionCode            versionnameSuffix "-minAPI23"            ...        }        minAPI21 {            dimension "API"            minSdkVersion 21            versionCode 10000  + androID.defaultConfig.versionCode            versionnameSuffix "-minAPI21"            ...        }    }}

Gradle 创建的 APK 数量(版本变体数) = 每个产品变种数 * 版本类型数。如上面的代码中,最终生成的 APK 数量为:12,形式如 app-[minAPI24, minAPI23, minAPI21]-[demo, full]-[deBUG, release].apk

某一个 APK 的名字为:app-minAPI24-demo-deBUG.apk。对应的版本变体名为:minAPI24DemoDeBUG。

过滤变体

默认的,在构建时,Gradle 会穷举所有的 BuildType 和 ProductFlavor 组合,但是实际上,有一些组合出来的 APK 结果并不是我们所需要的,此时就需要进行过滤。

可以通过在各个模块的 build.gradle 文件中创建变体过滤器来移除某些构建变体配置。

继续上面的例子,假设我们只想让 "demo" 版应用仅支持 API 级别 23 和更高版本。那么此时可以使用 variantFilter 代码块过滤掉所有将 "minAPI21" 和 "demo" 结合在一起的配置,此代码块仍然在 androID 块内:

androID {    ...    buildTypes {...}    flavorDimensions "API", "mode"    productFlavors {        demo {...}        full {...}        minAPI24 {...}        minAPI23 {...}        minAPI21 {...}    }        // 过滤变种组合,对于每一中组合,都会经过这个过滤器筛选。    variantFilter {        // groovy 语法,根据已有列表创建新列表的简洁语法, * 相当于遍历 flavors 中的所有元素,并取出每个元素的 name 构成一个新的列表        // 转换成 Java 语法的形式为(非正确代码)        //         // def names;        // for(Flavor flavor : variant.flavors)        //     names.add(flavor.name);        //         // 此处的 flavors 实际大小为 1,因为是针对每一个 variant 而言的,则 names 实际是个字符串类型        variant ->        def names = variant.flavors*.name        if (names.contains("minAPI21") && names.contains("demo")) {            // 符合条件则忽略            setIgnore(true)        }    }}
配置源集(Source Set)

源集,也叫做源代码文件集。默认情况下,AndroID Studio 会为我们创建 "main/" 源代码文件集和目录。但是,如果我们希望构建新的版本类型和产品变种及其交叉产物。那么我们就可以构建新的源集,在 "main/" 源代码文件集中定义基本功能,各个变种 APK 的不同特性定义在不同的源集中。

Gradle 要求以某种类似于 "main/" 源代码文件集的方式,组织源代码文件集文件和目录。例如,Gradle 要求将 "deBUG" Build Type特有的 Java 类文件放在 "src/deBUG/java/" 目录中。

使用任务查看源集

Gradle 的 AndroID 插件提供了一个有用的 Gradle 任务(task),该任务可以用来展示如何整理每个构建类型(Build Type,中文翻译不一样,意思一样)、产品类型(Product Flavor)和构建变体(Build Variant)的文件。例如,以下任务输出的示例描述了 Gradle 希望 "deBUG" 构建类型的部分文件所在的位置:

------------------------------------------------------------Project :app------------------------------------------------------------...deBUG----Compile configuration: compilebuild.gradle name: androID.sourceSets.deBUGJava sources: [app/src/deBUG/java]Manifest file: app/src/deBUG/AndroIDManifest.xmlAndroID resources: [app/src/deBUG/res]Assets: [app/src/deBUG/assets]AIDL sources: [app/src/deBUG/aIDl]RenderScript sources: [app/src/deBUG/rs]JNI sources: [app/src/deBUG/jni]JNI librarIEs: [app/src/deBUG/jnilibs]Java-style resources: [app/src/deBUG/resources]

想要使用此任务查看输出,可以使用一下 *** 作步骤:

点击 IDE 右侧的 Gradle 图标。依次转到 MyApplication > Tasks > androID,然后双击 sourceSets。Gradle 执行该任务后,系统应该会打开 Run 窗口以显示输出,Run 窗口默认在 IDE 底部。位置如下,

注意:输出的结果中还包含了测试(AndroID测试,Java测试)源代码文件集。

创建源集

当创建新的构建变体时,AndroID Studio 不会创建源代码文件集目录,而是提供一些有用的选项,手动触发创建选项。例如,为 "deBUG" 构建类型创建 "java/" 目录,应执行以下 *** 作:

打开 Project 窗格,然后从窗格顶部的下拉菜单中选择 Project 视图。转到 MyProject/app/src/。

右键点击 src 目录,然后依次选择 New > Folder > Java Folder。

从 Target Source Set 旁边的下拉菜单中,选择 deBUG。点击 Finish。

当 "deBUG" 构建类型被指定为目标源代码文件集后,AndroID Studio 在创建 XML 文件时会自动创建必要的目录。如图:

按照相同的过程,可以创建产品变种的源代码文件集目录(如 src/demo/)和构建变体的源代码文件集目录(如 src/demoDeBUG/)。此外,还可以创建特定构建变体的,特定的测试源代码文件集(例如 src/androIDTestDemoDeBUG/)。要了解详情,请查看测试源代码文件集

更改默认源代码文件集配置

如果开发中未按照官方建议的源集文件结构,整理源文件(如上文创建源集的相关内容所述),则可以使用 sourceSets 代码块,更改为源集的每个组件收集文件的位置。改代码块也是在 androID 代码块下。无需改变文件的位置,只需设置相对于模块级 build.gradle 文件的路径即可。Gradle 会在该路径下找到每个源集组件的文件。要了解可以配置哪些组件,以及是否可以将它们映射到多个文件或目录,请参阅AndroidSourceSet DSL 参考文档

下面的代码展示了将 "app/other/" 目录中的源文件映射到 "main/" 源代码文件集的某些组件,并更改 "androIDTest/" 源代码文件集的根目录。

androID {    ...    sourceSets {        // 指定 Java 源代码目录为,默认的目录是'src/main/java'        java.srcDirs = ['other/java']        // 指定资源文件夹目录,默认的目录是'src/main/res'        // 如果此处同时列举了多个目录,gradle 在编译时会从所有目录中收集源文件。因为所有目录的优先级都是一样的。        // 但是如果不同的目录中有相同的源文件,则会报错。即可以指定多个目录,但目录之间之间不同有相同的文件。        // 另外,在自动目录时,应避免目录之间存在父子关系(父目录,子目录)。即目录之间应该是并列关系,而不是包含关系        res.srcDirs = ['other/res1', 'other/res2']        // 对于每一个源集,可以指定一个清单文件。AndroID Studio 会默认为 "main/" 源集创建一个清单文件        manifest.srcfile 'other/AndroIDManifest.xml'        ...    }    // 额外的块配置其他源集    androIDTest {        // 如果一个源集的所有文件都在一个目录下,则可以使用 'setRoot ' 属性指根目录。        // 设置了以下属性后,Gradle 会在 'src/tests/java/' 目录下寻找 Java 源文件        setRoot 'src/tests'        ...    }    ...}
使用源集进行构建

可以在源代码文件集目录中,添加针对某些配置打包在一起时的代码和资源。例如,如果要构建 "demoDeBUG" 这个构建变体("demo"产品变种和"deBUG"构建类型的混合产物),则 Gradle 会查看这些目录,并为它们指定以下优先级:

src/demoDeBUG/(构建变体源代码文件集)src/deBUG/(构建类型源代码文件集)src/demo/(产品类型源代码文件集)src/main/(主源代码文件集)

注意,优先级也受维度的影响。参见上文对构建变体(Build Variant)的介绍。

上面列出的顺序决定了 Gradle 组合代码和资源时,哪个源代码文件集的优先级更高。如果 'demoDeBUG/' 包含了 'deBUG/' 中也定义了的文件,则 Gradle 会使用 'demoDeBUG/' 源代码文件集中的文件。在应用以下构建规则时,Gradle 会考虑这种优先级顺序:

java/ 目录中的所有源代码将一起编译以生成单个输出。注意:对于给定的构建变体,如果 Gradle 遇到两个或更多个源代码文件集目录定义了同一个 Java 类的情况,则会抛出构建错误。例如,在构建 deBUG APK 时,您不能同时定义 src/deBUG/Utility.java 和 src/main/Utility.java 两个相同的类。这是因为 Gradle 在构建过程中会查看这两个目录并抛出“重复类”错误。所有清单都将合并为一个清单。优先级将按照上面列出的顺序分配。也就是说,构建类型(deBUG)的清单设置会替换产品变种(demo)的清单设置,依此类推。要了解详情,请参阅@L_419_5@。同样,values/ 目录中的文件也会合并在一起。如果两个文件同名,例如存在两个 strings.xml 文件,将按照上述列表中的相同顺序指定优先级,高优先级覆盖低优先级。res/ 和 asset/ 目录中的资源会打包到一起。如果在两个或更多个源代码文件集中定义了同名的资源,将按照上面列表中的顺序指定优先级。同 'values' 目录的处理方式。最后,在构建 APK 时,Gradle 会为库模块依赖项随附的资源和清单指定最低优先级(依赖库中的内容为最低优先级)。

总结一下,Java 类比较特殊,重复了会报重复类的错误,说明 Java 类之间不会相互覆盖。而其他的资源、清单文件会根据优先级来相互覆盖。

从上面的类重复错误和资源覆盖可以看出。源集的构建应该遵循"主源集包含公共的内容,其他构建变体的源集包含差异化的内容"的原则。

到这里为止,AndroID Gradle 当做工具的进阶使用讲解算是告一段落。

最后,附上Android Plugin for Gradle DSL 参考

总结

以上是内存溢出为你收集整理的Android Gradle 2:配置构建变体全部内容,希望文章能够帮你解决Android Gradle 2:配置构建变体所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1065855.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存