android资源替换方案overlay,Android 运行时资源替换----Runtime Resource Overlay
先抛一个问题:现在有一个第三方应用,没有代码,只有编译好的apk,在不去改动这个apk的前提下,如果想改变这个应用中的一些资源显示效果,比如改变一个button的文字,一个imageview的背景,有没有可能做到?
我的答案是有可能做到(废话,做不到的话让我怎么往下写(bian))。直接上栗子,拿蘑菇街的应用来开刀。先看下蘑菇街的部分原生效果图。
红色框中的文字就是我要改变的地方,接下来放改变后的效果图。
注意圈起来的红色部分文字已经改变了,而我并没有去改动mogujie的apk。不要问为啥替换后的文字这么的丧心病狂,我会说我被mogujie伤害过吗?
上面的这个栗子就引出了我要讲的Android 资源替换-----Runtime Resource Overlay(RRO)。RRO是在Android5.0后引入的,它能在 apk 运行时,自动加载需要定制的资源,而不加载原有的资源。mogujie的应用我压根没动,只是当系统在调用mogujie的资源的时候,我给它分配了一个同名的资源,这样系统不会去获取mogujie原生的资源,而获取的是我分配给它的资源。给出了感性的一个解释,下面开始讲解具体的原理,再次之前需要先说明下应用查找资源的过程。
应用通过 getString/getDrawable去调用某个资源时,会将这个resources ID 作为参数传给 framework 层。同一名称但不同状态的 resources ID 是一样的,比如不同分辨率但名称相同的图片分别被放置在了drawable-hdpi/drawable-ldpi/drawable-mdpi下,但在编译时针对该图片生成的resources ID只有一个。framework 层 查 找 资 源 时会使用这个resources ID , 同时还要使 用 当前 系 统 的configuration(分辨率、语言、横竖屏)。通过 resources ID 和 configuration,系统会找到最匹配的资源(如果没有找到,则使用默认的 ),最后将找到的resources ID返回给 apk。整个过程如下图所示。
结合上图可以看出应用只是负责提供资源IDs,系统层会根据当前的语言,横竖屏,分辨率等状态去取适当的资源ID加载。这种不连续性就提供了资源欺骗的可能,RRO发生在系统层检索资源时,应用层使用资源的接口并没有改变,甚至都不知道还有一个跟它同名的资源存在,因此使用RRO更改应用的资源时无需对原来的应用做任何修改。
RRO机制的运用是依靠overlay apk实现的,与普通的apk相比它不包含代码,只有资源。一个overlay apk只能替换一个目标apk的资源,但一个目标apk的资源可以被多个overlay apk更改。在使用RRO机制的前提是必须要知道待替换目标apk中的资源名,比如我要替换mogujie在桌面的应用名称,就要知道这个应用名称是在哪个资源文件中写入的,这得依靠反编译知识,这里不详述了,直接给出
有了这个就可以开始尽情的替换了。下面就是我制作的mogujie overlay 的目录结构。
其中AndroidManifest.xml中的内容如下:
package="com.mogujieoverylay">
targetPackage的值必须要与mogujie应用的package值一样(反编译可以获取),priority的值是针对一个目标apk的资源可以被多个overlay apk更改"而设置的一个优先级,值越大优先级越高。
替换的几个字串都是放在values目录下的string.xml中
唯品会
不买
别逛
拒聊
呵呵
这个过程的难度在于反编译后,如何正确的猜测出目标apk中资源的名称,只有拿到了正确的资源名才能保证overlay成功。到此打包编译就生成了一个overlay apk。在罗嗦下打包的apk的方法.1在源码环境下使用Android.mk文件然后进行模块化编译,这个是最方便快捷的,我刚才使用的Android.mk内容如下
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := Mogujieoverlay
LOCAL_SRC_FILES := $(call all-java-files-under,res)
LOCAL_SDK_VERSION = current
LOCAL_PACKAGE_NAME := Mogujieoverlay
include $(BUILD_PACKAGE)
2使用aapt命令打包,然后签名,必须要签名,否则打包生成的apk是无法安装的。
打包命令:
aapt p -f -I [ANDROID_SDK_PATH]/android.jar \
-S [OVERLAY_PATH]/res \
-M [OVERLAY_PATH]/AndroidManifest.xml \
-c [PRODUCT_AAPT_CONFIG] \
-F [MODULE_NAME]-overlay.apk
签名命令:
java -jar [PATH]/signapk.jar \
[PATH]/platform.x509.pem \
[PATH]/platform.pk8 \
[MODULE_NAME]-overlay.apk [MODULE_NAME]-overlay.apk_signed
由于RRO是在系统层做的,Android出于安全考虑,要想overlay生效必须将生成的overlay apk放到/system/vendor/overlay目录下才会生效。RRO的应用场景主要是在方案开发时用到,上面的例子只是替换了string资源,实际上RRO能支持除了 layout 和 AndroidManifest 外的所有资源定制,在做ROM定制开发时还是非常有用的。曾经测试报了一个google应用字串太长显示不全的问题,但google 应用压根就没有代码,只有apk,当时就是靠RRO来解决该bug的。RRO剥离了代码和资源的共生关系,在方案开发中可以针对不同的显示需求,打包不同的overlay apk,不用每次更改UI资源都去修改原来的应用。
android资源替换方案overlay,Android 运行时资源替换----Runtime Resource Overlay相关推荐
- 全面盘点当前Android后台保活方案的真实运行效果(截止2019年前)
全面盘点当前Android后台保活方案的真实运行效果(截止2019年前) 本文原作者"minminaya",作者网站:minminaya.cn,为了提升文章品质,即时通讯网对内容作 ...
- android屏幕适配教程,Android屏幕适配方案,android屏幕适配
Android屏幕适配方案,android屏幕适配 文章转载禁止用于商业用途,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处莫高雷草原以及作者@JiongBull. Android屏幕适配方 ...
- U3D游戏运行时资源是如何从AB中加载出来的
U3D游戏运行时资源是如何从AB中加载出来的 以安卓为例 1,游戏启动,自定义版本管理器去安卓的持久化目录下查找我们自定久的版本管理文件 rep.db,若该文件不存在,说明这是游戏第一次启动,于是就把 ...
- Android不使用支持库请求运行时权限
Android 6.0后,用户开始在应用运行时向其授予权限,而不是在应用安装时授予.Android官网上也有相关教程:在运行时请求权限.但教程是使用支持库来举例的,用支持库的话,APK的大小也会变得很 ...
- 【转】android IDE——通过DDMS查看app运行时所占内存情况
在Android内存优化方面,我们不可能做到没有大内存的占用情况. 所以有时候要清楚我们的app到底占用了多少内存,哪一步操作占用了多少的内存. 这时候,android的ddms中提供了一个工具,是可 ...
- android权限询问,Android:检查是否必须询问运行时权限
我想检查一个特定的应用程序是否需要在运行时处理Android Marshmallow运行时权限. 以下假设是否正确? /** * Checks whether runtime permissions ...
- android 热更新 方案,与Android热更新方案Amigo的初次接触
主要记下引入Amigo的过程. 修复前:点击文字没有跳转 修复后:点击文字可以跳转(增加了Activity和布局文件) 其实热更新最重要的是不需要重新安装apk,有的甚至不需要重启app,就可以更新代 ...
- WebAssembly运行时库(WASM runtime:wasmer 或 wasmtime)\将rust官方demo猜数字编译为WASI目标并使用Wasmer运行
文章目录 WebAssembly运行时库(wasmer 或 wasmtime.wasmer-go) 一.引子 1. 什么是WASI 2. 有哪些优秀的 WebAssembly 运行时? 二.wasme ...
- 运行时数据区(Run-Time Data Areas)
在装载阶段的第(2),(3)步可以发现有运行时数据,堆,方法区等名词 (2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构 (3)在Java堆中生成一个代表这个类的java.lang.C ...
最新文章
- 资源贴|吴恩达新课发布第1天,3万人观看 | 完整PPT
- CRUD之delete操作
- Android--开发资源管理器/优化ListView显示列表方法
- ListView几个比较特殊的属性
- 高级 | Java中获取类名的3种方法
- 基于ZigBee 自组网模块的路灯控制网络
- 深入java核心_Java核心(五)深入理解BIO、NIO、AIO
- pycham窗口显示多个编辑页面
- 实验9Linux共享内存通信,操作系统原理与Linux实践教程(卓越工程师培养计划系列教材)...
- 人机协作机器人发展趋势_一文了解全球工业机器人发展现状:轻型化、柔性化及人机协作成为发展趋势...
- 解决 mac ssh空闲 连接断开问题
- 机器人编程和python的区别_机器人编程和少儿编程的区别
- Unity 3D WebView 插件之基础介绍(一)
- 微信缓存css怎么清理,前端清除缓存方法(微信缓存引起的bug)
- Android 对ListView和RecyclerView的两个BaseAdapter封装分享
- beyond compare如何设置只比较实际内容?(使用关联规则比较)
- java获取项目所在服务器的ip地址和端口号(获取当前ip地址)
- JAVA练习题38:正则表达式基本练习
- python turtle 绘制七段数码管以及14段数码管显示字母和时间
- 滴滴云「于某声」在「服务器采购过程中」受贿累计超过 1000 万元:已移交公安机关
热门文章
- 用于手语识别的自注意力机制
- c语言的一些易错知识积累
- 利用HTML5 Canvas和Javascript实现的蚁群算法求解TSP问题演示
- 用简单的C语言实现多任务轮流切换(模拟操作系统线程机制)【转】
- NS_ASSUME_NONNULL_BEGIN 延伸
- OCA读书笔记(6) - 配置Oracle网络环境
- mysql 使用真正的utf-8编码
- 电脑如何格式化_分别手把手教你在Windows和mac上格式化磁盘
- java判断是否为数组_JS如何判断是否是数组?
- 编程入门:准备学Python入门编程 为什么前辈一直劝我不行?