Android开发

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
上一篇 下一篇

猜你喜欢

热点阅读