找到一个 aar,看看它是什么?

在项目中找到多个aar文件
image.png

下载的一个recyclerview的aar解压后如下:
image.png

AAR 文件的文件扩展名为 .aar,Maven 工件类型应该也是 aar此文件本身是一个 zip 文件。唯一的必需条目是 /AndroidManifest.xml
此外,AAR 文件可能包含以下一个或多个可选条目:

  • /classes.jar
  • /res/
  • /R.txt
  • /public.txt
  • /assets/
  • /libs/name.jar
  • /jni/abi_name/name.so(其中 abi_name 是 Android 支持的 ABI 之一)
  • /proguard.txt
  • /lint.jar
  • /api.jar
  • /prefab/(用于导出原生库

    简单研究下 AAR 是如何被用起来的

一种本地使用

  1. repositories {
  2. flatDir {
  3. dirs 'libs'
  4. }
  5. }
  6. dependencies {
  7. compile(name:'AAR-name', ext:'aar')
  8. }

一种远程使用

dependencies {
    implementation 'androidx.appcompat:appcompat:1.2.0'
}
  1. 远程依赖,gradle会下载对应的pom文件,根据pom文件配置来下载aar文件
  2. 通过transformer对aar转换为一个classes.jar,转换后结果会缓存,一般路径是 ~/.gradle/caches/transforms-2 或者 ~/.gradle/caches/transforms-1
  3. 通过ConfigurationContainer来获取转换后的产物

尝试在自己做的 APK 里面,用上一个 AAR

生成aar

通过android studio新建了一个module,然后获取到aar文件,放入到项目的build目录中,进入build目录
image.png

编译aar的资源文件

$ANDROID_HOME/build-tools/29.0.3/aapt2 compile --zip mylibrary-debug.aar -o resources_module.zip

—zip参数后会遍历aar内部所有文件,识别其中的资源文件进行编译

接着编译主项目的资源

$ANDROID_HOME/build-tools/29.0.3/aapt2 compile --dir main/res -o build/resources.zip

得到两个zip文件,如下

image.png

链接

由于存在多个AndroidManifest.xml文件,所以第一步先对AndroidManifest.xml做一个合并操作。
合并清单文件没有对应的工具,所以需要手动进行了合并
image.png

然后再进行链接,进入src目录

$ANDROID_HOME/build-tools/29.0.3/aapt2 link build/resources.zip build/resources_module.zip  -I $ANDROID_HOME/platforms/android-30/android.jar -o build/out_merge.apk --extra-packages net.mikaelzero.mylibrary --manifest main/AndroidManifest.xml -v --java build/

命令注释:—extra-packages package_name 生成相同的 R.java 文件,但软件包名称不同。为了就是给aar重新生成R文件,因为aar是不带R文件的。
—java directory 指定要在其中生成 R.java 的目录。这里要同时进行生成不能单独生成,否则会发生ID冲突,生成后手动复制到对应的java目录中。

为什么不带R文件,因为R文件中的ID是唯一的,在引用大量的aar情况下可能发生冲突,因此把 AAR 在合并进 apk 的过程中,对所有的资源 ID 进行重生成,使得这个 R 在这个 app 内全局唯一。

在自己项目中也可以发现,有非常多的R文件
image.png

把编译期生成的两个资源文件合成out_merge.apk,这个时候如果解压该app,可以发现资源合并在了一起

image.png

编译源码

源码需要做一下修改,
image.png
主要是增加一个跳转,跳转的Activity来自aar,所以在编译的时候,需要去链接aar中的jar包

javac -encoding utf-8  -target 1.8 main/java/net/mikaelzero/gradledemo/*.java build/mylibrary/src/main/java/net/mikaelzero/mylibrary/*.java -bootclasspath  $ANDROID_HOME/platforms/android-30/android.jar;build/classes.jar

class转dex

$ANDROID_HOME/build-tools/29.0.3/d8 main/java/net/mikaelzero/gradledemo/*.class build/mylibrary/src/main/java/net/mikaelzero/mylibrary/*.class --classpath $ANDROID_HOME/platforms/android-30/android.jar --output build

那么现在的build目录下就会有一个classes.dex文件,内容如下

image.png

整合

进入build目录

zip -ur out_merge.apk classes.dex

签名

$ANDROID_HOME/build-tools/29.0.3/apksigner sign --ks gradle-key_store.jks out_merge.apk

通过adb命令安装后,可以发现跳转到了TestActivity
image.png