我找到了一种完全自动执行此操作的方法。我会过一遍,然后完成的 Android.mk 在这篇文章的底部。
首先,让我们创建一些变量,其中包含将在您的实例中更改的部分,以便您可以复制/粘贴其余部分。您可以手动解压缩 .aar 文件一次以检查文件结构和内容。相对路径是从我当前的目标目录回到 Android 构建树的根目录('out' 所在的位置)。
LOCAL_PATH := $(call my-dir)
#####################################
# Definitions for extracting .so files from .aar
AAR_WITH_JNI=lib/whatever-your.aar
AAR_ALIAS=MakeThisMeaningfullToYou
AAR_JNI_FLAVOR=arm64-v8a
AAR_ROOT_EXTRACT_PATH=out/target/common/obj/JAVA_LIBRARIES/$(AAR_ALIAS)_intermediates/aar/jni/$(AAR_JNI_FLAVOR)
AAR_RELATIVE_EXTRACT_PATH=../../../../$(AAR_ROOT_EXTRACT_PATH)
接下来,我们要使用“解压缩”来使用 shell 命令查询 .aar 文件中的 jni 内容,标准输出通过 grep 和 sed 管道进行清理。这是有效的,因为 .aar 文件已签入并出现在干净的“make”开始时。因此,将其添加到您的变量定义之后的 Android.mk 顶部。
AAR_JNI_SO_FILE_LIST := $(shell \
unzip -l $(LOCAL_PATH)/$(AAR_WITH_JNI) | \
grep -e jni/$(AAR_JNI_FLAVOR)/lib\.*.so | \
sed 's?^.*jni/$(AAR_JNI_FLAVOR)/??g')
现在我们遵循aar support in Android.mk 中的模式,通过将 LOCAL_STATIC_JAVA_AAR_LIBRARIES 添加到您的 BUILD_PACKAGE 并使用 3 行 BUILD_MULTI_PREBUILT 之后为提取的 AAR 定义别名,将 AAR 库添加到您的包中。
include $(CLEAR_VARS)
# your LOCAL_SRC_FILES and whatever else you need here
LOCAL_STATIC_JAVA_AAR_LIBRARIES:= $(AAR_ALIAS)
LOCAL_AAPT_FLAGS := --auto-add-overlay
include $(BUILD_PACKAGE)
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := $(AAR_ALIAS):$(AAR_WITH_JNI)
include $(BUILD_MULTI_PREBUILT)
现在我们通过将 .so 文件的引用添加到 BUILD_PACKAGE 来扩充该解决方案。我使用 addprefix 使用相对路径来做到这一点。
LOCAL_PREBUILT_JNI_LIBS := \
$(addprefix $(AAR_RELATIVE_EXTRACT_PATH)/,$(AAR_JNI_SO_FILE_LIST))
此时,如果您在干净的工作区执行此操作,则每个 .so 文件都会出现错误,因为它们尚不存在。解决方案是为每个 .so 文件创建一个Empty Recipe,并以我们的别名为先决条件。我们可以使用eval 和call 函数组合的foreach 循环来做到这一点,如Generate dynamically Makefile rules 中所述。由于这些规则,'make' 将知道.so 文件不会出现在文件系统上,直到BUILD_MULTIPLE_PREBUILT 步骤的结束。
define fake-so-rule-from-aar
$(1): $(AAR_ALIAS) ;
endef
$(foreach soFile,$(addprefix $(AAR_ROOT_EXTRACT_PATH)/,$(AAR_JNI_SO_FILE_LIST)),$(eval $(call fake-so-rule-from-aar,$(soFile))))
因此,当您将所有这些放在一起时,您不需要从 .aar 文件中预提取 .so 文件。您可以简单地“rm -rf out”,构建系统将提取所需的所有内容并将 .so 文件正确复制到您的库中。
完成的 Android.mk 文件:
LOCAL_PATH := $(call my-dir)
#####################################
# Definitions for extracting .so files from .aar
AAR_WITH_JNI=lib/my.aar
AAR_ALIAS=MyAarFile
AAR_JNI_FLAVOR=arm64-v8a
AAR_ROOT_EXTRACT_PATH=out/target/common/obj/JAVA_LIBRARIES/$(AAR_ALIAS)_intermediates/aar/jni/$(AAR_JNI_FLAVOR)
AAR_RELATIVE_EXTRACT_PATH=../../../../$(AAR_ROOT_EXTRACT_PATH)
# We cannot look in the driectory at the extracted files on a clean build, so we peek at the .aar contents to know what filenames we'll end up extracting
AAR_JNI_SO_FILE_LIST := $(shell unzip -l $(LOCAL_PATH)/$(AAR_WITH_JNI) | grep -e jni/$(AAR_JNI_FLAVOR)/lib\.*.so | sed 's?^.*jni/$(AAR_JNI_FLAVOR)/??g')
#$(info AAR_JNI_SO_FILE_LIST = $(AAR_JNI_SO_FILE_LIST))
#####################################
# java package
include $(CLEAR_VARS)
LOCAL_MULTILIB := 64
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := AlsoMine
LOCAL_STATIC_JAVA_AAR_LIBRARIES := $(AAR_ALIAS)
LOCAL_PREBUILT_JNI_LIBS := $(addprefix $(AAR_RELATIVE_EXTRACT_PATH)/,$(AAR_JNI_SO_FILE_LIST))
#$(info LOCAL_PREBUILT_JNI_LIBS = $(LOCAL_PREBUILT_JNI_LIBS))
LOCAL_AAPT_FLAGS := --auto-add-overlay
# Build an APK
include $(BUILD_PACKAGE)
#####################################
# Create an alias to the extracted library from the .aar
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := $(AAR_ALIAS):$(AAR_WITH_JNI)
include $(BUILD_MULTI_PREBUILT)
#####################################
# Create empty recipes so Make thinks it knows the so files are created
# by the BUILD_MULTI_PREBUILT above
define fake-so-rule-from-aar
$(1): $(AAR_ALIAS) ;
#$(info Created empty recipe for $(1): $(AAR_ALIAS))
endef
#$(foreach soFile,$(addprefix $(AAR_ROOT_EXTRACT_PATH)/,$(AAR_JNI_SO_FILE_LIST)), $(info $(soFile)))
$(foreach soFile,$(addprefix $(AAR_ROOT_EXTRACT_PATH)/,$(AAR_JNI_SO_FILE_LIST)),$(eval $(call fake-so-rule-from-aar,$(soFile))))
我在我的文件中留下了很多 cmets 和 $info 调用,以便为下一个需要调试它的人打印各种状态。享受吧!