应用程序(在Android Studio中开发)使用AAR
作为库。我需要在AOSP
树中构建这个应用程序。所以我创建了Android.mk:
LOCAL_STATIC_JAVA_AAR_LIBRARIES:= <aar alias>
include $(BUILD_PACKAGE)
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := <aar alias>:libs/<lib file>.aar
include $(BUILD_MULTI_PREBUILT)
构建成功完成但问题是AAR
在其“libs”目录中包含多个JAR文件。并且似乎这些JAR未包含在构建中,因此应用程序与NoClassDefFoundError
崩溃。
AOSP是否缺少对AAR
的全力支持?或者我会错过什么?谢谢。我使用Android 6.0.1。
答案 0 :(得分:1)
你做的方式是正确的。包含在aar中的jar文件也将包括在内。我认为你错过了包括aapt标志。
LOCAL_AAPT_FLAGS += --extra-packages your.package.name
答案 1 :(得分:1)
我最终得到了以下内容:
-in application&#39; Android.mk:
LOCAL_STATIC_JAVA_AAR_LIBRARIES += coollibrary
include $(LOCAL_PATH)/java-static-lib-from-aar.mk
-java-static-lib-from-aar.mk:
define list-jar-libs-from-aar
$(foreach f, $(2), $(shell if [ -f $(LOCAL_PATH)/$(f)/$(1).aar ]; then unzip -Z1 $(LOCAL_PATH)/$(f)/$(1).aar libs/*.jar | sed 's/libs\///g; s/\.jar//g'; fi))
endef
define build-jar-lib-from-aar
$(2): $(1)
-mkdir -p $(dir $2);\
cp -fp $1 $2
endef
MY_STATIC_JAVA_LIBS := $(foreach aar,$(LOCAL_STATIC_JAVA_AAR_LIBRARIES),\
$(foreach jar, $(call list-jar-libs-from-aar,$(aar), libs aosplibs),\
$(aar)_$(jar)))
$(info Adding following java libraries from AAR(s) into LOCAL_STATIC_JAVA_LIBRARIES: $(MY_STATIC_JAVA_LIBS))
LOCAL_STATIC_JAVA_LIBRARIES += $(MY_STATIC_JAVA_LIBS)
$(foreach aar,$(LOCAL_STATIC_JAVA_AAR_LIBRARIES),\
$(foreach jar, $(call list-jar-libs-from-aar,$(aar), libs aosplibs),\
$(eval $(call build-jar-lib-from-aar,$(call intermediates-dir-for,JAVA_LIBRARIES,$(aar),,COMMON)/aar/libs/$(jar).jar,$(call intermediates-dir-for,JAVA_LIBRARIES,$(aar)_$(jar),,COMMON)/javalib.jar))))
java-static-lib-from-aar.mk假设AAR位于./libs和aosplibs目录中。
答案 2 :(得分:0)
在这里养死人,我经历了同样的行为。 同样适用于./jni/下的* .so文件。和资产。 查看$(BUILD_MULTI_PREBUILT),我看到它只查找类jar和res文件。
我最终提取了那些组件(* .so,* .jar,assets),并在我的应用Android.mk中明确添加它们。
答案 3 :(得分:0)
我找到了一种完全自动执行此操作的方法。我会逐步完成,然后完成的 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)
接下来我们要使用'unzip'来查询.aar文件中的jni内容,使用shell命令,stdout通过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))))
我在我的文件中留下了很多注释,调用 $info 来为下一个需要调试它的人打印各种状态。享受!