Android 运行时资源替换----Runtime Resource Overlay实践

转载自 【车载 Android】应用换肤方案(一) - Runtime Resource Overlay

Android从M开始加入了动态资源overlay机制 runtime resource overlay(RRO),这个是sony贡献的,实现机制如下图,就是在框架中建立一套资源ID映射表,通过这个映射表动态切换不同的主题。
Android 运行时资源替换----Runtime Resource Overlay实践_第1张图片

RRO 换肤实践

首先准备一个需要被换肤的应用,这里我们随便新建一个APP为例,下面我们将新建的Target App工程称为『目标应用』,目标是利用RRO机制替换目标应用中颜色值。

Android 运行时资源替换----Runtime Resource Overlay实践_第2张图片

第 1 步:创建资源包,配置 AndroidManifest.xml

首先我们要新建一个独立的 app 工程,这个应用存在的意义就是放置『目标应用』的资源文件,下面我们将其称为『资源包』。它虽然是一个应用工程,但是不包含逻辑代码,只能用于存放资源文件。

注意到这一步,我们实际上新建了两个app工程,一个是目标应用,一个是资源包。



    

    


如果某个APK 的AndroidManifest.xml中包含 标记作为 标记的子项,该APK将被视为『资源包』 。

  • 【必需设定】android:targetPackage 用于指明 RRO 想要替换的『目标应用』。
  • 【必需设定】android:hasCode必须设定为 false。由于无法替换代码,因此 RRO 无法使用 DEX 文件。
  • 【非必需设定】android:targetName 用于指明 RRO 『目标应用』的可替换资源子集的名称。如果『目标应用』没有定义可替换资源集,此属性就不需要设定。

可替换资源集

在 Android 10 或更高版本中,『目标应用』可以使用 标签公开一组允许 RRO 替换的资源,未被公开的资源,则不允许 RRO 替换。


    
        
            
            
        
    


一个 APK 可以定义多个 标记,但每个标记必须在该软件包中具有唯一的名称。例如:

  • 两个不同的资源包可以同时定义 。
  • 一个 APK 不能具有两个 块。

然后需要在资源包的AndroidManifest.xml中使用targetName指定ThemeResources。



    

    



当目标应用定义 标记时,资源包的需满足以下条件:

  • 必须指定 targetName。

  • 只能替换 标记中列出的资源。

  • 只能定位到一个 名称。

限制策略

使用标记可以在目标应用中对可替换资源施加限制。type属性指定叠加层必须满足哪些政策的要求才能替换包含的资源。支持以下类型:

  • public:任何叠加层均可替换相应资源。
  • system:系统分区上的任何叠加层均可替换相应资源。
  • vendor:vendor 分区上的任何叠加层均可替换相应资源。
  • product:product 分区上的任何叠加层均可替换相应资源。
  • signature:使用与目标 APK 相同的签名进行签名的任何叠加层均可替换相应资源。

   
       
   
   
       
       
   


如需指定多个政策,请使用竖线 (|) 作为分隔符。 如果指定了多个政策,叠加层只需满足一个政策的要求即可替换 标记中列出的资源。

第 2 步:定义资源映射

  • Android 10或以下版本
    在 Android 10 或更低版本中,系统是根据资源的名称进行资源替换,所以我们只需要在资源包中将需要替换的资源定义好即可。

Android 运行时资源替换----Runtime Resource Overlay实践_第3张图片

  • Android 11或以上版本
    在 Android 11 或更高版本中,Google推荐在『资源包』的res/xml 目录中创建一个文件overlays.xml,枚举出应覆盖的『目标应用』的资源值及其替换值。


    
    
    
    
    
    
    
    


注意,target标签中的color并没有带上@标记,他实际上仅仅是一个字符串而不是引用

然后在资源包的AndroidManifest.xml 中将android:resourcesMap 属性的值设置为资源映射文件。



    

    


第 3 步:构建资源包

构建出的资源包,我们在调试时,可以使用Android Studio直接安装,如下所示。

  1. 运行目标应用和资源包
  2. 在data/app 目录上右键,选择 “Synchronize” 选项

以上两步之后data/app目录下会多出两个路径,分别代表目标应用和资源包的apk。

正式发布时,『资源包』可以发布到vendor/overlay目录下,『目标应用』则可以根据需要可以灵活放置。之后重启Android系统即可。

第 4 步:启用/停用 RRO

使用OverlayManager提供的API可以启用、停用RRO。OverlayManager在公开的Android SDK中并没有提供,如果是使用Gradle构建工程,需要额外使用AOSP源码编译一个framework.jar并引入才可以使用,同时应用签名也需要使用Android系统签名,让应用成为系统级应用。

OverlayManager manager = MainActivity.this.getSystemService(OverlayManager.class);
OverlayInfo overlayInfo = manager.getOverlayInfo("com.android.target.overlay.ten", UserHandle.CURRENT_OR_SELF);
manager.setEnabled("com.android.target.overlay.ten", !overlayInfo.isEnabled(), UserHandle.CURRENT_OR_SELF);

在启用或停用RRO后,配置更改事件会传播到目标应用,并且目标应用的 activity 会重新启动。

如果要在手机端测试,可以使用adb命令来开启、关闭RRO

adb shell cmd overlay enable [com.android.target.overlay.ten] // 开启
adb shell cmd overlay disable [com.android.target.overlay.ten] // 关闭

Demo

官方文档

你可能感兴趣的:(android,android,studio,java)