深入理解Android(三):Xposed详解

2016-07-25 11:49:14来源:oschina作者:waffle930人点击

深入理解Android(三):Xposed详解
作者邓凡平 发布于 2016年1月4日 |首届应用性能管理大会 APMCon,聚焦国内外性能优化先进技术。 讨论 分享到:
微博
微信
Facebook
Twitter
有道云笔记
邮件分享 稍后阅读
我的阅读清单

编者按:随着移动设备硬件能力的提升,Android系统开放的特质开始显现,各种开发的奇技淫巧、黑科技不断涌现,InfoQ特联合《深入理解Android》系列图书作者邓凡平,开设深入理解Android专栏,探索Android从框架到应用开发的奥秘。


一、背景

Xposed,大名鼎鼎得Xposed,是Android平台上最负盛名的一个框架。在这个框架下,我们可以加载很多插件App,这些插件App可以直接或间接操纵系统层面的东西,比如操纵一些本来只对系统厂商才open的功能(实际上是因为Android系统很多API是不公开的,而第三方APP又没有权限)。有了Xposed后,理论上我们的插件APP可以hook到系统任意一个Java进程(zygote,systemserver,systemui好不啦!)。


功能太强大,自然也有缺点。Xposed不仅仅是一个插件加载功能,而是它从根上Hook了Android Java虚拟机,所以它需要root,所以每次为它启用新插件APP都需要重新启动。而如果仅是一个插件加载模块的话,当前有很多开源的插件加载模块,就没这么复杂了。


Anyway,Xposed强大,我们可以学习其中的精髓,并且可以把它的思想和技术用到自己的插件加载模块里。这就是我们要学习Xposed的意义。


Xposed支持32位和64位的dalvik以及ART,同时支持selinux。我仔细看了下,如果拓展把这些东西都讲的话,一个是很枯燥,另外一个是背离了我们本章讲解插件的主线。所以,本章将围绕下面几个点开展介绍:


l 32位dalvik上非selinux模式下的xposed实现原理


64位、selinux模式其实难度不在虚拟机上,而是在selinux上。


二、 初识Xposed

本章先来介绍下Xposed,这是一个大工程,包含多个项目,我也是花了不少时间才把它整个玩转起来的。Xposed包含如下几个工程:

XposedInstaller,这是Xposed的插件管理和功能控制APP,也就是说Xposed整体管控功能就是由这个APP来完成的,它包括启用Xposed插件功能,下载和启用指定插件APP,还可以禁用Xposed插件功能等。注意,这个app要正常无误得运行必须能拿到root权限。
Xposed,这个项目属于Xposed框架,其实它就是单独搞了一套xposed版的zygote。这个zygote会替换系统原生的zygote。所以,它需要由XposedInstaller在root之后放到/system/bin下。
XposedBridge。这个项目也是Xposed框架,它属于Xposed框架的Java部分,编译出来是一个XposedBridge.jar包。
XposedTools。Xposed和XposedBridge编译依赖于Android源码,而且还有一些定制化的东西。所以XposedTools就是用来帮助我们编译XposedXposedBridge的。

提示,提示,提示:


我把所有相关代码都下载并放到下面的地址了:


https://code.csdn.net/Innost/xposed-learning 里边包含:


1 xposed所有代码库的内容


2 XposedDemo:Xposed插件APP Demo,非常简单


3 XposedDemoTarget:XposedDemo将hook上的目标App


2.1 编译Xposed

下面介绍下如何编译Xposed,这里以Android 4.4.4为例。做Android开发最好配一个Nexus手机或Pad。我用得是Nexus 7 2013Wi-Fi版。Anyway,Xposed的编译和具体机器无关,不过下面的前提条件需要满足:

准备Android 4.4.4源码。我分享了很多AOSP源码,注意:我提供的源码没有.repo和.git,虽然省了很多空间,不过在编译Xposed的时候,还是需要有.repo。
下载我提供的Xposed源码和测试Demo。

好,马上开始我们的步骤:


2.1.1 下载支持库

根据XposedTools的说明,我们先要修改下AOSP源码里的.repo,具体步骤如下:

进入AOSP/.repo目录。
在.repo目录下新建local_manifests目录。
把XposedTools/local_manifests/下的目标文件拷贝过去。local_manifests/目录下是各种API版本(即SDK=19,21之类)对应的xml文件。由于本例对应的SDK版本是19,所以需要把该目录下xposed_sdk19.xml文件拷贝到.repo/local_manifests/目录下。

这个文件是什么内容呢?来看图1:



这个文件内容是啥意思呢?

:新添远程仓库地址为github。
第一个:为frameworks/base/cmds/下新增加xposed工程。当然,这个工程我们刚才下载过了。你可以直接copy到指定目录下。
:移除AOSP/build目录。xposed有自己的处理。
第二个:下载xposed自己的build。path="build",表示下载路径就是AOSP/build。

配置好后,请在AOSP目录下执行repo sync。这样它会根据manifests更新AOSP源码。当然,也可以只是下载frameworks/base/cmds/xposed工程和更新build工程。


注意,repo sync是一个重型操作,会导致所有工程都进行一次同步。我建议的方法是直接下载和更新对应的工程


比如,下载xposed工程,用repo sync frameworks/base/cmds/xposed即可。对于build目录,先把原来的build挪到其他地方。然后repo sync build即可。


好了,到此,所有源码都已经ready了。


2.1.2 修改build.conf

下面我们进入XposedTools目录,然后修改其中的build.conf文件。该文件用于指示AOSP源码等参数。如图2所示:



XposdTools提供了一个build.conf.sample模板,图2中的build.conf文件是在这个模板基础上修改而来。红框中是我修改的结果。其他选项没有变化。


2.1.3 执行build.pl

到XposedTools目录下,执行:./build.pl -t arm:19命令,这表明我要编译arm平台上SDK=19版本的xposed框架。注意,./build.pl --help会打印出使用方法。build.pl是一个perl脚本。图3是编译过程截图:



图3中,你可以发现build.pl跑到AOSP源码目录下,执行了:

. build/envsetup.sh:初始化AOSP编译环境
lunch aosp_flo-userdebug:选择交叉编译平台。注意,这一块我是修改了XposedTools/xposed.pom,使它单独为我的nexus 7编译,而不是针对ARM平台做generic的编译。
make -j4 xposed libxposed_dalvik:编译xposed和libxposed_dalvik这两个目标文件。

在使用build.pl时,它还依赖一些Perl的类库,请童鞋们按照下面步骤下载这些依赖库:


sudo apt-get install libconfig-inifiles-perl


sudo apt-get install libio-all-perl


sudo apt-get install libfile-readbackwards-perl


sudo apt-get install libfile-tail-perl


sudo apt-get install libtie-ixhash-perl


build.pl执行过程中,如果报还有其他依赖库未找到,请通过下面命令


apt-cache search perl XXX 来查找需要apt-get install哪个目标库。XXX是build.pl执行过程中报错时提供的库信息


2.1.4 编译结果

编译完成后,将产生一个zip包到AOSP/out/sdk19/arm下。AOSP/out是我在build.conf中指定的目录。如图4所示:



编译结果是一个xposed-v65-arm-custom-build-xyz-20151030.zip包,这个包可以通过recovery刷到手机上。包的内容就是files文件夹下的内容,包含:

system/bin/app_process_xposed:xposed版zygote。
system/bin/libxposed_dalvik.so:xposed框架的native层。
system/xposed.prop:xposed框架信息,包含版本号等。内容如右边图所示。三、 XposedInstaller

XposedInstaller是Xposed的App,用于管理Xposed框架和插件App。本节我们主要讨论它是如何安装Xposed框架和插件App的。


XposedInstaller启动界面如图5所示:



图5中可知XposedInstaller提供好几项子页面。第一个“框架”用来安装或卸载Xposed框架的。我们来看它。


3.1 安装Xposed框架

如图6所示:



注意,图6右上角的“程序自带”两个版本号,分别是app_process版本号为58,XposedBridge.jar版本号是54.


而“激活”这两项为空,因为我们的系统还没有安装Xposed框架。


“程序自带”是什么意思?原来,XposedInstaller在自己的assets目录下携带了所需要的xposed框架程序和模块,如图7所示:



从图7可知,XposdInstaller自带了xposed版zyote(比如app_process_xposed_sdk16),为了更好得支持不同版本的Android,它还区分了SDK版本。另外,XposedInstaller也支持刷机包把xposed框架模块刷入系统,比如Xposed-Installer-Recovery.zip,里边包含的主要内容就是一个脚本,在recovery模式下运行,其内部也是把assets里的文件拷贝到/system相关目录中。这一块我们后续看代码就知道怎么玩儿了。


安装Xposed框架的主要功能由InstallerFragment.java提供,我们看看相关代码。


3.1.1 onCreateView

onCreateView函数是Fragment里初始化UI的核心回调,其代码如图8所示:



图8代码中最后的refreshVersions用于获取版本号,也就是图6中右上角“程序自带”要显示的信息,它包括两个东西:

xposed版app_process的版本,包括程序自带(也就是XposedInstaller放在assets目录下的)和系统安装的。当然,只有该系统安装过Xposed版app_process才有必要检查它的版本。图6中由于没有装过,所以“激活”那一栏显示为“-”。
XposedBridge.jar:也包括程序自带和系统已安装两个jar包的版本。

检查版本主要是为了兼容性考虑。代码中的refreshVersions用于获取他们的版本号,代码如图9所示:



图9中:

getInstalledAppProcessVersion:读取/system/bin/app_process的版本号。
getLatestAppProcessVersion:读取自带app_process_sdkXX的版本号。
getJarInstalledVersion,读取/data/data/de.robv.android.xposed.installer/bin/ XposedBridge.jar版本号。对,你没看错,XposedBridge.jar是放在XposedInstaller自己的目录下的。
getJarLatestVersion:读取自带XposedBridge.jar的版本号。

想知道怎么获取版本系想你吗?来看图10:


对于app_process,直接读取文件内容,然后找到红框中的那一行,后面的58就是版本号。
对于XposedBrdige.jar,打开这个jar包,读取assets/VERSION的内容,里边就是存储了一个版本号信息。

太简单了,不惜得说。


注意XposedBridge.jar包安装版的位置,它在/data/data/de.robv.android.xposed.installer/bin/XposedBridge.jar里


3.1.2 安装xposed框架

InstallerFragment的install函数用于安装xposed框架相关的模块。这个函数一点也不复杂,不过还是给大家看看。如图11所示:



install函数没什么难度,但是我们要总结下xposed框架安装到底做了什么手脚:

将xposed版的app_process拷贝到/system/bin/,系统原来的app_process改名为app_process.orig
将XposedBridge.jar放到/data/data/de.robv.android.xposed.installer
删除/data/data/de.robv.android.xposed.installer/conf/disabled文件。如果有disabled文件则表明整个Xposed功能被禁止使用。

嗯嗯,也没什么太多可说的。


3.1.3 安装xposed插件

xposed插件,在xposed世界里我们说它是插件,但是放到Android世界里它就是一种特殊的APP。这种类型的APP由xposed框架识别并加载,然后hook到其他的App进程。


当然,这里既然提到进程,那么这些APP就必须要被先启动起来才是。


XposedInstaller的插件管控由ModulesFragment界面来处理。本节主要想介绍下XposedInstaller是怎么对待Xposed插件APP的。


来看代码,如图12所示:



我们重点来看看Xposed插件APP是怎么被load的,代码其实在ModuleUtil的reloadInstalledModules函数中。代码很简单如图13所示:



图13左下角已经告诉各位Xposed插件APP该是什么样的了,右下角是XposedDemo示例。


在AndroidManifest.xml里定义这些东西只是告诉Xposed自己是一个插件APP。但是作为一个挂钩插件,Xposed还需要知道这个APP里哪个类是用来挂钩的。这句话的意思是:


1 这个APP是一个插件APP。该APP包含很多功能。


2 这个APP包含的众多功能中,有一个功能是给目标进程挂钩。挂钩操作是Xposed框架来做的,所以它需要知道该APP中哪个类是继承了Xposed钩子接口。这样,Xposed框架找到插件APP之后会触发这个app的钩子接口进行挂钩。


要做到第二步就得在assets/下放一个名叫xposed_init文件,里边指明插件APP的挂钩类名。XposedDemo的


assets/xposed_init的内容就是:com.xposed.demo.MyXposedModule。当然,这个插件类必须实现Xposed的IXposedHookLoadPackage接口类。这个我们以后再讨论。


四、 Xposed框架介绍

Xposed框架分为xposed版app_process和XposedBridge.jar两部分。app_process就是zygote,我们先看看xposed版的zygote干了些什么。


4.1 Xposed版zygote

注意,本章只分析32位,dalvik版的xposed app_process,其入口main函数位于app_main.cpp里。


图14所示的代码展示了Xposed版zygote与众不同之处。



图14中,左上角的框是app_main的main函数,里边有两处不同之处:

AppRuntime:此处的AppRuntime类是xposed版的AppRuntime。它的与众不同之处从左下图的onVmCreated开始。当检查到isXposedLoaded为真是时,将调用xposed::onVmCreated函数。
xposed::onVmCreated函数位于右上框,它先判断当前虚拟机是ART还是dalvik,然后加载xposed一个特殊so,此处是/system/bin/libxposed_dalvik.so。注意,这里的xposed框架和XposedInstaller略有区别。因为XposedInstaller比较旧了(也就支持sdk 16的样子),还没有涉及到ART和dalvik的区别。在onVmCreate中,它将调用libxposed_dalvik.so中的xposedInitLib函数,然后再调用so中设置的onVmCreated函数。这个onVmCreated函数由xposedInitLib设置。
左上框中还有一个xposed:initialized函数。这个函数初始化了XposedShared类型的全局变量xposed,同时还把一个重要的jar包加到了CLASSPATH里。来看代码。如图15所示:


图9展示了initialize函数的内容,主要是最后一个把/system/bin/XposedBridge.jar(这个jar包的位置和我们在XposedInstaller那里看到得不同,原因前面解释过了)加到CLASSPATH比较重要。


注意,我们这里虽然对initialize介绍的内容很少,但实际上这个函数要真正看明白还是很需要技术实力的:


1 logcat:start:里边fork了logcat进程用来存储xposed自己的log


2 service:startAll:为了完美支持selinux,这里的处理更是很有技巧。selinux是一个完整的知识体系,想彻底掌握它的童鞋请参考我的三部曲文章《深入理解SELinux SEAndroid》


1&2其实很真实得反映出xposed的作者在Android、Linux上水平很高,经验很丰富。


最后,如果xposed框架启用成功,那么zygote的入口类将由以前的com.android.internal.os.ZygoteInit变成de.robv.android.xposed.XposedBridge


下面我们按照执行流程,把相关函数分析一遍:

AppRuntime的onVmCreated,它最终会导致libxposed_dalvik.so中的onVmCreated被调用。我们直接分析最后这个onVmCreated
然后AppRuntime里会调用de.robv.android.xposed.XposedBridge.main函数。4.2 onVmCreated

图16为代码:



onVmCreated比较简单了:

针对android/content/res/XResource&XTypedArray进行了一些处理,这是为将来资源替换时候做准备。以后我们碰到再说。
XposedBridge注册JNI函数

xposed官方说MIUI大量用了xposed的东西,并且不共享,以后碰到MIUI的问题他们不再支持。Don't know what to say....


4.3 XposdBridge.main函数

main函数代码如图17所示:



main函数里有三个重要函数:

initNative:好好学习下
initForZygote:好好学习下
loadModules:加载App插件4.3.1 initNative

initNative很重要,来看代码,如图18所示:



图18中,我们重点看一下callback_XposedBridge_initNativeregister_natives_XResources这两个函数。这两个函数比较简单,我们统一放到图19中:



不多说了,没什么难度。


4.3.2 initForZygote

从这个函数开始,xposed就开始给系统一些关键函数挂钩子了。我们看看它怎么玩儿的。代码如图20所示:



图20中我在eclipse里用了代码缩略显示的方法,可知一共有五个框,分别hook了一些关键内容。我们从上到下一次分析。先来分析下Xposed框架提供的挂钩函数findAndHookMethod


(1) findAndHookMethod介绍

findAndHookMethod用来对指定类的指定函数进行挂钩。这个函数很重要,开发插件APP时用得最多。来看它的代码,如图21所示:



findAndHookMethod代码Java层面的逻辑还是比较好理解的:

首先是通过class相关的函数找到指定的函数对象。这里的查找需要指定函数所在的类,函数名,函数参数信息等,属于精确(exact)查找。注意,findAndHookMethod函数的最后一个参数必须是XC_MethodHook类型,即钩子对象的数据类型。
然后就是XposedBridge.hookMethod

来看hookMethod,如图22所示:



hookMethod可知,一个目标函数可以挂多个钩子,这些钩子由一个集合来存储。然后我们将转到JNI层去看看hookMethodNative干了什么事情。这才是hook的核心。代码如图23所示:



hookMethodNative完成了真正的挂钩处理,其思想很简单:

先找到目标函数在native层对应的Method对象。
修改这个Method为native方法,并设置nativeFunchookedMethodCallback函数。
然后还要保存原函数的一些信息到insns域。

我们在《深入理解Android之dalvik》一文中介绍过,JVM调用java函数时候,发现这个函数为native的话,就调用它的nativeFunc。下面我们看看钩子函数的调用。


(2) 调用钩子函数

hook钩子函数后我们就要调用它。上一节我们发现xposed在挂钩子的时候会把原函数改造成native属性(即Dalvik会按native函数的方式调用它),对应的nativeFunc是hookedMethodCallback,其代码如图24所示:



注意喔,我们现在已经在处理被挂钩函数的调用了喔....从JNI会进入到java层的钩子函数dispatch总入口,及handleHookedMethod,这个函数比较复杂,我们一段一段来看它。



很简单。接着看第二段,如图26所示:



貌似也很简单喔...


现在来看原目标函数的调用,即invokeOriginalMethodNative。代码如图27所示:



同样很容易,不多说了。到此,我们已经看到了Xposed挂钩的所有过程。好像也没什么复杂的,只要对dalvik稍微属性点,应该是比较容易做的。


当然,本文只是给大家show了主要流程,真要自己动手做,我觉得难点在于参数传递等方面。anyway,了解了大体流程,后面的事情也好办,多尝试几次就好。


下面我们回过头来看initForZygote里加的几个钩子都干了什么。


(3) initForZygote钩子设置

图20的initForZygote代码示意中可知xposed对下面几个函数进行hook(此处先不讨论钩子函数干了什么)

ActivityThread.handleBindApplication:这个函数是ActivityManagerService内部调用ActivityThread.bindApplication间接触发的。该函数的详情可参考《深入理解Android卷2》第六章深入理解ActivityManagerService的“ApplicationThread的bindApplication分析”一节。handleBindApplication主要工作是初始化APP(APP由zygote进程fork而来,在hanldeBindApplication之前,这个APP进程和zygote没什么区别。只有调用完handleBindApplication之后,这个APP进程才是APP,比如该进程有了对应的名字,Aplication对象被创建等)。
com.android.server.ServerThread. initAndLoop函数:这个函数是给system_server用的,用于启动系统各种重要服务。
LoadedApk构造函数:通过hookAllConstructors来对LoadedApk各种构造函数进行挂钩。LoadedApk是APK文件在APP里的代表对象,里边有很多重要的信息。
android.app.ApplicationPackageManager. getResourcesForApplication:挂钩PackageManager的资源获取函数。
hookResources:对资源进行hook。这一块由于涉及到android APP对资源的管控,以后有机会我们再详细介绍。4.3.3 loadModules

main函数在initForZygote之后的下一个动作就是loadModules,这就是加载所有的插件APP。我们来看看这个函数,代码如图28所示:



我们来看下loadModules的处理:

先从XposedInstaller那获取当前已经安装(并启用)的插件APP列表,然后调用loadModule来加载这个APP。
loadModule从APP的assets/xposed_init文件里看看这个apk里声明了哪些钩子类。
loadModule校验这些钩子类是不是符合Xposed定义的钩子类类型,然后作对应处理。图29列出了Xposed支持的钩子类类型。


图30展示了hookLoadPackagehookInitPackageResource两个函数的内容,特别简单。



嗯嗯,就是把对应的钩子函数保存起来先。


好了,下面我们就来开始分析initForZygote里挂上的几个钩子分别有什么用。


4.3.4 handleBindApplication钩子

initForZygote为hanldeBindApplication设置了前处理钩子,代码如图31所示:



前面说过,在APP生命周期内,handleBindApplication是APP刚准备好相关信息的一个重要点,在这个点去进行挂钩处理简直是最好不过了。当然,此处的挂钩处理也就是准备好这个APP的相关信息然后调用所有的IXposedHookLoadPackage类型的钩子。


注意,除了handleBindApplication之外,由于一个APP进程事实上可以加载多个APK(比如那些申明同样的uid和运行在同一进程的APP),在LoadedApk的构造函数中也做了类似的处理


IXposedHookLoadPackage钩子一般会干些什么呢?图31对XposedInstaller的处理就很明显了。一般而言,这种钩子会对目标APP中感兴趣的函数进行挂钩(调用findAndHookMethod),比如XposedInstaller对getActiveXposedVersion进行了挂钩,用于返回系统里正在使用的Xposed框架版本。


我们应该在钩子函数里干些什么?这是一个重要问题。我也不废话了,直接上XposedDemo的源码,如图32所示:



图32是我在xposed-learning项目中提供的XposedDemo示例,可知:

Xposed框架对handleBindApplication进行hook后,当有APP启动的时候,该框架就会调用所有IXposedHookLoadPackage类型的钩子。
这种钩子一定要区分当前被hook的APP是不是自己想要Hook的APP。如果不是,请直接return。如果是自己的目标APP,则进一步通过findAndHookMethod进行挂钩。

简单点说,我们在IXposedHookLoadPackage的handleLoadPackage中把该挂的钩子都挂上就好。


4.3.5 initAndLoop钩子

initAndLoop是system_server进程的关键函数,在这个函数里Android Framework的绝大部分Service都将被创建。真是艺高人胆大,这个进程居然都提供了挂钩处理。其代码如图33所示:



代码倒是很简单,无非是针对system_server进行hook。插件函数如果想区分被hook的进程是否为system_server的话,只需要判断packageName是否为"android"即可。


再次强调,system_server是Android Java层Framework的核心,要hook它需要万分小心,否则或导致手机系统出现会各种不稳定,崩溃,重启等情况。


下面我们介绍下Xposed框架对资源是怎么Hook的。


4.4 对资源的Hook

前面章节介绍了Xposed框架如何对代码调用逻辑进行hook。在Android APP中,除了代码逻辑外,Xposed还支持对资源进行Hook。对资源Hook的原理其实和对代码调用进行Hook的原理类似。这里我们简单介绍下Xposed框架如何对资源进行Hook。


在Android APP中,资源有三个重要类:

ResourcesManager:一个APP进程有一个ResourcesManager。一个ResourcesManager可以管理多个Resouces。
Resources:Resources是一个APK中资源的代表,注意,它不是指单独的一种类型的资源(比如字符串,图片等),它是一个APK文件中资源文件的代表。Resources对象有一个AssetManagerAssetManager能操作APK文件(其实就是一个压缩包)assets以及res目录里的内容。
Resources通过ResourcesKey将自己保存到ResourceManager中的一个ArrayMap里。
对于资源挂钩来说,Xposed框架及插件APP做如下几件重要的事情:
handleBindApplication类似,在APP进程某个时间点的时候(猜测:初始化资源相关模块)进行Hook,然后调用IXposedHookInitPackageResources类型的钩子。
IXposedHookInitPackageResources类型的钩子通过Xposed提供的XResources类的setReplacement对原有的资源进行替换。在Xposed框架中,XResources是用于替代Resources的。
App运行时候,Xposed框架截获相关的资源获取函数(比如Context的getString),先看看是否被replace了,如果是,则返回被replace的结果。

就这么简单。我们一步一步来看。


注意,XposedDemo并没有hook资源,请感兴趣的童鞋们自行加上该功能进行测试。


4.4.1 hookResource

hookResource对ResourceManager等进行了挂钩处理。来看代码,如图34所示:



hookResources主要是对ResourcesManager的getTopLevelResources进行了Hook。APP中原来使用的是Resources代表资源,Hook之后,Xposed用XResources代替了Resources。图35展示了XResources的派生关系。



接着看hookResources第二段代码,如图36所示:



第二段代码中,Xposed资源Hook框架调用了资源hook类型的钩子。同样,我们需要关注在这种类型的钩子里插件APP要干得事情,那就是:

通过XResources的setReplacement函数将目标资源的id和内容进行替换。

上面替换的还是APP自己的资源,除此之外,Xposed还能替换系统资源(即framework-res.apk里声明的资源),这部分代码也在hookResources里,来看图37:



图37中,Xposed将Resources里代表系统资源的mSystem对象也进行了替换。不过这里没有独立调用回调。没关系,因为在第二部分的回调中,插件APP通过XResourcessetSystemWideReplacement可以对系统资源进行替换。


注意,hookResources之后,APP里调用的Resources相关的函数就全部转到XResources来处理了。比如获取字符串的getString函数,其最终会调用到XResources的getText函数,代码如图38所示:



到此,我们对Xposed框架如何hook资源进行了介绍。不过,layout资源的hook我这里并没有介绍,请童鞋们阅读XResources的getLayout函数和init函数。


五、 总结

到此Xposed 32位dalvik版框架基本介绍完了。这一趟绝对不是本篇这20多页文章这么轻松的事情。正如我在《深入理解Android之Dalvik》一文写得那样,我是在研究xposed的时候,发现必须要搞清楚dalvik,所以才先写了dalvik的文章,然后才能走到今天这一步。


Xposed是一个成熟框架,高度体现了开发者在Java虚拟机这块有着非常深厚的知识积累。同时,如果加上selinux的话,那开发者对linux系统也是相当相当熟悉。另外,貌似开发者是用业余时间搞出来的,这在当下上班时间强制为996的码农而言几乎是不可能的事情。


再次向开发者致敬,也同时呼吁基于xposed框架的派生框架开发者遵守相关开源协议。


【CNUTCon全球容器技术大会】微服务、持续集成、容器云、大数据、电商、传统行业、创业公司等12个专题,Docker、Kubernetes、Netflix、Mesos、CoreOS、阿里巴巴、京东等公司的核心技术负责人现场独家揭秘,容器化和微服务化,从这里开始,8折报名中,详情请点击。
领域
语言 & 开发
专栏
虚拟机
深入理解Android
JVM
移动
运行时
Java
操作系统
Android

相关内容


深入理解Android(二):Java虚拟机Dalvik
深入理解Android(一):Gradle详解
Android Studio 2.0新特性:即时运行和云测试实验室
从案例学RxAndroid开发(下)
OpenJDK将对Android开发产生怎样的影响?

相关厂商内容

通过探针技术,实现Java应用程序自我防护
新Java,新未来
你离成为一位合格的技术领导者还有多远?
你了解技术领导与技术管理的差别吗?

相关赞助商




QCon全球软件开发大会上海站,2016年10月20日-22日,上海宝华万豪酒店,精彩内容抢先看!



您好,朋友! 您需要
注册一个InfoQ账号 或者
登录 才能进行评论。在您完成注册后还需要进行一些设置。
获得来自InfoQ的更多体验。 告诉我们您的想法 社区评论
Watch Thread关闭
by

发布于
查看
回复
回到顶部 关闭 关闭 关闭



相关内容


Android开发周报:GMTC PPT 下载、微信热补丁实践2016年6月29日
Android开发周报:Android份额继续增长、进程知识详细解读2016年6月22日
Android开发周报:Google击败Oracle,React Native编写跨平台App2016年6月15日
Google击败Oracle,Android可以正常使用Java API2016年6月12日
Android开发周报:中文Android7.0体验不佳、深入浅出Retrofit2016年6月12日
Android VPN实现原理介绍2016年6月20日
从Android到Swift iOS开发:语言与框架对比2016年5月23日
实战kotlin@android(三):扩展变量与其它技巧 2016年5月20日
蘑菇街支付金融Android单元测试实践2016年5月20日
实战Kotlin@Android(一):项目配置和语言转换2016年4月30日
Android官方MVP架构示例项目解析2016年4月29日


赞助商内容
活动大本营全新版本正式上线!
GTLC全球技术领导力峰会8折优惠中!


相关内容


从案例学RxAndroid开发(下)2016年4月8日
微信Android客户端后台保活经验分享2016年4月8日
从案例学RxAndroid开发(上)2016年3月28日
使用Clean Architecture模式开发Android应用的详细教程2016年3月17日
Android内存优化2016年2月4日
Android应用程序UI硬件加速渲染技术2016年1月22日
深入JVM彻底剖析ygc越来越慢的原因(下)2016年5月12日
深入JVM彻底剖析ygc越来越慢的原因(上)2016年5月5日
通过使用Byte Buddy,便捷地创建Java Agent2016年2月22日
sun.misc.Unsafe的后启示录2016年1月26日
Eclipse最新版 Neon已发布2016年6月28日

赞助商内容
GTLC全球技术领导力峰会8折优惠中!
活动大本营全新版本正式上线!


相关内容


Gil Tene:了解硬件事务内存2016年6月28日
测试框架的利好和繁荣:Java单元测试框架之争2016年6月28日
新JSON绑定库JSON-B发布公开预览版2016年6月24日
借Java EE守护者联盟之力拯救Java EE2016年6月21日
对Eclipse OMR(用于创建语言运行时环境的工具集)架构师Mark Stoodley的访谈2016年6月20日
Java 9将会从默认类路径中去除CORBA2016年6月15日
Gluon公布完整的Java 9 Mobile创新举措2016年6月13日
Kotlin 1.1路线图2016年6月13日
Log4j 2.6免垃圾收集2016年6月12日
Angular 2与TypeScript概览2016年6月23日
找出微服务性能方面常见的反模式2016年6月22日




赞助商链接 InfoQ每周精要

通过个性化定制的新闻邮件、RSS Feeds和InfoQ业界邮件通知,保持您对感兴趣的社区内容的时刻关注。







来自为知笔记(Wiz)

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台