Android aar打包总结

Android通过aar方式可以把代码,资源文件等等打成一个包,提供给第三方使用或者自己使用,aar包含这所需要的依赖资源,避免了大量的模块引用,加快了编译的速度,另外在SDK开发中通常是以aar的方法或者远程依赖提供给第三方使用。下面总结下aar生成依赖的方式和应用存在的一些问题。下面举例:

app依赖library,library依赖BaseLibrary,这种情况下如果library需要生成aar提供给app使用或者提供给第三方使用,就需要合理的进行打包资源,生成aar,下面介绍集中常用的方式:

一、分模块打包aar

1、生成aar

这种方式首先对BaseLibrary打包,生成一个base-aar,,然后在对library打包生成library-aar,把两个aar都集成到app里面进行使用。通过如下命令:

 ./gradlew BaseLibrary:assemble

./gradlew library:assemble

生成aar,然后在对应的build/outputs/aar文件夹下找到对应的文件。将两个aar放在app/libs下,在对应的gradle中添加:

 implementation files('libs/base.aar')
 implementation files('libs/library.aar')

重新编译即可。

2、注意事项

通过这种方式可以将jar包打进去到aar,但是对于implementation或者api的依赖则无效,如果base-aar中含有远程依赖,则需要重新将依赖文件拷贝到app的gradle的dependencies中去,否则会找不到类。

二、整体打包aar

对于第一种方式的不足是如果aar比较多的话用起来比较繁琐,这时候可以将BaseLibrary和library合并成一个aar来进行使用。如果将base-aar放入ibrary-aar直接打包生成aar会出现下面classes.jar嵌套的情况:

这种情况显然是有问题的,因此不能这样使用。下面介绍一种开源的方式:

1、使用方式

参考:https://github.com/kezong/fat-aar-android

2、集成

project/build.gradle下:

buildscript {
    dependencies {
        classpath 'com.android.tools.build:gradle:3.4.0'
        classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
    }
}

library/build.gradle下:

apply plugin: 'com.kezong.fat-aar'

dependencies {

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

    embed project(':BaseLibrary')
}

3、使用

./gradlew library:assemble

这时候生成的library-aar即是包含base-aar的aar,即将两个aar合并成为一个,此时还是不能找到implementation或者api的依赖,如果base-aar或者library-aar中含有远程依赖,则需要重新将依赖文件拷贝到app的gradle的dependencies中去,否则会找不到类。下面可以通过embed将一个implementation或者api打入aar中,如:

apply plugin: 'com.kezong.fat-aar'

dependencies {

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

    embed project(':BaseLibrary')
    embed 'com.google.code.gson:gson:2.8.4'
    embed 'com.github.bumptech.glide:glide:4.11.0'
}

生成的aar包中就包含gons和glide的源码了,如下:

4、注意事项

尽管这种方式很便捷的能将implementation或者api的依赖合并为一个aar,但是还是存在很多兼容性问题,导致编译失败,常见的如下:

(1)资源冲突

假如BaseLibrary和library有个values/strings的内容:

<string cancel">取消</string>

或者values/colors的内容:

<color name="c_1A1B1F">#1A1B1F</color>

这时候就会引起资源冲突,解决方法是保证每个library的资源名称不一样。

(2)依赖冲突

假如第三方的库和aar或者本地依赖未打成aar的库有多个不同版本的gson,这时候需要exclude多余的gson,保证只能使用一个,这样如果引用的比较多或者比较深的话很难完全找到,用起来也很麻烦。

其他的问题请参考:https://www.jianshu.com/p/8f9cf6271c20?tdsourcetag=s_pcqq_aiomsg

三、使用本地仓库

以上两种方式都是生成本地aar方式,这种方式不能够理想的打包进去implementation的依赖,maven方式则可以不用担心这种情况,生成的maven仓库的pom文件则包含了依赖的所以信息,当使用生成的仓库使用,则可以自动的拉取下来所需的aar文件和相关依赖。

1、project/build.gradle

buildscript /repositories里面添加mavenLocal(),如下:

buildscript {
    repositories {
        mavenLocal()
        google()
        jcenter()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:3.4.0"
    }
}

2、app/build.gradle

apply plugin: 'maven'

uploadArchives {
    configuration = configurations.archives
    repositories {
        mavenDeployer {
            //这里必须要file://localhost/,后面的地址换成你本地的绝对路径,下面是mac的路径
            repository(url: "file://localhost/" + "/Users/xxx/Desktop/aar")
            pom.project {
                version '1.0.0'
                artifactId 'library-demo'
                groupId 'com.test.demo'
                packaging 'aar'
                description '测试aar本地仓库'
            }
        }
    }
}

参数定义如下:

  • repository url 路径可自定义
  • version   版本
  • artifactId 名称
  • groupId  包名
  • packaging 类型
  • description 描述

3、执行 

./gradlew uploadArchives  

4、结果

5、使用

在项目最外层build.gradle 文件中添加如下代码

allprojects {
    repositories {
        google()
        jcenter()
        //注意:路径与之前生成路径保持一致,需要加上file://,下面是mac地址
        maven{  url "file:///Users/xxx/Desktop/aar"}
        //或者,二选一
        maven {
            url "file://${new File(project.rootProject.rootDir, 'aar').getAbsolutePath()}"
        }
    }
}

之后添加依赖:

implementation 'com.test.demo:library-demo:1.0.0'

重新编译一下即可使用。

四、使用jcenter仓库

1、jcenter仓库配置

本地maven仓库虽然解决了依赖问题,但是之只能在本地使用,但是在开发中使用最多的全球三大仓库是mavenCentral()、jcenter()、google()仓库,下面以jcenter仓库为例,介绍本地library的上传。

1.1、注册Jcenter

https://bintray.com/

备注:网上很多帖子说这块需要注册个人版的,直接点进去是企业版的,没法发布,我在最新的官方上没遇到这种情况,直接点进去注册就行。

备注:另外网上很多帖子说注册需要国外邮箱才行,国内的不行,比如说google邮箱,我用的是公司的企业邮箱注册,一切顺利。

1.2、新建仓库

这样就注册完成!返回首页,下面会多一个仓库名称,就是你建立的仓库:

点进去啥也没有:

网上有的帖子说还需要Add New Package,这个步骤其实不用,到此仓库就建立完成了,准备工作已经做好了。

2、gralde环境配置

2.1、插件配置

gradle推送到jcenter需要使用两个插件:

classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'

在projct/build.gradle下面添加:

buildscript {

    dependencies {
       
        classpath 'com.android.tools.build:gradle:3.4.0'
    
        classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
    }
}

2.2、library/build.gradle配置

在library/build.gradle最下面配置如下:

配置好在使用的时候即可:

implementation 'com.test.demo:payLib:1.0.0'

  • com.test.demo:给个库的配置一样,因此在jcenter中写死了,去每次重复的编写。
  • payLib:就是上面libraryName的名称,一般和模块名称一致。
  • 1.0.0:版本号,每次提交到jcenter的时候必须升级版本号,否则提交失败。

这样,每个模块需要提交的jcenter的时候就配置上面几行代码,方便灵活,下面介绍jcenter.gradle的内容。

2.3、jcenter.gradle

jcenter.gradle位于项目的根目录,包括三大内容:

  1. 完成maven相关文件的生成与打包。
  2. 生成javadoc.jar和source.jar。
  3. 文件的打包上传到bintray.com。

首先需要使用引入的插件:

apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'com.jfrog.bintray'

(1)完成maven相关文件的生成与打包

//项目在github主页地址
def siteUrl = 'https://github.com/xxx/xxx'
//Git仓库的地址
def gitUrl = 'https://github.com/xxx/xxx'.git'

//这块的内容就是implementation 'com.test.demo:payLib:1.0.0'的com.test.demo,要使用啥改成啥
group = 'com.test.demo'
//项目引用的版本号
version = project.versionName

install {
    repositories.mavenInstaller {
        // 生成pom.xml和参数
        pom {
            project {
                packaging 'aar'
                //可选,项目名称。
                name project.libraryName
                //可选,项目描述。
                description project.libraryDesc
                // 项目主页,这里是引用上面定义好。
                url siteUrl
                // 软件开源协议,现在一般都是Apache License2.0
                licenses {
                    license {
                        name 'The Apache Software License, Version 2.0'
                        url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                    }
                }
                //填写开发者基本信息,复制我的,这里需要修改。
                developers {
                    developer {
                        //开发者的个人信息
                        id 'zhangsan'
                        name 'zhangsan'
                        email 'zhangsan@qq.com'
                    }
                }

                // SCM
                scm {
                    // Git仓库地址.
                    connection gitUrl
                    // Git仓库地址。
                    developerConnection gitUrl
                    // 项目主页。
                    url siteUrl
                }
            }
        }
    }
}

(2)生成javadoc.jar和source.jar

// 生成jar包的task
task sourcesJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    classifier = 'sources'
}

// 生成jarDoc的task
task javadoc(type: Javadoc) {
    source = android.sourceSets.main.java.srcDirs
    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
    // destinationDir = file("../javadoc/")
    failOnError false // 忽略注释语法错误,如果用jdk1.8你的注释写的不规范就编译不过。
}

// 生成javaDoc的jar
task javadocJar(type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}
artifacts {
    archives javadocJar
    archives sourcesJar
}

这块没啥好讲的,直接复制即可。

(3)文件的打包上传到bintray.com

// 这里是读取Bintray相关的信息,不要把帐号密码的信息直接写在这里,写在local.properties中,这里动态读取。
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
bintray {
    // Bintray的用户名。
    user = properties.getProperty("bintray.user")
    // Bintray刚才保存的ApiKey。
    key = properties.getProperty("bintray.apikey")
    configurations = ['archives']
    pkg {
        //id
        userOrg = user
        //Repository名字 需要自己在bintray网站上先添加
        repo = properties.getProperty("bintray.rep")
        //发布到JCenter上的项目名字
        name = project.libraryName
        //项目描述
        desc = project.libraryDesc
        websiteUrl = siteUrl
        vcsUrl = gitUrl
        licenses = ["Apache-2.0"]
        // 是否是公开项目。
        publish = true
    }
}

//如果你的项目里面有中文注释的话,必须将格式设置为UTF-8,不然会出现乱码
javadoc {
    options {
        encoding "UTF-8"
        charSet 'UTF-8'
        author true
        version true
        links "http://docs.oracle.com/javase/7/docs/api"
    }
}

为了控制权限,不要把帐号密码的信息直接写在这里,写在local.properties中,这里动态读取。包括用户名、密码、仓库名称。

  1. 用户名:就是登录jcenter的用户名。
  2. 仓库名称:就是上上面创建的仓库名称。
  3. 密码:点击头像,选择Edit Your Profile,出现

2.4、local.properties

  • bintray.rep=你的仓库名称
  • bintray.apikey=获取到的key
  • bintray.user=你的登录名称

3、推送到jcenter

项目右上角gradle,点击bintrayUpload就上传上去了。

上传完成之后,打开https://bintray.com/,就会看到之前仓库新建的内容:

点开刚刚提交项目的主页,点击右下角的添加到jcenter按钮,填写信息,也可以不填:

提交之后大概40分钟左右就通过了,不通过的话也会收到邮件的说明不通过原因,修改后再次提交即可。

注意事项:

Jcenter提交的maven仓库代码必须开源,私有的,本地的,内部的,别人访问不到的等等代码仓库无法通过提交审核,如果不能开源的aar库,需要使用其他仓库,mavenCentral理论上也需要开源项目才能上传,但是可以通过添加许可证、开源协议等的方式上传非开源的依赖库,这个过程比较漫长和繁琐,另外开源项目mavenCentral相比Jcenter也不容易,所以还是推荐Jcenter方法,不开源的项目内部搭建私有仓库或者提供arr包也可以解决问题。

  • 1
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值