转载

Android导包全攻略

在我们开发安卓项目的时候,不会所有的功能都自己去造轮子,经常要使用到各种的其他包,其中有谷歌给我们提供的各种 support 包,也有各种第三方的功能库,有时候我们自己也会将一些功能封装成包。这些包存在和导入的形式也多种多样,有远程仓库的,有直接拷贝到本地的,jar包、aar包、so包等。所幸我们都可以在主工程和各个Module的 build.gradle 里进行统一管理。本文将在Android Studio3.0环境下来汇总下这些用法。

远程仓库依赖

我们先来看下主工程下的 build.gradle 文件

buildscript {
    ext.kotlin_version = '1.1.51'
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

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

allprojects {
    repositories {
        google()
        jcenter()
    }
}

引入远程仓库依赖是很方便的,但在之前我们需要声明远程仓库的地址。上面有两个仓库地址的声明,一个在 buildscript {} ,另一个在 repositories {} 。看代码中系统给我们的注释就知道:前者是gradle脚本自身执行所需依赖(Gradle插件),后者是项目本身需要的依赖(普通代码库)。所以如果你没有引入远程的Gradle插件,那么就不用在 buildscript {} 下的 dependencies 下添加依赖。

关于Gradle插件的开发可以看下这篇文章:Gradle自定义插件

再来看下几种远程依赖的添加方式:

implementation 'commons-lang:commons-lang:2.6'
 
 implementation group: 'com.google.code.guice', name: 'guice', version: '1.0'
 
 implementation('org.hibernate:hibernate:3.1') {
        //不同版本同时被依赖时,那么强制依赖这个版本的,默认false
        force = true
        //exclude可以设置不编译指定的模块,有三种写法:
        exclude module: 'cglib' 
        exclude group: 'org.jmock' 
        exclude group: 'org.unwanted', module: 'iAmBuggy' 
        //禁止依赖的传递,gradle自动添加子依赖项(依赖包所需的依赖),设置为false,则需要手动添加每个子依赖项,默认为true。
        transitive = false
    }

同样的配置下的版本冲突,会自动使用最新版;而不同配置下的版本冲突,gradle同步时会直接报错。可使用exclude、force解决冲突。 比如你同时依赖了两个版本的v7包:

implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support:appcompat-v7:23.1.1'

最终只会使用 26.1.0 版本。但是如 implementation 'com.android.support:appcompat-v7:23.1.1' ,和 androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.1' ,所依赖的 com.android.support:support-annotations 版本不同,就会导致冲突。除了可以用exclude、force解决外,也可以自己统一为所有依赖指定support包的版本,不需要为每个依赖单独排除了:

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support') {
            if (!requested.name.startsWith("multidex")) {
                details.useVersion '26.1.0'
            }
        }
    }
}

编译期注解的依赖--annotationProcessor

用过 butterknife 或者 Dagger 的同学可能对这种 annotationProcessor 引入方式有所印象,这种方式是只在编译的时候执行依赖的库,但是库最终不打包到apk中。结合编译期注解的作用,他是用来生成代码的,本身在运行时是不需要的。

本地依赖

jar包

jar包依赖的导入还是比较简单的:

  • implementation files('hibernate.jar', 'libs/spring.jar') //列出每个jar包的相对路径
  • implementation fileTree(dir: 'libs', include: ['*.jar']) //列出包含jar包的文件夹路径

但和远程仓库依赖引入方式不同,如果本地同时存在两个不同的jar包,或者本地已有jar包,再去远程依赖不同版本的jar包,就会报错。

Android导包全攻略
解决方式:将其中的一个采用 compileOnly 替换 implementation 。顾名思义, compileOnly

只在编译时起作用,不会包含到APK里面,在运行时也就避免找到重复的类了。

aar包

和jar包不同,aar包存放的路径声明和依赖引入是分开的:

repositories {
    flatDir {
        dir "../${project.name}/libs"
    }
}
dependencies {  
    implementation(name: 'aar名字', ext: 'aar')  
}

如果aar包有很多,也可以一样象jar包统一添加一个文件夹下的所有包:

def dir = new File('app/libs')
    dir.traverse(
            nameFilter: ~/.*/.aar/
    ) { file ->
        def name = file.getName().replace('.aar', '')
        implementation(name: name, ext: 'aar')
    }

当一个library类型的module需要引用aar文件时,也要在所在模块的build.gradle文件中加入上面的话,但是当其他 Module引用此library的module时,也需要在他的build.gradle中加入如下配置,否则会提示找不到文件:

repositories {  
    flatDir {  
        dirs 'libs', '../包含aar包的模块名/libs'  
    }  
}

即如果当前Module需要一个aar包内容,不论aar包是不是在当前Module中,都需要声明它所在的路径。如果项目中这样的模块比较多,不便于管理的话,也可以在项目的 build.gradle 中统一添加,将所有包含aar包的模块名列出,这样不论是本Module或其他Module都不需要单独写了:

allprojects {
    repositories {
        jcenter()
        google()
        flatDir {
             dirs "../moudle-A/libs,../moudle-B/libs,../moudle-C/libs".split(",")
        }
    }
}

so文件

声明下so文件的存放路径就行了:

sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

或者直接在main目录下新建jniLibs目录,就不需要声明了,不过不常用。

常见问题

1.aar包中的资源文件重复了, 在主项目中添加build->android->添加packagingOptions exclude 包含重复的文件

packagingOptions {
        exclude 'META:-INF/LICENSE.txt'
      
}

2.AndroidManifest合并错误,同样也是发生在aar包上, Android Studio 项目每个module中都可以有一个AndroidManifest.xml文件,但最终的APK 文件只能包含一个 AndroidManifest.xml 文件。在构建应用时,Gradle 构建会将所有清单文件合并到一个封装到 APK 的清单文件中。aar包的清单文件和我们的app清单文件属性冲突时:用 tools:replace="属性名" 解决。

原文  https://juejin.im/post/5acd6daaf265da238a30ca73
正文到此结束
Loading...