Android源码中编译带androidx(support)库的app源码
阅读本文需要了解:
- Android.mk
- Android.bp
- Linux grep命令
WHY
一般企业级开发中,Android源码都会使用git或者其它版本管理工具进行管理,将app源码放到Android源码中,可以有效的记录代码修改记录,并且能够有效的避免多个仓库带来的管理困难.
但是将app源码放到Android源码中也带来库(support|androidx)版本的兼容性问题,本文针对app库版本、Android源码库版本、实际需要的最低库版本给出了一些解决方案,供大家参考。
HOW
这里根据所使用的库以及库相对Android源码版本分为4种情况,见下表
库 | 版本 | 解决方案 |
---|---|---|
androidx | 高于源码 | 导入新版本库文件及其依赖或者尝试降低代码中库的版本或者改用support库 |
androidx | 低于或等于源码 | 直接放入源码,添加Android.mk(bp)编译 |
support | 高于源码 | 导入新版本库文件及其依赖或者尝试降低降低代码中库的版本 |
support | 低于或等于源码 | 直接放入源码,添加Android.mk(bp)编译 |
由上表可知,不论是support库或者是androidx库,实际上都只有两种办法,一是导入新版本库文件及其依赖或者尝试降低代码版本,二是直接放入源码,添加Android.mk(bp)编译。
这两种办法是根据Android源码特性决定的,因为Android源码中的support库以及androidx库是无法升级也不建议升级的,那么当app源码中使用的库的版本高于源码中相应库的版本时,只能通过导入新版本库及其依赖或者在不需要用到新版本库的特性时降低app源码中相应库版本来兼容Android源码。
1. 导入新版本库文件及其依赖或者尝试降低代码中库的版本
如果一定要用最新的库,那么就需要通过导入新版库及其依赖的方式来实现,这种方式要根据库的复杂程度来判断是否采用,因为库依赖较多时会比较复杂,如果你要导入这个库,那么它的依赖也需要全部导入;当然,也有比较好的情况,比如你只需要使用constraintlayout
库,可能会相对简单一点,只需要导入constraintlayout(aar)
以及constraintlayout-slover(jar)
包即可,并且新版Android Studio默认使用constraintlayout
作为页面根布局,使用到的case可能会比较多。
导入新版本库文件
那么如何导入库文件呢?这里根据库的复杂程度以及可复用性介绍两种方法:
(以下内容需要熟悉Android.mk
)
第一种情况,依赖较少时,以constraintlayout
为例,可采用以下方式:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PACKAGE_NAME := Xxx
# 其它定义
LOCAL_xxx := xxx
LOCAL_AAPT_FLAGS += --auto-add-overlay \
--extra-packages android.support.constraint
# 导入第三方库时,建议关闭混淆
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_DEX_PREOPT := false
# include constraint-layout
# aar包需要用LOCAL_STATIC_JAVA_AAR_LIBRARIES导入
LOCAL_STATIC_JAVA_AAR_LIBRARIES := constraint-layout
# include constraint-layout-slover
# jar包用LOCAL_STATIC_JAVA_LIBRARIES导入
LOCAL_STATIC_JAVA_LIBRARIES := \
constraint-layout-slover
# 定义包名称及对应文件
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
constraint-layout:libs/constraint-layout-1.1.3.aar \
constraint-layout-slover:libs/constraint-layout-solver-1.1.3.jar
include $(BUILD_MULTI_PREBUILT)
include $(BUILD_PACKAGE)
在Android.mk
同级目录下新建libs
目录,将需要导入的aar包和jar包放到libs
目录中即可。
第二种情况,依赖较多时,可以将库打包成一个模块,然后在你的APK里面直接引用这个模块,这种方式没有试过,可以参考如何在AOSP项目中包含约束布局库,感兴趣的可以试一下。
降低代码中库的版本 | 直接放入源码,添加Android.mk(bp)编译
降低代码中使用库的版本或者直接放入源码中编译其实是一个道理,即保持代码中所使用的库版本与Android源码中对应的库版本一致,这样就可以将代码放到Android源码中编译,故这里仅介绍降低代码中库的版本的做法。
如果app不需要使用新版本库的特性,那么就可以对库进行降级
降级的办法是先找到Android源码中相应库的版本,以androidx
的constraintlayout
库为例:
由于Android.mk
中所使用的库名称不等同于库名称,所以首先要找到库在Android源码中对应的名称,在Android源码中,support库以及androidx库都存放在prebuilt目录下,定义在相应的Android.bp
文件中,而Android.bp
中每个模块都需要使用name
属性进行声明,故执行以下命令就可以找到相关信息:
grep -nr "name.*androidx.constraintlayout" --include=*.bp prebuilts/
结果如下,由于一个组件可能有相关的依赖,所以不止一个,Android.mk
中要引用的一般都是androidx-moudle_module
这种形式的:
prebuilts/sdk/current/extras/constraint-layout-x/Android.bp:5: name: "androidx-constraintlayout_constraintlayout-nodeps",
prebuilts/sdk/current/extras/constraint-layout-x/Android.bp:13: name: "androidx-constraintlayout_constraintlayout",
prebuilts/sdk/current/extras/constraint-layout-x/Android.bp:24: name: "androidx-constraintlayout_constraintlayout-solver-nodeps",
prebuilts/sdk/current/extras/constraint-layout-x/Android.bp:30: name: "androidx-constraintlayout_constraintlayout-solver",
再打开prebuilts/sdk/current/extras/constraint-layout-x/Android.bp
定位到13
行:
android_library {
# 以下是第13行
name: "androidx-constraintlayout_constraintlayout",
sdk_version: "current",
manifest: "manifests/androidx-constraintlayout_constraintlayout/AndroidManifest.xml",
static_libs: [
"androidx-constraintlayout_constraintlayout-nodeps",
"androidx-constraintlayout_constraintlayout-solver",
],
java_version: "1.7",
}
这里我们需要找的是jar包或者aar包版本,但是并没有发现jar包或者aar包,不过还有依赖,那么再定位到androidx-constraintlayout_constraintlayout-nodeps
即第5
行
android_library_import {
# 以下为第5行
name: "androidx-constraintlayout_constraintlayout-nodeps",
aars: ["layout/constraintlayout-1.1.0.aar"],
sdk_version: "current",
static_libs: [
],
}
已经看到了,版本为1.1.0,那么将Android Studio里面相应的库版本改为1.1.0,再进行编译就知道那些地方有问题了,针对这些问题,看有无替代方法、是否必须,如果可以降级,那么将降级后的代码复制到源码中并创建相应的Android.mk
再导入相应组件即可:
LOCAL_STATIC_ANDROID_LIBRARIES := androidx-constraintlayout_constraintlayout