相关文章:
- Android Gradle(一)Gradle的Android插件入门
- Android Gradle(二)签名配置和依赖管理
- Gradle核心思想(一)为什么现在要用Gradle?
- Gradle核心思想(二)Gradle入门前奏
- Gradle核心思想(三)Groovy快速入门指南
- Gradle核心思想(四)看似无用,实则重要的Gradle Wrapper
- Gradle核心思想(五)通俗易懂的Gradle插件讲解
- Gradle核心思想(六)自定义Gradle插件的三种方式
前言 {#前言}
本系列上一篇,我介绍了Gradle的Android插件的入门,这一篇来介绍一些Gradle进阶的内容,当然进阶内容非常多,这篇文章就总结一些相对重要的、常用的一些知识点,比如Gradle的签名配置和依赖管理。
Android签名文件配置 {#Android签名文件配置}
在一般公司中,当团队比较小的时候,App的签名信息都是放到项目中的,甚至会上传到github上,这样做很是方便。但随着团队人数的增多,这样做的风险会越来越大,因为签名信息是重要的资源,这样就不能将签名上传到github上,也就不应该在build.gradle中直接配置签名。
主要有以下的几种解决方法:
1.自定义一个签名配置文件
2.本地~/.gradle/gradle.properties文件中配置签名信息
自定义签名信息文件 {#自定义签名信息文件}
首先,在工程的目录下新建一个文件夹,内部存储签名文件和签名信息文件。签名文件为gradledemo.jks,签名信息文件为keystore.properties。keystore.properties中的配置如下所示。
|-----------------|-------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4
| STORE_FILE=../signfiles/gradledemo.jks KEY_ALIAS=gradle STORE_PASSWORD=jinjiesanbuqu KEY_PASSWORD=jinjiesanbuqu
|
当然不要忘了在.gitignore中将gradledemo.jks和keystore.properties忽略掉。接着在模块build.gradle中进行配置,如果还不清楚什么是模块build.gradle和项目build.gradle,看Android Gradle (一)Gradle的Android插件入门这篇文章。
在模块build.gradle中加入如下代码。
|------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| apply plugin: 'com.android.application' android { ... } def setSigningProperties(){ def propFile = file('../signfiles/keystore.properties') if (propFile.canRead()){ def Properties props = new Properties() props.load(new FileInputStream(propFile)) if (props!=null && props.containsKey('STORE_FILE') && props.containsKey('STORE_PASSWORD') &&props.containsKey('KEY_ALIAS') && props.containsKey('KEY_PASSWORD')) { android.signingConfigs.release.storeFile = file(props['STORE_FILE']) android.signingConfigs.release.storePassword = props['STORE_PASSWORD'] android.signingConfigs.release.keyAlias = props['KEY_ALIAS'] android.signingConfigs.release.keyPassword = props['KEY_PASSWORD'] } else { throw new Exception("some key missing") } }else { throw new Exception("keystore.properties not found:" + propFile.absolutePath) } }
|
setSigningProperties方法用于读取keystore.properties文件中的签名文件的信息。
最后在模块build.gradle中的signingconfigs块中调用setSigningProperties方法就可以了。
|------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10
| apply plugin: 'com.android.application' android { ... signingConfigs { release { setSigningProperties() } } }
|
本地添加签名信息文件 {#本地添加签名信息文件}
还可以将签名文件和签名信息文件放到本地中。比如签名文件放到/.gradle/gradledemo.jks,签名信息文件放到/.gradle/keystore.properties。这样签名文件和签名信息文件都不会提交到github上。
keystore.properties的内容如下。
|-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4
| GRADLEDOME_RELEASE_STORE_FILE=~/.gradle/release-key.keystore GRADLEDOM_RELEASE_KEY_ALIAS=key-alias GRADLEDOM_RELEASE_STORE_PASSWORD=pass GRADLEDOM_RELEASE_KEY_PASSWORD=pass
|
在模块build.gradle中的signingconfigs块中配置签名,如下所示。
|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8
| signingConfigs { release { storeFile file(GRADLEDOME_RELEASE_STORE_FILE) storePassword GRADLEDOME_RELEASE_STORE_PASSWORD keyAlias GRADLEDOME_RELEASE_KEY_ALIAS keyPassword GRADLEDOME_RELEASE_KEY_PASSWORD } }
|
除了这两点,还可以将签名文件和签名信息文件放在专门打包的服务器上,在打包的时候读取即可。这个涉及的内容就多了,就不在本文进行说明了。
Gradle的库依赖 {#Gradle的库依赖}
现在一个Android项目都是需要去引入其他的库,比如jar、aar、Module等等,现在我们分别来介绍下。下面例子的代码如果不特意说明均是写在模块build.gradle中的。
Gradle的本地库依赖 {#Gradle的本地库依赖}
关于jar依赖可以按照如下这么写,可以指定一个也可以指定多个jar。
|-------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5
| //依赖引入libs下所有的jar implementation fileTree(dir:'libs',include:['*.jar']) //指定依赖某一个或几个jar implementation files('libs/XXX.jar','libs/XXX.jar')
|
aar依赖需要额外增加一些语句,如下所示。
|------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12
| android { ... repositories { flatDir { dirs "libs" } } } dependencies { implementation fileTree(dir:'libs',include:['*.aar']) implementation(name:'XXX',ext:'aar') }
|
Gradle的本地Module依赖 {#Gradle的本地Module依赖}
当项目中有多个Module时,我们需要在settings.gradle中引入,如下所示。
|-------------|---------------------------------------------------------|
| 1 2
| include ':app' include ':library1', ':library2'
|
接着在模块build.gradle引入。
|-----------|---------------------------------------------|
| 1
| implementation project(':library1')
|
Gradle的远程库依赖 {#Gradle的远程库依赖}
当在Android Studio中新建一个项目时,会在项目build.gradle有如下代码:
|------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.4.0' } } allprojects { repositories { google() jcenter() } }
|
这些代码都是默认的,在buildscript和allprojects块中,通过repositories来引入谷歌的Maven库和JCenter库。首先会从谷歌的Maven库去寻找相应的库,如果找不到会从JCenter库中去寻找。
然后在模块build.gradle加入如下的代码,就可以引入远程库。
|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3
| implementation group:'com.android.support',name:'appcompat-v7',version:'28.0.0' //简写 implementation 'com.android.support:appcompat-v7:28.0.0'
|
Gradle的库依赖管理 {#Gradle的库依赖管理}
随着Gradle依赖的库越来越多,那么必然会产生一些问题,比如依赖冲突的问题,为了解决依赖冲突,我们需要先了解Gradle的库依赖管理的几个技术点。
Gradle的依赖传递 {#Gradle的依赖传递}
Gradle默认是支持依赖传递的,所以当用到Gradle依赖时一定会涉及到它,是必须要知道的一个知识点。
那什么是依赖传递呢?举一个最简单的例子。
projectC依赖projectB,projectB依赖projectA,那么projectC就依赖了projectA。
依赖传递会产生一些问题,比如重复依赖、依赖错误等问题,那么我们可以通过transitive来禁止依赖传递。
|---------------|----------------------------------------------------------------------|
| 1 2 3
| implementation('com.xxx.xxx:xxx:3.6.3') { transitive false }
|
上面禁止了com.xxx.xxx:xxx:3.6.3库的依赖传递,还可以使用如下语句来关闭当前模块的所有库的依赖传递:
|---------------|---------------------------------------------------|
| 1 2 3
| configurations.all { transitive = false }
|
只不过这样就需要手动添加当前模块的每个库的依赖项,一般不会这么做。
Gradle的依赖检查 {#Gradle的依赖检查}
有了依赖检查,我们可以解决依赖产生的问题。依赖检查有很多种方式,分别来介绍下。
使用Gradle的命令行 {#使用Gradle的命令行}
可以直接使用Gradle的命令行来进行依赖检查,拿Windows平台来说,使用cmd进入项目的根目录,执行gradle :app:dependencies即可,其中app是我们新建工程时默认的模块的名称。日志输出很多,下面截取一部分:
|---------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| +--- com.android.support:appcompat-v7:28.0.0 | +--- com.android.support:support-annotations:28.0.0 //1 | +--- com.android.support:support-compat:28.0.0 //2 | | +--- com.android.support:support-annotations:28.0.0 | | +--- com.android.support:collections:28.0.0 | | | \--- com.android.support:support-annotations:28.0.0 | | +--- android.arch.lifecycle:runtime:1.1.1 | | | +--- android.arch.lifecycle:common:1.1.1 | | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 //3 | | | +--- android.arch.core:common:1.1.1 | | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 | | \--- com.android.support:versionedparcelable:28.0.0 | | +--- com.android.support:support-annotations:28.0.0 | | \--- com.android.support:collections:28.0.0 (*)
|
上面是appcompat-v7:28.0.0库的依赖树的一小部分,appcompat-v7:28.0.0依赖了注释1处和注释2的库,注释2处的库又依赖了com.android.support:support-annotations:28.0.0和com.android.support:collections:28.0.0,因此当我们引入appcompat-v7:28.0.0时,会自动下载所有它依赖传递的库。注释3处说明,Gradle在依赖传递时,会自动提升依赖传递的库的版本,默认使用最高版本的库。
使用Gradle面板 {#使用Gradle面板}
除了命令行,还可以使用Android Studio中的右侧的Gradle面板,找到app模块,展开后找到help目录中的dependencies,如下图所示。
双击或者右键选择第一个选项即可执行命令,日志就会在AS中Run窗口中打印出来。
现在再举个例子,拿我们熟悉的retrofit举例,在模块build.gradle中引入retrofit:
|-----------|----------------------------------------------------------------|
| 1
| implementation 'com.squareup.retrofit2:retrofit:2.6.0'
|
执行依赖检查命令,打印的关于retrofit的日志如下:
|---------------|----------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3
| +--- com.squareup.retrofit2:retrofit:2.6.0 | \--- com.squareup.okhttp3:okhttp:3.12.0 | \--- com.squareup.okio:okio:1.15.0
|
可以很清楚看到retrofit:2.6.0依赖okhttp:3.12.0,而okhttp:3.12.0依赖okio:1.15.0。
这时我们使用3.1小节的transitive试试,修改build.gradle:
|---------------|---------------------------------------------------------------------------------------|
| 1 2 3
| implementation ('com.squareup.retrofit2:retrofit:2.6.0') { transitive false }
|
执行依赖检查命令,打印的关于retrofit的日志如下:
|-----------|----------------------------------------------------|
| 1
| +--- com.squareup.retrofit2:retrofit:2.6.0
|
使用Gradle View插件 {#使用Gradle-View插件}
如果你觉得前两种方式查看不方便、不直观,还可以使用Android Studio的Gradle View插件。
在AS中选择File-->Settings-->Plugins中搜索gradle view,找到Gradle View插件安装并重启AS,如下图所示。
接下来选择View--->Tools Windows--Gradle View,这时就可以在AS的底部发现Gradle View窗口,里面会显示当前项目的所有依赖树,如下图所示。
Gradle的依赖冲突 {#Gradle的依赖冲突}
依赖冲突产生的原因多是库的版本问题,举个例子,如果在build.gradle中这么写:
|-------------|---------------------------------------------------------------------------------------------------------------|
| 1 2
| implementation 'com.squareup.retrofit2:retrofit:2.6.0' implementation 'com.squareup.okio:okio:1.14.0'
|
在3.2小节中,我们知道retrofit:2.6.0依赖的okio的版本是1.15.0,而这里引入的okio的版本为1.14.0,引入的版本不同就会产生依赖冲突。依赖冲突的解决的关键有两点,一个是Gradle的依赖检查,这个在3.2小节已经讲过了,另一个是利用Gradle的关键字,合理利用它们是解决依赖冲突的关键,在3.1小节已经介绍了 transitive,现在介绍其余的。
force {#force}
有时候我们不是想要排除某个库,而是需要强制使用统一的库的版本,force可以强制设置模块的库的版本,在模块build.gradle中加入如下代码。
|-------------------------|-----------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8
| configurations.all { resolutionStrategy { force 'com.squareup.okio:okio:2.1.0' } } dependencies { ... }
|
强制当前模块的okio的版本为2.1.0,使用依赖检查来查看下retrofit的依赖:
|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4
| +--- com.squareup.retrofit2:retrofit:2.6.0 | \--- com.squareup.okhttp3:okhttp:3.12.0 | \--- com.squareup.okio:okio:1.15.0 -> 2.1.0 \--- com.squareup.okio:okio:1.14.0 -> 2.1.0
|
可以看到okio的版本都被强制升级到了2.1.0,这样就可以解决一些依赖冲突的问题。
exclude {#exclude}
有些时候需要排除库依赖传递中涉及的库,此时不能靠关闭依赖传递来解决问题,这时可以使用exclude。
我们知道com.android.support:appcompat-v7:28.0.0依赖于com.android.support:support-annotations:28.0.0、com.android.support:support-compat:28.0.0、com.android.support:cursoradapter:28.0.0等库,这时我们不想再依赖support-annotations库,可以这么写。
|---------------------|--------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6
| configurations { all*.exclude group: 'com.android.support', module: 'support-annotations' } dependencies { ... }
|
使用依赖检查来查看com.android.support:appcompat-v7:28.0.0的依赖:
|------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10
| +--- com.android.support:appcompat-v7:28.0.0 | +--- com.android.support:support-compat:28.0.0 | | +--- com.android.support:collections:28.0.0 | | +--- android.arch.lifecycle:runtime:1.1.1 | | | +--- android.arch.lifecycle:common:1.1.1 | | | \--- android.arch.core:common:1.1.1 | | \--- com.android.support:versionedparcelable:28.0.0 | | \--- com.android.support:collections:28.0.0 | +--- com.android.support:collections:28.0.0 | +--- com.android.support:cursoradapter:28.0.0
|
和3.2节的日志对比下,可以发现com.android.support:appcompat-v7:28.0.0不再依赖com.android.support:support-annotations:28.0,目的达到了。
感谢 {#感谢}
https://www.jianshu.com/p/c602e6c493ce
https://blog.csdn.net/ouyang_peng/article/details/82590820
https://www.jianshu.com/p/82de510b40b9
https://blog.csdn.net/zjpp2580369/article/details/82707581
http://blog.fidroid.com/post/gradle/zai-gradlezhong-yin-cang-qian-ming-zheng-shu-xiang-guan-xin-xi
参考链接:http://liuwangshu.cn/application/android-gradle/2-gradle-dependency.html