• 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

  • 相关阅读:
    ASP.net注意点小结
    AJAX笔记
    为Dreamweaver写的扩展—jQuery自动提示.
    Cisco PIX防火墙配置上
    Cisco PIX防火墙配置下
    基于DNS的负载均衡
    c#使用文本框TextBox使用ctr+enter直接跳到指定Button
    Google marker
    C#中的关键字详解
    android中,锁屏之后是不是会关掉部分服务?怎么让我的服务不被关掉?
  • 原文地址:https://www.cnblogs.com/xgjblog/p/14817279.html
Copyright © 2020-2023  润新知