如何在Android O 实现overlay AndroidManifest.xml
新的Android版本已经不支持对AndroidManifest.xml的overlay,如果要想实现该功能,可以有三种实现方法可供参考:
1. 采用Android 编译系统中的PRODUCT_COPY_FILES变量
PRODUCT_COPY_FILES的工作原理是在编译时做文件的替换也可以是文件夹)。在makefile文件中添加如下内容(本例是在device.mk中添加):
PRODUCT_COPY_FILES += device/xx/broxton/xx/packages/providers/MediaProvider/AndroidManifest.xml:packages/providers/MediaProvider/AndroidManifest.xml
这样一来,在编译时,会提前把我们想要编译的AndroidManifest.xml替换过去,然后加入编译。
经过编译验证,该方法确实可以生效,但是也存在一个问题。因为我们一般在一套code base中不仅仅只支持一个项目,如果某一个项目需要替换该文件,而其他项目不需要,在编译了需要替换的项目后,该文件已经拷贝过去了,再编译其他项目时不会自动恢复原来的文件。
2. 采用overlay机制实现
因为在高版本(貌似Android4.0以后)中不支持对AndroidManifest.xml的overlay了,要实现overlay就需要对编译脚本做一些改动。
改动1(build/core/definitions.mk),该文件中定义了编译系统中使用的方法,添加两个方法如下:
第一个方法是来读取系统中所有加入的overlay文件路径,参考build/core/package_internal.mk中package_resource_overlays的获取方法。
define get-overlay-paths
$(wildcard $(foreach dir, $(PRODUCT_PACKAGE_OVERLAYS), \
$(addprefix $(dir)/, $(1)))) \
$(wildcard $(foreach dir, $(DEVICE_PACKAGE_OVERLAYS), \
$(addprefix $(dir)/, $(1))))
endef
第二个方法是获取第一个存在的文件。
define get-first-existing-file
$(shell for f in $(1); do [ -f $$f ] && echo $$f && break; done)
改动2(build/make/core/android_manifest.mk),将对full_android_manifest的赋值改为如下:
#full_android_manifest := $(LOCAL_PATH)/$(LOCAL_MANIFEST_FILE) 注掉原来的行
android_manifest_path := $(LOCAL_PATH)/$(LOCAL_MANIFEST_FILE)
android_manifest_overlay_path := \
$(call get-overlay-paths, $(android_manifest_path )) \
$(android_manifest_path )
full_android_manifest := $(call get-first-existing-file, $(android_manifest_overlay_path ))
经过编译验证,该方法有效。
3. 采用Android编译系统中LOCAL_FULL_MANIFEST_FILE变量来实现
LOCAL_FULL_MANIFEST_FILE的作用是定义客制化AndroidManifest.xml的路径,个人认为它是对Android高版本不支持AndroidManifest.xml overlay的补充(我没有去验证哈),如果未定义该变量,则使用默认的LOCAL_MANIFEST_FILE,否则,会用LOCAL_FULL_MANIFEST_FILE。
需要做的是在该module的Android.mk中添加如下:
LOCAL_FULL_MANIFEST_FILE := xx/xx/AndroidManifest.xml 将需要的AndroidManifest.xml路径赋给该变量
经过编译验证,该方法有效。