android 在很早时候就引入了overlay机制,目的是为了方便客制化,不需要修改源码,只需要修改overlay里的东西,就可以达到修改的目的。overlay分为两种,静态的overlay和动态的overlay。下面简单来说下这两种overlay:
静态的overlay :这种overlay比较简单,把资源文件放在device目录对应的项目下面,原理就是在编译时直接引用overlay下的资源文件,代替源码下的资源文件,这种方法比较简单。
动态的overlay :这种方法比较复杂,用的比较少。把资源文件直接编译成一个独立的apk,运行时会把原apk的资源文件替换,这就是所谓的动态overlay。
首先需要一个AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 Google Inc. All Rights Reserved. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.settings.overlay">
<overlay android:targetPackage="com.android.settings" android:priority="1" android:isStatic="true" />
</manifest>
这里最关键的就是android:targetPackage这个属性,需要被覆盖的。这个应用本身的包名是可以随便取的,但是为了可读性,一般都在被覆盖的包名后面加上overlay,例如我这里的com.android.settings.overlay。
然后一个Android.mk文件
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PACKAGE_NAME := FotaOverlay
LOCAL_MODULE_TAGS := optional
LOCAL_CERTIFICATE := platform
LOCAL_SRC_FILES := $(call all-java-files-under, res)
LOCAL_SDK_VERSION := current
LOCAL_IS_RUNTIME_RESOURCE_OVERLAY := true
ifeq ($(LOCAL_RRO_THEME),)
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/overlay
else
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/overlay/$(LOCAL_RRO_THEME)
endif
include $(BUILD_PACKAGE)
建一个res文件夹,里面放资源文件
还需要注意一点,被覆盖的apk要有这个权限,否则是不会生效的。
<uses-permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES" />
编译完成之后,apk会在out的/vendor/overlay目录生成。
这两种overlay有一个很大的区别,动态overlay不能替换AndroidManifest.xml文件及reference resource 类型的文件,如layout、anim、xml目录中的xml文件。