当前位置:首页 » 《资源分享》 » 正文

Android 源码之overlay分析_云儿的博客

28 人参与  2021年11月02日 15:23  分类 : 《资源分享》  评论

点击全文阅读


文章目录

        • 前言
        • 编译方式
        • 前提
        • 静态Overlay
        • res 目录
        • 运行时Overlay
          • 与SRO的区别
          • 配置步骤
          • 存在的问题
          • RRO注意事项
        • 资源ID
        • 总结
        • 关于源码中的device.mk

前言

Android Overlay是一种资源替换机制,它能在不重新打包apk的情况下,实现资源文件的替换(res目录非assert目录),Overlay又分为静态Overlay(Static Resource Overlay)与运行时Overlay(Runtime Resource Overlay),他有自己的局限性,它无法替换java文件。
Android Override是一种文件替换方式,注意是文件替换,他有自己的局限性,它无法覆盖一个APK中的某一个文件,但是可以直接覆盖APK。

编译方式

编译类型:mmm mm m
source build/envthup.sh
brunch -b -f (override文件打入源码中)
lunch
make
adb sync

framework-res.apk
framework-res__auto_generated_rro_product.apk

adb shell sync 命令:

1,在shell中执行
2,将内存缓冲区中的数据 写入到磁盘

adb sync 命令:
命令意思:同步更新/data/或/system/下的数据
命令用法:adb sync [directory]
如果不指定目录,将同步更新/data/和/system

前提

Overlay需要在源码编译环境中完成

静态Overlay

静态Overlay,简称为SRO,发生在编译时,需要在Android系统源码环境中进行配置。\device\sample\products\backup_overlay.mk
SRO生成图

res 目录

目录Directory资源类型Resource Types
res/anim/XML文件,它们被编译进逐帧动画(frame by frame animation)或补间动画(tweened animation)对象
res/drawable/.png、.9.png、.jpg文件,它们被编译进以下的Drawable资源子类型中:要获得这种类型的一个资源,可以使用Resource.getDrawable(id) 位图文件 9-patches(可变尺寸的位图)为了获取资源类型,使用mContext.getResources().getDrawable(R.drawable.imageId)
res/layout/被编译为屏幕布局(或屏幕的一部分)的XML文件。参见布局声明(Declaring Layout)
res/values/可以被编译成很多种类型的资源的XML文件。
res/xml/任意的XML文件,在运行时可以通过调用Resources.getXML()读取。
res/raw/直接复制到设备中的任意文件。它们无需编译,添加到你的应用程序编译产生的压缩文件中。要使用这些资源,可以调用Resources.openRawResource(),参数是资源的ID,即R.raw.somefilename。

注意: 不像其他的res/文件夹,它可以保存任意数量的文件,这些文件保存了要创建资源的描述,而不是资源本身。XML元素类型控制这些资源应该放在R类的什么地方。
尽管这个文件夹里的文件可以任意命名,不过下面使一些比较典型的文件(文件命名的惯例是将元素类型包含在该名称之中):

     array.xml 定义数组
     colors.xml 定义color drawable和颜色的字符串值(color string values)。
     			使用Resource.getDrawable()Resources.getColor()分别获得这些资源。
     dimens.xml 定义尺寸值(dimension value)。使用Resources.getDimension()获得这些资源。
     strings.xml 定义字符串(string)值。使用Resources.getString()或者
     			Resources.getText()获取这些资源。
     			getText()会保留在UI字符串上应用的丰富的文本样式。
     styles.xml 定义样式(style)对象。

放在这里的图像资源可能会被aapt工具自动地进行无损压缩优化。比如,一个真彩色但并不需要256色的PNG可能会被转换为一个带调色板的8位PNG。这使得同等质量的图片占用更少的资源。所以我们得意识到这些放在该目录下的二进制图像在生成时可能会发生变化。如果你想读取一个图像位流并转换成一个位图(bitmap),请把图像文件放在res/raw/目录下,这样可以避免被自动优化。

运行时Overlay

运行时Overlay,简称RRO,顾名思义,该机制的资源替换发生在运行时。

与SRO的区别
  1. RRO能直接定制替换第三方APK的资源,而不需要其源码。SRO如上节所述,则需要对应APK的源码才能完成,一般而言,第三方是不会提供项目源码的。
  2. RRO的编译结果会得到一个xxx_overlay.apk,加上原项目的apk,总共会有2个apk,而SRO最终只会得到一个已经完成资源替换的apk。得到的overlay.apk可以视为一个正常的apk,因为它能被安装,含有自己的AndroidManifest.xml文件,当然正常下,overlay.apk是不含有执行代码的。
  3. RRO不能替换AndroidManifest.xml文件及reference resource 类型的文件,如layout、anim、xml目录中的xml文件。虽然RRO具有自己的AndroidManifest.xml文件,但它却不能替换源项目中的AndroidManifest.xml文件。关于layout目录中的xml文件,SRO是可以替换的。
配置步骤

下面以创建Launcher的RRO为例进行说明
创建一个新项目,包名命名为com.android.launcher.overlay,事实上包名可以随意命名,这样命名可读性高,一看包名就知道是哪个项目的overlay。
编辑overlay项目的AndroidManifest.xml文件,文件内容如下:

	<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    	package="com.android.launcher.overlay"> 
    	<overlay android:targetPackage="com.android.launcher"  android:priority="1"/> 
	</manifest>

其中,android:targetPackage:需要overlay的项目的包名
android:priority:设置overlay.apk的优先级,值越大,优先级越高,用于存在多个overlay.apk情况下的判断。
替换相对应路径下的res资源
编写mk文件,编译、打包、签名,并将生成的overlay.apk输出到/vendor/overlay目录下,Android 8.0以后 其中签名需要与源项目签名一致,否则不会生效。

存在的问题

把app放到vendor/overlay下面以后,还要activate,默认是disable的
activate有两种方式:
一种是overlay的app的清单文件中,overlay标签写 isStatic=“true”
一种是加系统属性ro.boot.vendor.overlay.theme=overlay的app的包名,分号分割
PS:没有源码环境,或者不懂mk文件,可以通过root手机,直接将我们生成的overlay.apk直接push到/vendor/overlay目录下,来测试RRO机制。
部分厂商可能更改了路径,可通过adb shell pm path xxxx.overlay 查找到路径,前提是手机中已经安装了某个overlay的apk。

RRO注意事项
  1. 生成的apk需要指定输出到vendor下才会生效
    LOCAL_MODULE_PATH := $(TARGET_OUT)/vendor/overlay
    include $(BUILD_PACKAGE)
  2. 由于overlay替换的是资源文件,所以必须调用res目录资源文件
    LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
  3. android:priority范围是0-9999,过万就不生效了 (越大优先级越高)
    单个overlay包
    当对应项目只有一个overlay包时,那么查找资源时,会先从overlay.apk中进行查找,查找成功直接返回,反之则从app中查找。
    多个overlay包
    当对应项目具有多个overlay包时,会按照overlay包的优先级从高到底依次进行查找,如果overlay包都查找失败,才会到app中进行查找。
    以访问R.drawable.ic_01为例,会先从overlay1包先查找,因为其优先级最高,查找到则直接返回。
    如果访问R.drawable.ic_02,先从overlay1查找,查找失败,接着从overlay2中查找,查找到直接返回。
    如果访问R.drawable.ic_03,依次从overlay1,overlay2中查找,查找失败,最后会从app中查找到,并返回。
    RRO流程图

资源ID

资源文件在打包之后,会在R.java文件中生成一个对应的int类型资源id,这个id遵循以下的规则:
0xppttiiii
其中,
pp:01表示是系统资源,7f表示是应用资源
tt:用于表示资源类型,如string、array、图片资源等
iiii:用于表示相同类型的不同资源

总结

SRO实际上只是利用AAPT重新打包,发生在编译时;RRO,才是overlay机制的关键,其本质是Android系统的动态资源查找机制。
overlay新增一个资源通过add-resource 方式添加

<!-- add for status bar system icon define -->
    <add-resource type="string" name="status_bar_child_mode"/>
    <string translatable="false" name="status_bar_child_mode">child_mode</string>

关于源码中的device.mk

项目下的mk文件
这里有一个overlay的先后问题,比较重要。由高到底

  1. DEVICE_PACKAGE_OVERLAYS
  2. PRODUCT_PACKAGE_OVERLAYS–级别最高,也就是优化用PRODUCT_PACKAGE_OVERLAYS中的overlays(高于DEVICE_PACKAGE_OVERLAYS)
  3. PRODUCT_ENFORCE_RRO_TARGETS
  4. PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS
    在Android O上面 Google增加了一个enforced RRO的方法,可以把之前的build time overlay强制转换成runtime resource overlay.如果overlay的是framework-res的资源包,那麽会自动生成一个file在/vendor/overlay/framework-res__auto_generated_rro.apk.里面会包含overlay的资源。也就是说,对于加了PRODUCT_ENFORCE_RRO_TARGETS的模块,便由SRO变成RRO模式,如果仍然想保持SRO模式,就需要使用到PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS变量。
    具体原因见此文章

另外,出于安全性考虑,谷歌公司在Android 8.0版本后,不仅要求Overlay apk 和Target apk这两个apk中的签名–致,还需要在源项目Targetapk中的AndroidManifest. xml文件中声明具有android.permission. CHANGE_ OVERLAY_ PACKAGES 的权限。

代码中存在的RRO.apk
在这里插入图片描述


点击全文阅读


本文链接:http://zhangshiyu.com/post/30417.html

文件  资源  替换  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1