logo头像
Snippet 博客主题

android 库依赖问题

android 库依赖问题

原因

  1. 库版本不一致 com.android.support的包版本号要保持一致 ,google gcm 与 firebase不一致
  2. 重复库 开源库中 包含 本项目中的库

解决方法

  1. 修改自己项目中的com.android.support的版本号,与所依赖的库版本号一致,但是当我们依赖的库中的com.android.support版本号有好几个版本就不行了。(不推荐)

  2. 依赖第三方库时候排除掉对com.android.support包的依赖,这样自己的项目随便依赖什么版本都可以,但是这种方法需要你先找到哪些库存在冲突

  3. 通过groovy脚本强制修改冲突的依赖库版本号 (推荐)

解决问题

查看依赖报告

命令行 ./gradlew :app:dependencies

查看 项目库依赖关系

排除传递性依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

+--- com.android.support:support-v4:27.1.1
| +--- com.android.support:support-compat:27.1.1
| | +--- com.android.support:support-annotations:27.1.1
| | \--- android.arch.lifecycle:runtime:1.1.0
| | +--- android.arch.lifecycle:common:1.1.0
| | \--- android.arch.core:common:1.1.0
| +--- com.android.support:support-media-compat:27.1.1
| | +--- com.android.support:support-annotations:27.1.1
| | \--- com.android.support:support-compat:27.1.1 (*)
| +--- com.android.support:support-core-utils:27.1.1
| | +--- com.android.support:support-annotations:27.1.1
| | \--- com.android.support:support-compat:27.1.1 (*)
| +--- com.android.support:support-core-ui:27.1.1
| | +--- com.android.support:support-annotations:27.1.1
| | +--- com.android.support:support-compat:27.1.1 (*)
| | \--- com.android.support:support-core-utils:27.1.1 (*)
| \--- com.android.support:support-fragment:27.1.1
| +--- com.android.support:support-compat:27.1.1 (*)
| +--- com.android.support:support-core-ui:27.1.1 (*)
| +--- com.android.support:support-core-utils:27.1.1 (*)
| +--- com.android.support:support-annotations:27.1.1
| +--- android.arch.lifecycle:livedata-core:1.1.0
| | +--- android.arch.lifecycle:common:1.1.0
| | +--- android.arch.core:common:1.1.0
| | \--- android.arch.core:runtime:1.1.0
| | \--- android.arch.core:common:1.1.0
| \--- android.arch.lifecycle:viewmodel:1.1.0
+--- com.android.support:appcompat-v7:27.1.1
| +--- com.android.support:support-annotations:27.1.1
| +--- com.android.support:support-core-utils:27.1.1 (*)
| +--- com.android.support:support-fragment:27.1.1 (*)
| +--- com.android.support:support-vector-drawable:27.1.1
| | +--- com.android.support:support-annotations:27.1.1
| | \--- com.android.support:support-compat:27.1.1 (*)
| \--- com.android.support:animated-vector-drawable:27.1.1
| +--- com.android.support:support-vector-drawable:27.1.1 (*)
1
2
3
4
5

这里对gradle dependencies中的->、 (*)进行解释
固定版本: 唯一的依赖
固定版本(*):还存在该库其他版本的依赖或者间接依赖,并且默认选择(*)所标注的版本。这里rxjava版本就是使用rxbinding里的2.0.2
版本1->版本2(*):还存在该库其他版本的依赖或者间接依赖,并且并且选择版本2。这里rxandroid版本就是使用2.0.1

强制制定一个版本

gradle会自动帮我们强制依赖最高版本的jar包

修改默认解决策略方法,不然很难发现版本冲突      

取消gradle的默认高版本统一依赖,在bulid.gradle中添加:

//取消gradle默认统一使用高版本依赖的策略(gradle默认依赖冲突解决策略)

1
2
3
4
5
configurations.all{
resolutionStrategy{
failOnVersionConflict()
}
}

排除传递性依赖的方法如下

1
2
3
4
compile('org.hibernate:hibernate-core:3.6.3.Final'){
exclude group:"org.slf4j",module:"slf4j-api"
//transitive=false
}

强制制定一个版本

1
2
3
4
5
6

configurations.all{
resolutionsStrategy{
force 'org.slf4j:slf4j-api:1.7.24'
}
}

依赖方式

依赖类型 意义
Compile 默认配置,该依赖会参与编译并且打包到所有的build type以及flavors的apk中
Provided 对所有的build type以及flavors来说只在编译时使用,只参与编译并不打包到最终apk
APK 只会打包到apk文件中而不参与编译,所以不能在代码中直接调用jar中的类或方法,否则在编译时会报错
- - - -
Test compile 仅仅是针对单元测试代码编译以及最终打包测试apk时有效,而对正常的debug或者release apk包不起作用。
Debug compile 仅仅针对debug模式的编译和最终的debug打包时有效。
Release compile 仅仅针对release模式的编译和最终的release打包时有效

依赖远程文件

compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

依赖本地文件

当前模块下libs文件夹下的全部jar文件
compile fileTree(include: ['*.jar'], dir: 'libs')

指定路径下的全部jar文件
compile fileTree(dir: '../librarymodule/libs', include: '*.jar')

加载aar文件

在项目build.gradle中 添加

1
2
3
4
5
repositories {
flatDir {
dirs 'libs'
}
}

这意味着系统将在libs目录下搜索依赖。同样的如果你愿意的话可以加入多个目录。这里系统直接加载libs文件夹下的aar文件

compile(name: 'aar的名字(不用加后缀)', ext: 'aar')

依赖本地库工程

compile project(':librarymodule')

冲突的解决方法

先来看看几种不同的写法对库的加载有何区别

// 下载包含该库在内的其他所依赖的所有库
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

// 只下载该库,其他所依赖的所有库不下载
compile ‘io.reactivex.rxjava2:rxandroid:2.0.1@aar’

// 在使用@aar的前提下还能下载其他依赖库,则需要添加transitive=true的条件
compile ("io.reactivex.rxjava2:rxandroid::2.0.1@aar") { transitive=true }

// 去除某一个依赖库
compile ("io.reactivex.rxjava2:rxandroid:$rootProject.ext.rxandroid") { transitive=true exclude group: 'io.reactivex.rxjava2', module: 'rxjava' }

configurations

configurations - 项目中的所有rxjava2引用都去除

configurations { all*.exclude group: 'io.reactivex.rxjava2', module: 'rxjava' }

或者

configurations { compile.exclude module: 'rxjava' }

configurations DSL还可以通过Force强制约束某个库的版本,比如我这里将appcompat-v7包限定为25.1.0

1
2
3
4
5
configurations.all {
resolutionStrategy {
force "com.android.support:appcompat-v7:25.1.0"
}
}

外部配置依赖版本

我们新建一个config.gradle作为配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

ext {
androidGradleVersion = '2.3.1'
AndroidSupportVersion = '25.3.1'
AndroidConstraintLayoutVerson = '1.0.2'
compileSdkVersion = 25
buildToolsVersion = '25.0.2'

defaultConfig = [
applicationId : "com.renyu.gradledemo",
minSdkVersion : 15,
targetSdkVersion : 25,
versionCode : 1,
versionName : "1.0"
]
}

其中defaultConfig是一个map键值对,有别于上方的公共配置,这样看起来更清晰简洁

这里我们需要使用apply from来引用config.gradle。同理当你的gradle脚本太大的时候,你可以按照具体任务类型将一个大gradle脚本拆分成几个子脚本,然后分别apply from引入到主脚本中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 这里的apply是为了让子模块使用
apply from: "config.gradle"

buildscript {
repositories {
jcenter()
}
dependencies {
// root下build.gradle使用
apply from: "config.gradle"
classpath "com.android.tools.build:gradle:$androidGradleVersion"

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}

再看看app模块下的build.gradle的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
apply plugin: 'com.android.application'

android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId rootProject.ext.defaultConfig.applicationId
minSdkVersion rootProject.ext.defaultConfig.minSdkVersion
targetSdkVersion rootProject.ext.defaultConfig.targetSdkVersion
versionCode rootProject.ext.defaultConfig.versionCode
versionName rootProject.ext.defaultConfig.versionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile "com.android.support:appcompat-v7:$rootProject.ext.AndroidSupportVersion"
compile "com.android.support.constraint:constraint-layout:$rootProject.ext.AndroidConstraintLayoutVerson"
testCompile 'junit:junit:4.12'
}

layout进行模块化分包

对layout进行模块化分包

main模块与main2模块他们的布局是相互独立保存的,没有堆叠在一起。
那么这个是怎么做到的呢?之前大家从eclipse直接转项目到Android Studio上的时候,

不知道有没有注意到在app模块下的build.gradle有一个DSL叫sourceSets,
通过修改sourceSets中的属性,可以指定哪些源文件(或文件夹下的源文件)要被编译,哪些源文件要被排除。

Gradle就是通过它实现项目的布局定义。
Android Studio插件默认实现了两个sourceSet:main和test。
每个sourceSet都提供了一系列的属性,通过修改这些属性,可以定义该sourceSet所包含的源文件,比如java.srcDirs,res.srcDirs

1
2
3
4
5
6
7
8
9
10
sourceSets {
main {
java
res
}
test {
java
res
}
}

实现 步骤

  1. 按照自己的项目需求建立layout目录,例如本文就是/alllayouts/main/layout与/alllayouts/main2/layout
    在module对应的build.gradle下添加sourceSets配置
1
2
3
4
5
6
7
8
9
sourceSets {
main {
res.srcDirs = [
'src/main/res/alllayouts/main',
'src/main/res/alllayouts/main2',
'src/main/res'
]
}
}

多渠道打包

NDK篇

abiFilters可以优先适配需要适配的cpu,其他做兼容处理。
如本例我们放置了armeabi、armeabi-v7a、x86三种类型CPU的so,其他的就让手机自己去做兼容处理去了

1
2
3
4
ndk {
//选择要添加的对应cpu类型的.so库。
abiFilters 'armeabi', 'armeabi-v7a', 'x86' // 还可以添加 'armeabi-v8a', 'x86_64', 'mips', 'mips64'
}

编译出错查看详情

输出较详细的信息
gradlew compileDebug --stacktrace

后面加上-info或者-debug的选项得到更详细的信息

gradlew compileDebug --stacktrace -info

或者
gradlew compileDebug --stacktrace -debug

gradlew compileDebugSources --stacktrace -info

支付宝打赏 微信打赏

打赏