buildTypes——安卓gradle

目录
1、前言
2、buildTypes
3、buildType
一、buildTypes存在形式
二、buildTypes 中属性的意义
三、buildTypes 中方法的意义
4、写在最后
html

1、前言

上一篇博客 分享了defaultConfig 中可配置参数的含义,今天咱们来分享另外一个咱们也很熟悉的 buildTypesjava

2、buildTypes

buildTypes 也是存在于每一个应用级模块中的 android 下的,即以下所示,是每次构建完项目以后自动生成的结构。android

android {
    buildTypes{
    	release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}
复制代码

buildTypes 能够配置咱们须要的构建类型,例如咱们经常使用到的 “测试类型” 和 “本地类型”,则可使用以下配置git

buildTypes{
    // 发布类型
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    // 测试类型,给测试人员
    debug {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    // 本地类型,和后端联调使用
    local {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}
复制代码

增长完这些配置后,咱们能够在 android studio 看到多了 “debug” 和 “local” 两个能够构建的类型,在 “点击运行” 时,便会使用咱们所选择的构建类型。假设此时选择的是 “debug” 类型,咱们此时运行代码,则是 debug 下的配置参数。 github

固然运行编译成 apk 时,也不例外,各自使用的也是各自类型的配置。

而这里所说的 “release”,“debug”,“local”,三个构建类型其实即是三个 buildTypebuildType 所能配置的参数即是咱们今天要来捋清楚的。windows

3、buildType

buildType 官方文档传送门后端

一、buildType存在形式

从上一篇博客咱们知道,每一个配置最终会被映射为一个类,或是一个属性、或一个方法。buildType 也不例外,他会被映射为 com.android.build.gradle.internal.dsl.BuildType,继承结构以下android-studio

咱们从新看一下 DefaultConfig 的继承结构,能够看到都会继承到 BaseConfigImpl 类,说明二者会有必定的交集。这也说明了为何咱们看 gradle 文件时,总感受一个配置参数哪里都能出现的状况(后面会进行更多的比较,来解除咱们这种疑惑)浏览器

二、buildType 中属性的意义

咱们先来一个约定,避免使用的代码过于冗长。bash

buildTypes{
    debug {
	// 咱们下面的 “使用方法” 代码都是基于这一块,除非特殊说明。
    }
}
复制代码

2.1 applicationIdSuffix

  • 类型:String
  • 描述:会追加在 applicationId 字符串的后面,造成最终的包名
  • 值得一提:在 defaultConfig 中也有这个属性,但通常不会使用。而会在 buildTypes 中使用,这样可让包名不一样,同时安装多个类型的应用。例如咱们上面所提到的 release包、debug包、local包,均可以同时存在而不会覆盖,方便调试。
  • 使用方法:
debug {
    applicationIdSuffix '.debug'
}
复制代码

2.2 consumerProguardFiles

  • 类型:List< File >
  • 描述:这个属性只做用于咱们建立的 library 中,包括咱们以aar形式导入的 library ,或是直接建立的 library。它的做用是,负责该 library 被进行编译时的混淆规则,咱们在 主App 的模块下则能够不用再管理各个 library 的混淆规则,会直接使用各个 library 的混淆规则文件。
  • 值得一提:这个属性 和 proguardFiles 的区别在于,consumerProguardFiles 会被 主App模块 做为混淆文件使用导入,而 proguardFiles 则不会。
  • 使用方法:
debug {
    consumerProguardFiles 'consumer-rules.pro'
    ......省略其余配置
}

// 由于该属性是一个 List<File> 类型,若是须要多个文件配置,则以下所示
debug {
    consumerProguardFiles 'consumer-rules.pro','zincPower-rules.pro'
    ......省略其余配置
}
复制代码

2.3 crunchPngs

  • 类型:boolean
  • 描述:是否对 PNG 图片进行压缩处理。设置为true时,会对未进行最佳压缩的PNG资源进行压缩,但也会增长构建时间。
  • 值得一提:默认状况下,release 类型是开启的,debug 类型则为关闭。
  • 使用方法:
debug {
    crunchPngs false
    ......省略其余配置
}
复制代码

2.4 debuggable

  • 类型:boolean
  • 描述:是否能够对应用进行调试。
  • 值得一提:release 的构建类型默认为不可调试,即为false。而 debug 默认为true,既能够调试。所谓的 没法调试 即下图的 “虫子” 标记没法让应用启动,而正常的运行是能够的。
  • 使用方法:
debug {
    debuggable true
}
复制代码

2.5 javaCompileOptions

  • 类型:JavaCompileOptions
  • 描述:配置编译时 java 的一些参数,例如咱们使用 annotationProcessor 时所须要的参数。
  • 使用方法:
debug {
    javaCompileOptions {
        annotationProcessorOptions{
    		arguments = []
    		classNames ''
    		....
    	}
    }
    ......省略其余配置
}
复制代码

JavaCompileOptions 能够配置的具体参数,请进传送门

2.6 jniDebuggable

  • 类型:boolean
  • 描述:是否能够对应用的 native 代码进行调试
  • 值得一提:release 的构建类型默认为不可调试 native 代码,即为false。而 debug 默认为true,既能够调试 native 代码。没法对 native 代码调试,指的是即便在native方法打了断点,代码也不会被 “停住”。
  • 使用方法:
debug {
    jniDebuggable true
}
复制代码

2.7 manifestPlaceholders

  • 类型:Map<String, Object>
  • 描述:配置能够在 AndroidManifest.xml 中使用的参数。
  • 使用方法: 这里想配置咱们应用的 logo 为测试版本的logo,方便测试人员区分不一样类型的包,则能够在 gradle 中使用下面这段
debug {
    manifestPlaceholders = [APP_LOGO_ICON: "@mipmap/ic_logo"]
}
复制代码

而后在 AndroidManifest.xml 中使用,使用 ${你配置的变量名}

// 在 application 中使用替换,还须要多添加 tools:replace 这一标签,将咱们须要替换的名称写上,例如这里的 android:icon
<application android:allowBackup="true" android:icon="${APP_LOGO_ICON}" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" tools:replace="android:icon">
......
复制代码

2.8 minifyEnabled

  • 类型:boolean
  • 描述:是否开启混淆,代码优化。true开始,false则关闭。
  • 使用方法:
debug {
    minifyEnabled true
}
复制代码

2.9 proguardFiles

  • 类型:List< File >
  • 描述:配置混淆规则文件,只有 minifyEnabled 设置为 true 的时候会使用这个参数,文件中须要申明哪些文件不被优化和混淆。
  • 值得一提:由于被混淆后端代码,类名和方法名都会有所变化,因此进行反射会失败,这是咱们就须要进行申明他们不被混淆。(这里只是举了使用这个参数的一个场景,若是应用原本是正常的,开了混淆后,出现了莫名奇妙的bug,那就思考下是否由于混淆致使了这一bug
  • 使用方法:
debug {
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
复制代码

2.10 multiDexEnabled

64K 引用限制问题官方文档 传送门

  • 类型:Boolean
  • 描述:是否开启分包。由于安卓中方法索引值为两个字节,四位十六进制的一个数值,即[0, 0xffff],因此最大方法数为65536个。一旦超出了,就须要进行分包,因此咱们就须要开启这个参数。
  • 使用方法:
android{
    buildTypes {
    	debug {
    		multiDexEnabled true
    		...
    	}
    }
}

// 添加依赖
dependencies {
    // 若是使用的为 AndroidX,则使用下面这个导入
    // implementation 'androidx.multidex:multidex:2.0.1'
    // 若是不使用 AndroidX,则使用下面这段
    compile 'com.android.support:multidex:1.0.3'
}
复制代码

有两种开启 MultiDex 方法:

// 第一种:让你应用的 Application 继承 MultiDexApplication。
public class MyApplication extends MultiDexApplication {

}

// 第二种:重写应用的 Application 方法 attachBaseContext
public class MyApplication extends Application {

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }
}
复制代码

最后别忘了在 AndroidManifest.xml 中使用咱们在上面的 Application。

2.11 multiDexKeepFile

  • 类型:File
  • 描述:将咱们须要的类打包进主包,即 classs.dex。咱们在第 2.10 小点,分享到使用了多包处理,有时咱们须要将一些主要的类打包进主包,则可使用该属性。
  • 使用方法:
debug {
    multiDexKeepFile file('multidex-config.txt')
    ...
}
复制代码

multidex-config.txt 中的书写则以下,每个文件则为一行

com/example/MyClass.class
com/example/TestClass.class
复制代码

2.12 multiDexKeepProguard

  • 类型:File
  • 描述:将咱们须要的类打包进主包,和第 2.11 点的功能相同,区别在于写法。
  • 使用方法:
debug {
    multiDexKeepFile file('multidex-config.pro')
    ...
}
复制代码

multidex-config.pro 中的写法以下

// 将会保留全部的在com.example package的类
-keep class com.example.** { *; }
复制代码

2.13 name

  • 类型:String
  • 描述:构建类型的名字。
  • 使用方法:
// debug 则会被赋值至 name 属性,并且 name 是final 类型,没法在改动。
debug{
    ...
}
复制代码

2.14 pseudoLocalesEnabled

  • 类型:boolean
  • 描述:这个属性用于开启伪语言,用于发现UI中潜在的可本地化问题。
  • 使用方法:

第一步:咱们在配置中开启该属性

debug{
    pseudoLocalesEnabled true
}
复制代码

第二步:安装咱们的应用 第三步:打开设置 -> 系统 -> 语言和输入法 -> 语言 -> 添加语言

会在 “添加语言” 页面中看到以下图的选项,选择图中红色框的内容,各自的不一样在图中也有标明,咱们往下走看看具体不一样的表现是什么。

小盆友的测试机是 荣耀8,不一样机子会有些许不一样

选择以后,选择不一样的语言会有不一样效果,如图所示 (1)左边为未开启时的样子; (2)中间为选择了Pseudo locale(至关于en-XA); (3)右边为选择了Bidirection test locale(至关于en-XB);

2.15 renderscriptDebuggable

  • 类型:boolean
  • 描述:是否能够对 renderscript 代码进行调试
  • 使用方法:
debug {
    renderscriptDebuggable true
}
复制代码

2.16 renderscriptOptimLevel

  • 类型:int
  • 描述:设置渲染脚本等级
  • 使用方法:
debug {
    renderscriptOptimLevel 3
}
复制代码

2.17 shrinkResources

shrinkResources 官方使用手册 传送门

  • 类型:boolean
  • 描述:是否压缩资源,若是开启,gradle在编译时帮咱们把没有使用的资源给移除。
  • 值得一提:shrinkResources 的开启须要 minifyEnabled 也为开启状态,不然没法运行。
  • 使用方法:
debug {
    shrinkResources false
}
复制代码

开启后编译完会看到以下日志

2.18 signingConfig

  • 类型:SigningConfig

SigningConfig 的可配置参数 传送门

  • 描述:配置签名配置。apk包能被安装是须要被签名的,咱们直接运行的时候,是使用了系统默认的签名证书,当咱们要发布release包时,则须要使用属于我的或企业的签名。
  • 使用方法:
buildTypes {
    release {
        signingConfig {
    	    // 不建议将签名证书的信息写在这里,而应该是写在 properties 文件中,将其引入使用
            config {
                keyAlias keystoreProperties['keyAlias']
                keyPassword keystoreProperties['keyPassword']
                storeFile file(keystoreProperties['storeFile'])
                storePassword keystoreProperties['storePassword']
            }
        }
        ...
    }
}
复制代码

2.19 testCoverageEnabled

  • 类型:boolean
  • 描述:测试覆盖率,能够获取测试覆盖率的报告
  • 值得一提:记得将 minifyEnabled 置为 false,不然报告也会是以混淆后的类名出现。
  • 使用方法:

第一步:在 build.gradle 中开启 testCoverageEnabled

debug {
    testCoverageEnabled true
}
复制代码

第二步:链接上一台可用设备,由于咱们执行的测试代码是要基于设备的,若是不链接,测试阶段会报以下错

第三步:在 android studio 的 终端(即 Terminal)中输入下面这行命令,查看全部可运行任务。

小盆友是 mac 环境,因此 ./gradlew 开头。windows 的环境则直接使用 gradlew 便可。

./gradlew app:tasks
复制代码

输入运行后,能够看到图中高亮部分的可运行task。

咱们以驼峰式(即第一个字母加上后面每一个单词的首字母且以大写的形式)将其运行,代码以下

// create + 你的构建类型名(这里为debug) + CoverReport 
./gradlew app:cDCR
复制代码

运行完以后,就是查看测试报告的阶段了。咱们进入coverage目录,具体路径以下图所示。

在这里插入图片描述
最后用浏览器打开 index.html 文件,就能够看报告啦,以下图所示,由于小盆友的这个项目没有写测试代码,因此覆盖率为0。
在这里插入图片描述

2.20 useProguard

  • 类型:boolean
  • 描述:是否开启老是开启 proguard
  • 使用方法:
debug {
    useProguard true
}
复制代码

2.21 versionNameSuffix

  • 类型:String
  • 描述:追加在 versionName 以后
  • 使用方法:
debug {
    // 若是 versionName "1.0.0" ,则最终的版本名为 1.0.0.test
    versionNameSuffix ".test"
    .....
}
复制代码

2.22 zipAlignEnabled

  • 类型:boolean
  • 描述:是否开启zipAlign。会对应用程序进行字节对齐,对齐后会减小了运行应用程序时消耗的内存。
  • 使用方法:
debug {
    zipAlignEnabled true
    .....
}
复制代码

2.23 matchingFallbacks

  • 类型:List< String >
  • 描述:用于处理 本地依赖library 间 BuildType 的冲突。

matchingFallbacks 还能够处理 维度风味的 问题,但咱们这里先不讨论,后续的文章会介绍。

  • 使用方法:

一个东西的出现是为了处理至少一个问题,因此咱们须要先了解下这个问题是怎么产生的。

如上图所示,咱们的 主Module(通常是App),存在了三个构建类型,即咱们一开始所提的 “release”、“debug”、“local” 三种。

此时咱们在项目添加了一个 module 名字为 library,并依赖进咱们的app中。当咱们构建 “release”、“debug” 两种版本时,都不会有任何问题,由于 library 默认也提供了 “release”、“debug” 两种构建版本。

可是当咱们使用 “local” 时,便会出问题了,由于此时 gradle 的脚本也会默认选择 “library” 的 “local”,但 “library” 中并无。会报下面这样的错误

ERROR: Unable to resolve dependency for ':app@local/compileClasspath': Could not resolve project :lib:library.
Show Details
Affected Modules: app
复制代码

此时就须要帮 “local” 从 “library” 中选择一个可用的构建类型,则是经过 matchingFallbacks 进行设置。

铺垫了这么多,接下来就是怎么使用了,在 app 的 build.gradle 中添加以下代码便可。

local{
    matchingFallbacks = ['zinc','release']
    ...
}
复制代码

值得一提的是,咱们能够配置多个,gradle在编译的时候,会按照从头开始匹配的原则,例如这里的 “zinc” 会匹配不到,则匹配 “release”,由于 “release” 匹配到了,则会进行使用,中断后面的匹配。

三、buildTypes 中方法的意义

3.1 buildConfigField(type, name, value)

  • 描述:咱们能够在 BuildConfig 类中添加值,最终会在 BuildConfig 中添加以下一行代码。
// 值的注意的是 value 的值是原样放置,咱们经过使用方法一节来了解
<type> <name> = <value>
复制代码
  • 使用方法:
debug {
    // 能够经过 BuildConfig 进行获取
    buildConfigField('String', 'name', '"zinc"')
    buildConfigField('int', 'age', '26')
    .....
}
复制代码

最终会生成以下图的配置,咱们能够经过下面代码进行获取

String name = BuildConfig.name;
int age = BuildConfig.age;
复制代码

值的一提的是,咱们设置 String 类型的参数时,须要加上 "" 双引号(如例子中的name属性)。切记!

3.2 consumerProguardFile(proguardFile)

  • 描述:和上面分享的 2.2 小点的属性 consumerProguardFiles 是同样的做用。只是这里只能设置一个 混淆文件。
  • 使用方法:
debug {
    consumerProguardFile('consumer-rules.pro')
}
复制代码

3.3 consumerProguardFiles(proguardFiles)

  • 描述:和上面分享的 2.2 小点的属性 consumerProguardFiles 是同样的做用,并且也是多个混淆文件。
  • 使用方法:
debug {
    consumerProguardFile('consumer-rules.pro', 'zincPower-rules.pro',.....)
}
复制代码

3.4 externalNativeBuild(action)

  • 类型:ExternalNativeBuildOptions
  • 描述:这里咱们设置 ndk 编译过程的一些参数。分为 cmake 和 ndkBuild 两个参数。
  • 使用方法:
debug {
    externalNativeBuild {
        ndkBuild {
            // Passes an optional argument to ndk-build.
            arguments "NDK_MODULE_PATH+=../../third_party/modules"
        }
        // For ndk-build, instead use the ndkBuild block.
        cmake {
             // Passes optional arguments to CMake.
             arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang"
        
             // Sets a flag to enable format macro constants for the C compiler.
             cFlags "-D__STDC_FORMAT_MACROS"
        
             // Sets optional flags for the C++ compiler.
             cppFlags "-fexceptions", "-frtti"
        
             // Specifies the library and executable targets from your CMake project
             // that Gradle should build.
             targets "libexample-one", "my-executible-demo"
         }
    }
}
复制代码

cmake 具体参数 传送门
ndkBuild 具体参数 传送门

3.5 initWith(that)

  • 描述:会拷贝给定的 buildType(即参数的值)
  • 使用方法:
buildTypes {
    debug{
    }
    local{
    	// 会拷贝 debug 的配置
        initWith debug{
          	// 在这里进行咱们本身的配置
        }
    }
}
复制代码

3.6 proguardFile(proguardFile)

  • 描述:添加混淆文件,和 2.9小点 的功能一致,只是传入的是一个文件,这里就再也不赘述
  • 使用方法:
debug {
    proguardFile 'proguard-rules.pro'
}
复制代码

3.7 proguardFiles(files)

  • 描述:添加混淆文件,和 2.9小点 的功能一致,这里就再也不赘述
  • 使用方法:
debug {
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
复制代码

3.8 setProguardFiles(proguardFileIterable)

  • 描述:添加混淆文件,和 2.9小点 的功能一致,只是写法稍微不一样,这里就再也不赘述
  • 使用方法:
debug {
    proguardFiles = [getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro']
}
复制代码

3.9 resValue(type, name, value)

  • 描述:添加 value 资源
  • 使用用法:
debug {
    // 添加至 res/value,经过 R.string.age 获取
    resValue('string', 'age', '12 years old')
}
复制代码

4、写在最后

Gradle 的配置文件看起来好像挺乱,实际上是由于咱们没有进行总体的梳理。不少配置其实不是没有用,而是咱们没有对他有一个总体的了解,正所谓 “无知最可怕”

若是喜欢的话请给我一个赞,并关注我吧。文章中若有写的不妥的地方,请评论区或加我微信与我讨论吧,共同进步。

欢迎加我微信,进行更多的交流

若是以为文章有很大的帮助,快来赞扬一次吧😄
相关文章
相关标签/搜索