在最近的工作中,需要对开发的组件化SDK进行AAR打包,在这里记录一下。
组件化架构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| +--------------------+ | 壳App | +----------^---------+ +----------------------------------------------------------+ | +--------------------+ | | 需要打包的SDK | APP(UI相关) | | | +------^------^------+ | | | | | | +--------------------------------------------------+ | | | | | | | | | +-----------------++ +---+-------------+ | | | | | 业务A | | 业务B | | | | | +-----------------+ +-----------------+ | | | +----------------------^---------------------------+ | | | | | +--------------------------------------------------+ | | | +--------------+ +-------------+ +-------------| | | | | 基础库A | | 基础库B | | ... || | | | +--------------+ +-------------+ +-------------| | | +--------------------------------------------------| | +----------------------------------------------------------+
|
目标
将APP、业务、基础库中自己的代码打包成一个.aar
文件,用到的第三方依赖由配置文件提供给宿主App使用
思路
- 将业务和基础库中的jar包、aar使用maven依赖,使这些模块可以产出包含自己代码的jar包
- 将上述生成的jar包导入APP的lib依赖,切断APP和业务、基础库的gradle依赖关系
- 在APP中打包生成AAR
实施
各模块生成.jar文件
gradle编译完成后就会在每个模块的build
目录下生成classes.jar文件,这里需要在编译后将jar包重命名并拷贝到app/dep_lib
目录。
每个模块的build.gradle
配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| android { buildTypes { release { minifyEnabled false } } } task makeJar(type:Copy){ String filename = "xxx.jar" from('build/intermediates/aar_main_jar/debug/') into(rootDir.path + '/app/dep_lib') rename('classes.jar', filename) } makeJar.dependsOn(build)
|
之后,执行./gradlew makeJar
就会生成jar包,并复制到app/dep_lib
目录中。
注意:各个模块的混淆需要关闭,统一配置在app中,最终由app混淆。
将各模块的jar包导入app的依赖中,切断module依赖
执行完上个步骤后,app
目录下已有dep_lib目录,且包含各个模块的jar包。然后配置好混淆规则,切断module依赖,使用jar包依赖,执行./gradlew app:bundleReleaseAar
,之后就可以在app/build/outputs/aar
中看到aar产物。这个步骤很简单,但是每次打包都这么配置一次,太麻烦了!!!必须有更简单的办法。
所以app/build.gradle
需要做判断,只在打包时使用dep_lib
下的jar包依赖,正常开发过程中仍使用module依赖。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| dependencies { ...
if(project.hasProperties("buildAar")){ implementation fileTree(dir: 'dep_lib', includes: ['*.jar']) implementation 'androidx.recyclerview:recyclerview:1.0.0' implementation ... } else { implementation project('baseA') implementation project('businessA') }
... }
|
这里使用了编译参数buildAar
,编译aar的命令就成了
1
| ./gradlew app:bundleReleaseAar -PbuildAar=true
|
开发过程中没有这个参数,所以扔使用module依赖。
一键脚本
1 2 3 4 5 6 7 8 9
| ./gradlew clean rm -rf app/dep_lib ./gradlew makeJar ./gradlew app:bundleReleaseAar -PbuildAar=true
rm -rf SDK mkdir SDK cp app/build/outputs/aar/aar-release.aar SDK cp app/build/outputs/mapping/release/mapping SDK
|
壳工程测试AAR
将生成的aar复制到壳工程中。
在壳工程中测试AAR,也需要分情况判断依赖。一般执行Android Studio运行测试,所以配置可以写进gradle配置里。
build.gradle
1 2 3
| ext { buildWithAar:true }
|
shellapp/build.gradle
1 2 3 4 5 6 7 8 9 10 11 12 13
| dependencies { ...
if (!rootProject.ext.buildWithAar.toBoolean()){ implementation project(':app') } else { implementation fileTree(dir:"libs", include:['*.aar']) ... } }
|
大功告成
缺陷
- 依赖配置复杂,每个业务模块、基础模块的依赖都需要在
app/build.gradle
里多配置一次
更好的方式?
maven?