Android.mk aar引用过程
2020-03-01 本文已影响0人
徒步青云
网上很多教程都有问题,很多人这样引用aar包:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
.....
LOCAL_STATIC_JAVA_AAR_LIBRARIES:= <aar alias>
LOCAL_AAPT_FLAGS := \
--auto-add-overlay \
--extra-packages <aar package name>
include $(BUILD_PACKAGE)
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := <aar alias>:libs/<lib file>.aar
include $(BUILD_MULTI_PREBUILT)
首先,先给结论,这种方式在Android P上是有问题的,这样是引用不到aar中的资源文件。
看源码:
//multi_prebuilt.mk
define auto-prebuilt-boilerplate
$(if $(filter %: :%,$(1)), \
$(error $(LOCAL_PATH): Leading or trailing colons in "$(1)")) \
$(foreach t,$(1), \
$(eval include $(CLEAR_VARS)) \
$(eval LOCAL_IS_HOST_MODULE := $(2)) \
$(eval LOCAL_MODULE_CLASS := $(3)) \
$(eval LOCAL_MODULE_TAGS := $(4)) \
$(eval OVERRIDE_BUILT_MODULE_PATH := $(5)) \
$(eval LOCAL_UNINSTALLABLE_MODULE := $(6)) \
$(eval tw := $(subst :, ,$(strip $(t)))) \
$(if $(word 3,$(tw)),$(error $(LOCAL_PATH): Bad prebuilt filename '$(t)')) \
$(if $(word 2,$(tw)), \
$(eval LOCAL_MODULE := $(word 1,$(tw))) \
$(eval LOCAL_SRC_FILES := $(word 2,$(tw))) \
, \
$(eval LOCAL_MODULE := $(basename $(notdir $(t)))) \
$(eval LOCAL_SRC_FILES := $(t)) \
) \
$(if $(7), \
$(eval LOCAL_BUILT_MODULE_STEM := $(7)) \
, \
$(if $(word 2,$(tw)), \
$(eval LOCAL_BUILT_MODULE_STEM := $(LOCAL_MODULE)$(suffix $(LOCAL_SRC_FILES))) \
, \
$(eval LOCAL_BUILT_MODULE_STEM := $(notdir $(LOCAL_SRC_FILES))) \
) \
) \
$(eval LOCAL_MODULE_SUFFIX := $(suffix $(LOCAL_SRC_FILES))) \
$(eval LOCAL_STRIP_MODULE := $(8)) \
$(eval include $(BUILD_PREBUILT)) \
)
endef
这是其中的一段主要代码,不用理解他的具体含义,我们从倒数第三行可以看出,BUILD_MULTI_PREBUILT最终是对每个值分别调用了BUILD_PREBUILT,我们再看BUILD_PREBUILT,它是定义在prebuilt_internal.mk中
my_src_aar := $(filter %.aar, $(my_prebuilt_src_file))
ifneq ($(my_src_aar),)
# This is .aar file, archive of classes.jar and Android resources.
........
my_src_jar := $(intermediates.COMMON)/aar/classes.jar
my_src_proguard_options := $(intermediates.COMMON)/aar/proguard.txt
$(my_src_jar) : .KATI_IMPLICIT_OUTPUTS := $(my_src_proguard_options)
$(my_src_jar) : $(my_src_aar)
$(hide) rm -rf $(dir $@) && mkdir -p $(dir $@) $(dir $@)/res
$(hide) unzip -qo -d $(dir $@) $<
# Make sure the extracted classes.jar has a new timestamp.
$(hide) touch $@
# Make sure the proguard file exists and has a new timestamp.
$(hide) touch $(dir $@)/proguard.txt
这段代码,是对aar库进行解压。
ifdef LOCAL_AAPT2_ONLY
LOCAL_USE_AAPT2 := true
endif
ifdef LOCAL_USE_AAPT2
ifneq ($(my_src_aar),)
.......
my_res_package := $(intermediates.COMMON)/package-res.apk
# We needed only very few PRIVATE variables and aapt2.mk input variables. Reset the unnecessary ones.
$(my_res_package): PRIVATE_AAPT2_CFLAGS :=
$(my_res_package): PRIVATE_AAPT_FLAGS := --static-lib --no-static-lib-packages --auto-add-overlay
$(my_res_package): PRIVATE_ANDROID_MANIFEST := $(intermediates.COMMON)/aar/AndroidManifest.xml
$(my_res_package): PRIVATE_AAPT_INCLUDES := $(framework_res_package_export)
$(my_res_package): PRIVATE_SOURCE_INTERMEDIATES_DIR :=
$(my_res_package): PRIVATE_PROGUARD_OPTIONS_FILE :=
$(my_res_package): PRIVATE_DEFAULT_APP_TARGET_SDK :=
$(my_res_package): PRIVATE_DEFAULT_APP_TARGET_SDK :=
$(my_res_package): PRIVATE_PRODUCT_AAPT_CONFIG :=
$(my_res_package): PRIVATE_PRODUCT_AAPT_PREF_CONFIG :=
$(my_res_package): PRIVATE_TARGET_AAPT_CHARACTERISTICS :=
$(my_res_package) : $(framework_res_package_export)
full_android_manifest :=
my_res_resources :=
my_overlay_resources :=
my_compiled_res_base_dir := $(intermediates.COMMON)/flat-res
R_file_stamp :=
proguard_options_file :=
my_generated_res_dirs := $(intermediates.COMMON)/aar/res
my_generated_res_dirs_deps := $(my_src_jar)
include $(BUILD_SYSTEM)/aapt2.mk
# Make sure my_res_package is created when you run mm/mmm.
$(built_module) : $(my_res_package)
endif # $(my_src_aar)
endif # LOCAL_USE_AAPT2
这里看到,只有当定义LOCAL_USE_AAPT2时,才会调用aapt2.mk,将aar解压后的资源打包成package-res.apk,而我们举例的multi_prebuilt.mk代码中,可以看到两个信息:
1、调用了include $(CLEAR_VARS)
2、未定义LOCAL_USE_AAPT2
由此可以得出结论,无论我们如何在BUILD_MULTI_PREBUILT中引用aar库,都不能生成package-res.apk,这意味着我们下面的代码将不会生效(至少在Android 9上是这样)
LOCAL_AAPT_FLAGS := \
--auto-add-overlay \
--extra-packages <aar package name>
我们的代码将引用不到aar中的资源。
要想引用到,必须采用BUILD_PREBUILT,并且需要在里面声明LOCAL_USE_AAPT2 := true
那有人会问,我不用appt2,能引用到aar中的资源吗?答案是:可以,可是这样会出现很多错误,至少我解决不了。
当我们使用LOCAL_STATIC_JAVA_AAR_LIBRARIES时,如果没有定义LOCAL_USE_AAPT2,才会去引用aar/res
android_manifest.mk
LOCAL_STATIC_JAVA_AAR_LIBRARIES := $(strip $(LOCAL_STATIC_JAVA_AAR_LIBRARIES))
ifdef LOCAL_STATIC_JAVA_AAR_LIBRARIES
my_full_libs_manifest_deps += $(foreach lib, $(LOCAL_STATIC_JAVA_AAR_LIBRARIES),\
$(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/aar/classes.jar)
my_full_libs_manifest_files += $(foreach lib, $(LOCAL_STATIC_JAVA_AAR_LIBRARIES),\
$(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/aar/AndroidManifest.xml)
# With aapt2, we'll link in the built resource from the AAR.
ifndef LOCAL_USE_AAPT2
LOCAL_RESOURCE_DIR += $(foreach lib, $(LOCAL_STATIC_JAVA_AAR_LIBRARIES),\
$(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/aar/res)
endif # LOCAL_USE_AAPT2
endif # LOCAL_STATIC_JAVA_AAR_LIBRARIES