前言
根据我们上一篇的介绍,我们知道了项目的结构以及构建的流程,根据上面的知识,我们知道了构建的规则实际就是我们写在build.gradle的内容。gradle android插件读取这个文件的内容后,最后完成构建工作。在讲解实际内容前,我先提供一个网站给大家,因为gradle android 插件 是通过dsl语言编写的,所以我们需要知道在什么地方获取相应的api。
7 build.gradle文件分析
https://docs.gradle.org/3.5/dsl/
https://google.github.io/android-gradle-dsl/current/
第一个网站是gradle官方提供的dsl,第二个网站是google提供的dsl查询手册
7.1 根目录的build.gradle文件
我们来打开根目录下面的build.gradle文件,这个文件是整个项目的配置文件,我们一般是放置一些基础的配置。
上图是build.gradle文件的内容
7.1.1 buildscript
buildscript{} 这个是基础配置,所有的子模块都会读取到这个配置里面的内容,当构建开始的时候,就开始读取这个 buildscript{} 里面的内容。
repositories{} 这个模块的内容告诉gradle 去什么地址下载第三方的库。
jcenter() 代表 https://bintray.com/bintray/jcenter
mavenCentral() 代表使用maven的服务器 https://search.maven.org/
但是有一个问题就是上面的两个网站在中国访问速度慢
buildscript { repositories { maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'} } }
可以使用阿里云的maven服务
7.1.2 allprojects
allprojects 一般是配置所有模块的共同使用的内容。
allprojects { repositories { jcenter() } }
这个是默认的配置,代表所有的子modle都是从jcenter获取第三方包的。我建议大家可以改成下面的写法
allprojects { repositories { maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'} } }
7.1.3 gradle插件以及gradle版本的关系
在根目录上面的build.gradle的版本我们可以设置gradle 插件的版本号,初学者经常搞不懂插件与gradle的关系。特别是个版本之间的关系,下面我们来讲讲插件设置的方式。
最后的序号就是插件的版本号,注意插件不是gradle,插件是根据gradle特性编写为完成需求的jar包,插件依赖于gradle。
dependencies { classpath 'com.android.tools.build:gradle:2.3.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }
如果你使用的是2.3版本的插件,必须使用gradle3.3以上的版本。
如果你使用的是2.2版本的插件,必须使用gradle2.14.1以上的版本。
基本原则就是对照上面的表,看看你使用的是什么版本的插件。
那gradle的版本设置在哪里设置呢?我们打开gradle文件夹找到gradle-wrapper.properties文件,如下图所示
最后我再介绍一个方法,经常有同学说打开一个项目很久,其实就是去下载gradle.我们可以根据上面的这个表来手动下载gradle。然后放置到相应的文件夹内,下面的两张图片是插件的文件目录和gradle的文件目录
7.2 子项目的build.gradle
一般在稍微大一点的项目中,我们都按照业务逻辑分好不同的模块。根目录下的build.gradle是对所有模块起效果的基础配置,而每个模块下的build.gradle是这个模块的详细构建的配置,下面我们来学习一下有哪些内容。
上面的这张图片是默认的build的内容。我们看到内容可以分成三份。
7.2.1 apply
apply plugin: 'com.android.application'
这句话告诉gradle使用什么类型的插件进行构建。上面的是构建应用的,如果是构建库文件的是有下面的
apply plugin: 'com.android.library'
7.2.2 dependencies{} 依赖配置
这个模块是声明项目的依赖,为什么我们要配置依赖呢?我们的项目大部分需要使用第三方库,而第三库很有可能还有其他的依赖,比如说Okhttp。这个依赖的内容由gradle进管理,免除了开发者下载、导入、设置等繁琐的炒作。这个内容不是android gradle 插件提供了,是gradle提供的,也就是说不止android,java,c++,只要是使用gradle构建的项目都能够使用这个模块声明。
这个模块是声明项目的依赖,可以依赖本地的文件,远程的资源库,本地的library库。详细的参数我们可以查询gradle Dsl的工具页面。
https://docs.gradle.org/current/userguide/artifact_dependencies_tutorial.html
如果英语好的同学可以看到,gradle支持了4种依赖的模式。
- compile 意思是告诉gradle编译代码是需要使用的依赖。
- runtime 产品代码在运行时需要的依赖。
- testCompile 编译测试代码时所需要的依赖。
- testRuntime 运行测试时需要的依赖。
其中 runtime会包括compile的依赖。 testRuntime会包括testCompile的依赖。但是很遗憾的是,android gradle plugings不支持runtime,所以android只包含上面的compile、testCompile两种模式。
那为什么会有两种不一样的模式了,其实是这样的,比如在java Web中,编译的时候需要的是servlet的依赖,但是运行的时候,就由服务器的容器提供,所以需要分开来,但是在android中,基本上使用的依赖就是一起把类文件编译打包到apk,所以没有runtime与compile的区别。
7.2.2.1 compile 编译时导入依赖
远程依赖
compile是gradle依赖使用最多的关键字,在build.gradle中使用了compile后,gradle就会去repositories中加载,我们看看如果在我们的项目中使用了OKHTTP的写法是怎么写的呢?
compile 'com.squareup.okhttp3:okhttp:3.8.0'
这个是最简单的写法,我们刚开始从eclipse转到android studio开发的时候就知道整儿写了,但是世界实际这个一个简短的写法。规范的写法应用是这样。
compile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.8.0'
同步完成后,我们可以在External Libraries下面找到添加的依赖
)
本地依赖
gradle 提供了下载远程依赖包的能力,这个方式也是目前最流行的方式,但是考虑到国情等情况,我们也经常需要使用本地的jar包、AAR包、libery依赖。下面我们来学习这几种依赖的写法
本地jar包
compile fileTree(include: ['*.jar'], dir: 'libs')
上面这句话就把libs下面的jar包,导入到项目中,也就是绑定到项目的classPath.也可以单独制定某一个jar包。
compile files('libs/xxxx.jar')
上面的这两种方法都是导入jar包的方法,如果需要导入aar包,我们需要按照下面的来写。
本地aar包
repositories { flatDir { dirs 'libs' } }
增加一个本地的源目录。将aar文件放入libs文件夹。
compile(name: '不带后缀的文件名', ext: 'aar')
同步完成后就可以使用导入的类库了。
library依赖
我们可以在项目中创建不同的module,创建的model的时候我们可以选择创建一个不同的类型。
)
上图是我们创建一个新的module的时候可以选择的选项,通常我们选择的是第一个,代表这个是一个可执行的项目。第二个代码是一个libery库,它与一般的项目不同,libery项目不能运行,libery项目最后会生成一个aar包,aar包与jar包类似。jar包是将编译的class打包的压缩包,aar包不止包括了class还有项目的资源生成的压缩包。
上面我们学习了怎么依赖一个aar包,下面我们来学习一下怎么依赖一个library项目,常见的有两种方法:
1 编写代码依赖
在需要依赖的模块上面的build.gradle文件内,查找到dependencies{}模块。添加以下代码:
compile project(':名称')
在冒号后面输入模块的名称
2 ide添加依赖
我们在项目上面右键打开moduleseting
7.2.3 android{} 构建详细配置
android 模块的是该模块的详细设置,android app 的大部分的构建的内容都是在这个模块内配置的。
android { compileSdkVersion 24 buildToolsVersion "24.0.2" defaultConfig { applicationId "com.it520.x5webview" minSdkVersion 15 targetSdkVersion 24 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
上面是android studio为我们创建的内容。
compileSdkVersion 24
告诉 Gradle 用哪个 Android SDK 版本编译你的应用,建议使用最新的SDK 进行编译。在现有代码上使用新的编译检查可以获得很多好处,避免新弃用的 API ,并且为使用新的 API 做好准备。
buildToolsVersion "24.0.2"
构建工具的版本,其中包括了打包工具aapt、dx等等。这个工具的目录位于..your_sdk_path/build-tools/XX.XX.XX,注意这个工具和gradle版本有关系。
buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }
buildTypes 用来设置应用的构建版本。默认的情况会创建两个版本,1个版本是release(发布版),1个版本是debug(开发版)。默认的情况下,只显示了release的配置。我们一般都是在buildType中设置好相应的签名文件、打包加密方式、冗余资源等。
https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.BuildType.html#com.android.build.gradle.internal.dsl.BuildType:minifyEnabled
上面的文档是buildType支持的所有的属性
- applicationIdSuffix 包名的后缀
- versionNameSuffix 版本的后缀
上面两个是我们在区分不同版本的时候增加的后缀名称
- signingConfig
上面这个配置是设置打包的签名
- shrinkResources
- minifyEnabled
上面的配置是去除冗余资源
defaultConfig {…}
默认配置,这里的代码块配置的在后面的各个构建变体(这里理解成不同的版本)都能够使用,这里面设置的值,在不同的构建变体内还可以再修改成具体的值。
上面的配置是IDE默认生成的。了解默认的脚本后,我们来看看详细的配置。
7.2.3.1 签名配置 SigningConfig
但是在正式包的时候,我们是不能使用调试的签名文件的,我们需要使用对应的签名文件。
首先我们要生成一个签名文件,
生成完成后,我们要配置这个应用的签名,配置签名一般有以下几个参数,详细的参数请查看
https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.SigningConfig.html
上图的4个值分别是 签名的别名,签名的密码,签名的位置,签名的密码
signingConfigs { debug { } realse { keyAlias 'xmg' keyPassword '' storeFile file('/Users/kay/Desktop/release_key.jks') storePassword '' } }
定义了两种类型的签名配置。
设置好签名配置,我们要给不同类型的构建设置签名。
buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.realse } debug{ applicationIdSuffix ".debug" versionNameSuffix "huangkai" } }
在上面的代码,我们给发布版设置了签名配置。
为了验证签名配置的情况,我们切换到Terminal对话框,在对话框下输入以下命令
./gradlew assembleRelease
除了可以使用配置的情况,我们也可以使用ide来配置达到一样的效果。
7.2.3.2 定制版本 productFlavors
我们现在在中国开发要面对大量的渠道商(360市场、小米商店、应用宝),为了统计不同的渠道商,我们需要提供不同的版本。这样就会给开发者增加大量的开发任务,而且也出现代码管理的问题。原来在eclipse的环境下,我们需要将代码复制多份,再运行打包脚本,打包成不同的渠道包。但是现在使用gradle进行代码管理,我们就不需要在做这个了,我们可以使用gradle来定制不同的版本,最后gradle会根据一定的规则把代码或者资源进行融合,最后生成我们需要的apk。
在android{}模块内部增加以下的代码
productFlavors{ free{ } pay{ } }
我们定义了当前的应用有两个版本,一个是free(免费),pay(收费)。我们预计要打两个版本的包。这里组合起来有四个版本。
- freeDebug
- freeRelease
- payDebug
- payRelease
定制版本的资源合并
gradle把不同版本的文件夹下的资源进行合并与替换,假设free与pay版本的区别在与某个资源文件。
我们在src文件中创建相关的资源文件夹。
接着我们在各个资源夹中创建一个string.xml资源文件,接着编写以下内容
!!!! 注意,在各个资源文件夹下的内容要不一样才看得到区别。
接着我们编写一个activity放置在main文件夹内,在activity的布局显示这个字符串title。
在左下方选择相应的构建类型,比如说我们选择的是payDebug
编写代码完成后,我们可以使用命令行来构建相应的版本。
./gradlew assembleFreeRelease
总结一下,同名的资源文件可以存在不同的版本文件内。
定制版本的java合并
上面的例子我们是通过一个资源来区分应用的版本,在实际的开发中,也存在这样的情况,不同的版本可能有不一样的业务逻辑,所以我们可能需要在不同的版本里面处理java代码。
首先我们还是在之前的项目结构上面进行开发,这里有两个版本,一个free,一个pay。
首先我们先选择一个build variants,在这里我们选择payDebug。
选择完成后,我们打开pay文件夹,我们需要创建一个Activity。我们知道java代码再android studio下面默认是存放在java文件夹下的。所以我们需要创建一个Java文件夹。
同样的步骤我们在free文件夹也操作一遍
我们发现了free 和 pay 的Java文件夹颜色不一样,pay的变成了蓝色,free还是普通的黄色。
我们尝试新建一个class。
很明显在free文件上面没法新建类。为什么呢?
因为我们之前选择的payDebug,ide就只编译了pay文件夹下面的Java类。如果我们选择了freeDebug,情况就刚好相反。
我们在free 和 pay 下面创建了两个同名的activity,并指派了不同的界面。分别运行后,发现每次运行只能选其中一种显示。
接着我们在main文件夹下面创建一个类,Util。接着我们无论在free或者pay下面都无法创建同名的类了,均会提示我们重复创建类错误。
总结一下:
- 1 main 文件夹下有A类,那个其他版本的文件夹内不能有同名的类A
- 2 不同版本的相同的文件A类,运行的时候请选择相应的build variants
上面的例子是我们使用productFlavors合并了java代码。
7.2.3.3 定制版本组合 flavorDimensions
在项目中,我们可能会碰到这样的需求,我们可能需要对某个版本提供特殊的功能,但是这个功能与当前的定制版本代码差别不大,如果根据每个定制版本都再新建一个定制版本出来就优点复杂了。比如说我们根据上面的例子来说,当前的应用提供了两个定制版本,一个是pay,一个是free。但是项目在测试的时候,测试组希望根据版本提供有log消息和没有log消息的版本。根据之前的我们需要新建payLog,payNoLog,freeLog,freeNoLog等版本。看起来还行吧,但是如果不止两个而是5个版本,pay,free,….free5,而且log和noLog的区别可能就是几句代码。那个这个项目的结构就太过复杂了。这个时候,我们就可以使用定制版本组合。
定制版本组合怎么操作呢,我们根据需求将代码分成不同的组,不同的组代表不同的功能,组和组可以互相组合,最终形成需要的版本。相对于productFlavors,flavorDimensions是productFlavors的补充选择,可以让我们版本定制更灵活。
以上面的例子来说:
我们可以将版本的需求分成两个维度,一个是支付状态,一个是输出消息状态。
flavorDimensions "log","pay_status"
首先定义两个维度。下面我们要指定版本属于哪个维度。
productFlavors { withLog{ dimension "log" } noLog{ dimension "log" } free { dimension "pay_status" } pay { dimension "pay_status" } }
最后gradle会自动组合版本
7.2.3.4 定制版本依赖
我们在上面的内容学习了依赖的写法,但是之前我们学习依赖的时候,这个依赖的是对这个项目整体生效的。意思就是项目所有的版本都生效,但是在实际开发中,我们可能会碰到这样的情况,比如说我们开发一个应用,这个应用分成收费版本和免费版本。收费版本不需要显示广告。免费版本因为没有付费,需要显示广告。在这里我们需要对我们的定制版本的依赖做细化的区分。原来在eclipse的时候,我们只能通过复制多一份代码来进行实现。现在我们可以同过gradle实现。
free { dimension "pay_status" dependencies { freeCompile 'com.bm.photoview:library:1.4.1' } }
在上面的代码我们在版本定制内部添加了一个xxxxCompile的标签,这个意思就是告诉gradle是什么版本的依赖。xxxx是这个版本的名称。
7.2.3.5 packagingOptions 打包选项
我们可以使用这个参数来告诉Gradle什么文件打包到apk内,什么文件不打包,重复文件如何处理等。
- pickFirst 路径,如果文件匹配这个路径,只有第一个文件打包进apk
- Merge 合并两个文件进入apk,第二个文件会在第一个文件后
- Exclude 不打包的文件的路径
packagingOptions {
//以下文件不加入apk里
exclude ‘LICENSE.txt’
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/84428.html