对于一个gradle 项目,最基础的文件配置如下:
一个项目有一个setting.gradle、包括一个顶层的 build.gradle文件、每个Module (如app)都有自己的一个build.gradle文件。
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
}
}
allprojects{
repositories{
jcenter()
}
}
其中:
协作开发中引用AAR是比较正常的事情,这一条属于基本技能。引用也是十分简单的,直接把aar文件放到libs目录下,然后在gradle下面配置一行:
repositories{
flatDir{
dirs 'libs'
}
}
注意:外层的repositories不能少,然后直接就可以在dependencies中添加引用,注意单引号
compile(name: 'widget2-debug', ext: 'aar')
直接依靠gradle的语法来实现版本号的修改,分离主版本子版本,根据自己的逻辑进行修改。
def versionMajor = 2
def versionMinor = 1
def versionPatch = 0
android {
...
defaultConfig {
...
versionCode versionMajor * 100 + versionMinor * 10 + versionPatch
versionName "${versionMajor}.${versionMinor}.${versionPatch}"
}
}
使用applicationidsuffix可以为debug版本添加一个后缀到你的applicationid上。这个小技巧可以让我们在同一台设备上安装多个版本的apk,不用频繁卸载。
buildTypes {
debug {
applicationIdSuffix ".debug"
}
...
}
在现在越来越大的项目中,各种Module,子Module,引用版本不一致导致经常需要同步下载,而且一旦想要升级插件,support包之类的,可能有好多个需要同时升级。使用Gradle,我们也能做到这一点。首先在最外层的根build.gradle中,在ext块内定义一个版本
ext {
supportLibVer = "24.2.1"
}
这样我们就能在需要的地方引用了
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile "com.android.support:appcompat-v7:$rootProject.ext.supportLibVer"
compile "com.android.support:design:$rootProject.ext.supportLibVer"
...
}
包版本可以这么玩,其他的所有配置其实都可以这么玩,我们可以把配置抽成一个单独的gradle文件,里面就一个ext block。
ext {
androidPluginVer = "2.1.3"
compileSdkVer = 24
buildToolsVer = "24.0.2"
minSdkVer = 14
targetSdkVer = 24
supportLibVer = "24.2.1"
}
我们把这个命名成config.gradle,然后要做的就是让子module都能引用到这个,简单的做法就是直接让刚才的root gradle文件引用这个gradle配置文件。
这里有一点坑就是看你自己创建的gradle目录在哪一级,需要定位到才能找得到 不然会出错,这里我是在最外层,所以加了两处,另外改ext属性,需要手动同步一下,直接跑的话并不会自动同步,这是最关键的一点。
buildscript {
apply from: 'config.gradle'
...
}
subprojects {
apply from: '../config.gradle'
}
使用的话和前面的ext属性差不多,加不加rootProject都可以跑得动
如果我们要将一个module编译成library让其他的项目引用,我们需要在该module的bubild.gradle中将plugin设置为如下plugin:
apply plugin: 'com.android.library'
可以通过以下方式加快gradle 的编译:
org.gradle.parallel=true
org.gradle.daemon=true
org.gradle.jvmargs=-Xms256m -Xmx1024m
引用的时候在setting文件中include即可。
在编译的时候,我们可能会有很多资源并没有用到,此时就可以通过shrinkResources来优化我们的资源文件,除去那些不必要的资源。
某些情况下,一些资源是需要通过动态加载的方式载入的,这时候我也需要像 Progard 一样对我们的资源进行keep操作。方法就是在res/raw/下建立一个keep.xml文件,通过如下方式 keep 资源:
Gradle3.4之前的版本使用如下方式添加依赖:
dependencies {
compile 'commons-httpclient:commons-httpclient:3.1'
compile 'org.apache.commons:commons-lang3:3.5'
}
Gradle 3.4+后使用如下方式添加依赖:
dependencies {
api 'commons-httpclient:commons-httpclient:3.1'
implementation 'org.apache.commons:commons-lang3:3.5'
}
其中api和implementation两种依赖的不同点在于:它们声明的依赖其他模块是否能使用。
classpath一般是添加 buildscript 本身需要运行的东西,buildscript是用来加载gradle脚本自身需要使用的资源,可以声明的资源包括依赖项、第三方插件、maven仓库地址等,classpath 声明的依赖,不会编译到最终的 apk 里面。
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
classpath 'com.jakewharton:butterknife-gradle-plugin:8.2.1'
}
}
Gradle log级别如下:
public enum LogLevel {
DEBUG,
INFO,
LIFECYCLE,
WARN,
QUIET,
ERROR
}
Gradle log输出开关选项:
开关选项 | 输出的日志级别 |
---|---|
-d, --debug | DEBUG及更高级别(全部日志) |
-i, --info | INFO及更高级别 |
-q, --quiet | Log errors only |
-w, --warn | WARN及更高级别 |
logger.quiet('quiet 日志')
logger.error('error 日志')
logger.warn('warn 日志')
logger.lifecycle('lifecycle 日志')
logger.info('info 日志')
logger.debug('debug 日志')
错误特征:
14:37 Gradle sync started
14:37 Gradle sync failed: 'shadows-core-3.0' already disposed:
14:37 Gradle sync completed
14:39 Gradle sync started
14:39 Gradle sync failed: 'robolectric-resources-3.0' already disposed:
14:40 Gradle sync completed
解决方法:
./gradlew clean
Restart Android stduio
编译debug版本时打开了混淆开关,按如下方式修改:
buildTypes {
debug {
testCoverageEnabled = true
debuggable true
minifyEnabled false //值改为false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
}
......
}
以Android Studio IDE为例说明:
在Android Studio中打开项目,在其Terminal窗口中执行如下命令:
./gradlew build --stacktrace 2>logerr.txt
或者
./gradlew build --stacktrace >logs.txt 2>logerr.txt //不输入任何编译信息
然后进入项目的根目录中查看logerr.txt,可以发现第一行即为出错的位置,如下图:
出现该问题时其实已经提示了解决方法“You should manually set the same version via DependencyResolution.”,具体解决方法是在根目录的build.gradle中添加如下代码:
subprojects {
project.configurations.all {
resolutionStrategy.eachDependency { details ->
if (details.requested.group == 'com.tbuonomo.andrui'
&& !details.requested.name.contains('multidex') ) {
details.useVersion '23.1.1' //指定要使用的版本号
}
}
}
}
出现这个问题一般是因为解压gradle zip(如gradle-4.6-all.zip)解压失败,可以进入到.gradle的目录中查看一下gradle zip文件的大小,如下:
可以看到gradle-4.6-all.zip只有64K,正常情况下会有100多M。可以从如下几个方面解决问题:
如下面问题:
* What went wrong:
Execution failed for task ':app:processDevDebugManifest'.
> Manifest merger failed : Attribute application@appComponentFactory value=(android.support.v4.app.CoreComponentFactory) from [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91
is also present at [androidx.core:core:1.0.0] AndroidManifest.xml:22:18-86 value=(androidx.core.app.CoreComponentFactory).
Suggestion: add 'tools:replace="android:appComponentFactory"' to element at AndroidManifest.xml:17:5-70:19 to override.
可以使用如下gradle命令来定位:
./gradlew :app:processDevDebugManifest --stacktrace 或 ./gradlew :app:processDebugManifest --stacktrace
定位出的信息如下:
/Users/**/project name/app/src/main/AndroidManifest.xml:22:18-91 Error:
Attribute application@appComponentFactory value=(android.support.v4.app.CoreComponentFactory) from [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91
is also present at [androidx.core:core:1.0.0] AndroidManifest.xml:22:18-86 value=(androidx.core.app.CoreComponentFactory).
Suggestion: add 'tools:replace="android:appComponentFactory"' to element at AndroidManifest.xml:17:5-70:19 to override.
See http://g.co/androidstudio/manifest-merger for more information about the manifest merger.
./gradlew build -Dhttp.socketTimeout=60000 -Dhttp.connectionTimeout=60000
默认http.socketTimeout为10s,http.connectionTimeout为30s
如果您使用的是gradle 4.6或更高版本,请使用以下属性:
./gradlew build -Dorg.gradle.internal.http.socketTimeout=60000 -Dorg.gradle.internal.http.connectionTimeout=60000
log:
Unable to resolve dependency for ':app@xxPreview/compileClasspath': Could not resolve project :library.
Could not resolve project :library.
Required by: project :app
> Unable to find a matching configuration of project :library:
- Configuration 'debugApiElements':
- Required com.android.build.api.attributes.BuildTypeAttr 'preview' and found incompatible value 'debug'.
- Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
- Found com.android.build.gradle.internal.dependency.VariantAttr 'debug' but was't required.
- Required org.gradle.api.attributes.Usage 'java-api' and found compatible value 'java-api'.
- Required versionCode 'xiaomi' but no value provided.
- Configuration 'debugRuntimeElements':
- Required com.android.build.api.attributes.BuildTypeAttr 'preview' and found incompatible value 'debug'.
- Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
- Found com.android.build.gradle.internal.dependency.VariantAttr 'debug' but wasn't required.
- Required org.gradle.api.attributes.Usage 'java-api' and found incompatible value 'java-runtime'.
- Required versionCode 'xiaomi' but no value provided.
- Configuration 'releaseApiElements':
- Required com.android.build.api.attributes.BuildTypeAttr 'preview' and found incompatible value 'release'.
- Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
- Found com.android.build.gradle.internal.dependency.VariantAttr 'release' but wasn't required.
- Required org.gradle.api.attributes.Usage 'java-api' and found compatible value 'java-api'.
- Required versionCode 'xiaomi' but no value provided.
- Configuration 'releaseRuntimeElements':
- Required com.android.build.api.attributes.BuildTypeAttr 'preview' and found incompatible value 'release'.
- Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
- Found com.android.build.gradle.internal.dependency.VariantAttr 'release' but wasn't required.
- Required org.gradle.api.attributes.Usage 'java-api' and found incompatible value 'java-runtime'.
- Required versionCode 'xiaomi' but no value provided.
原因:app中buildTypes集合不是library的buildTypes集合子集,即app中buildType属性preview在依赖的library中找不到。
解决方法:
https://juejin.im/entry/5b17bce0e51d45067b059980
在gradle命令行加上–stacktrace,报错后会打印出堆栈信息
请参考第10节
gradlew assembleDebug -Dorg.gradle.daemon=false -Dorg.gradle.debug=true
或
gradlew assembleDebug -Dorg.gradle.debug=true --no-demo