zoukankan      html  css  js  c++  java
  • 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中的内容如下:


    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mogujieoverylay">
    <overlay android:targetPackage="com.mogujie" android:priority="1"/>
    </manifest>
    targetPackage的值必须要与mogujie应用的package值一样(反编译可以获取),priority的值是针对一个目标apk的资源可以被多个overlay apk更改"而设置的一个优先级,值越大优先级越高。
    替换的几个字串都是放在values目录下的string.xml中


    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    <string name="app_name">唯品会</string>
    <string name="host_tab_triple">不买</string>
    <string name="host_tab_follow">别逛</string>
    <string name="host_tab_msg">拒聊</string>
    <string name="host_tab_my">呵呵</string>
    </resources>
    这个过程的难度在于反编译后,如何正确的猜测出目标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资源都去修改原来的应用。
    ————————————————
    版权声明:本文为CSDN博主「思棉叶」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/azhengye/article/details/49050631

  • 相关阅读:
    遗传算法(Genetic Algorithm, GA)及MATLAB实现
    CCF CSP 201809-2 买菜
    PAT (Basic Level) Practice (中文)1008 数组元素循环右移问题 (20 分)
    PAT (Basic Level) Practice (中文)1006 换个格式输出整数 (15 分)
    PAT (Basic Level) Practice (中文)1004 成绩排名 (20 分)
    PAT (Basic Level) Practice (中文)1002 写出这个数 (20 分)
    PAT (Advanced Level) Practice 1001 A+B Format (20 分)
    BP神经网络(原理及MATLAB实现)
    问题 1676: 算法2-8~2-11:链表的基本操作
    问题 1744: 畅通工程 (并查集)
  • 原文地址:https://www.cnblogs.com/xgjblog/p/14817279.html
Copyright © 2011-2022 走看看