本篇记载我搭建Xposed开发环境到第一个Xposed插件的过程。
Xposed原理概述:
Android系统中,一个App的运行要借助于虚拟机进程,因为我们都知道Android系统的底层其实是由C++编写的Linux,那么这样的系统如何运行我们使用Java编写的上层App呢?很简单,为每一个App提供一个虚拟机进程,App在虚拟机中运行就没有问题了。Android中有一个特殊的进程负责创建这些虚拟机进程,它就是Zygote进程,Zygote进程在创建时。每一次创建一个虚拟机进程都是从Zygote进程fork出来,学过操作系统的同学都知道所谓的fork创建就是去拷贝一份进程的备份,因此每一个虚拟机进程都会享有这个Zygote进程的所有资源,比如运行时库,因此只要能修改Zygote进程,理论上就能控制所有其他应用进程,Xposed正是通过修改Zygote进程来完成劫持的。
注:这里的虚拟机进程指的是运行了一个虚拟机实例的进程,而Java程序就在这个虚拟机实例中运行。我简单的理一下这个关系:Zygote进程->拷贝一份应用进程->拥有一个虚拟机实例->运行Java程序。通过这样一种方式,Android系统只需要对虚拟机初始化一次,以后每一次创建虚拟机只用拷贝就完成了,且对于静态库,所有虚拟机与Zygote进程共享,这也可以节省内存。
Xposed的最终效果是实现对方法的劫持,也就是我们可以对任何一个方法的内容进行重写。
1.在手机上安装Xposed。
安装Xposed是个非常麻烦的事情,我的测试机是红米2 miUI7稳定版,我本来想在这台测试机上安装Xposed,但是这台手机没有root也没有合适的rom,如果要装在这台手机上可能要浪费大量的时间去刷机,最后我选择放弃在实机上安装,转而在Genymotion下的虚拟机上安装。
我虚拟机配置:
Google Nexus 6 - 5.0.0 API 21
Genymotion上的虚拟机自带root授权管理,我在root权限下安装。
Xposed有两个部分:
(1)XposedInstall—一个apk应用,这个东西是负责与用户交互和管理Xposed插件的Android应用,这个东西安装起来是很容易的,使用Genymotion只需要把apk拖入虚拟机窗口就能自行识别。
(2)Xposed SDK—实现root的底层库,这个东西是一个zip文件,需要以Recovery的方式刷上手机,且官方对Recovery的工具有明确的要求,不能使用源生的工具,也就是说你得先刷上要求的Recovery工具,非常的麻烦。幸运的是Genymotion下有很简单的工具在虚拟机环境下帮助我们快速刷机,GenyFlash,使用这个工具可以直接像安装apk一样刷机,很方便的就能装上SDK。
2.在Mac下配置Xposed插件开发环境
我起初以为开发Xposed的插件会非常的麻烦,因为它可能不是标准的Android工程,不能通过Android Studio这样IDE的编译。后来试了一下,其实很简单,开发Xposed插件就和一般的App没有什么两样,它只要求你mainfest和一些文件里多加少许识别的标记。
Xposed插件本身就是一个Android App,我们之前安装的XposedInstall就专门管理这批App,在编写插件的时候可以把App本身的启动icon设置为不显示,这样就只能在XposedInstall里找到它。
Xposed的开发和普通的App是一样的,因此我们只需要添加Xposed插件需要的依赖就行了。
我在Mac下的Android Studio中编写Xposed插件,因此我使用Gradle添加依赖如下:
app/build.gradle
provided 'de.robv.android.xposed:api:82'
这个东西好像是会引用本机上安装的sdk,但是我现在也搞不太清楚,目前先记住它是我们项目需要的依赖就够了。
3.Xposed Hello World
下面开始第一个Xposed插件的编写:
为了更直观的看到Xposed的作用,我们跳过官方文档提供的最简单的simple,直接编写第一个Hook插件。
首先创建一个简单的工程,它将被Xposed劫持并修改。
因为这个工程的内容很简单,我只贴Acitivity里面的代码:
1 | package com.zuliangwang.test; |
一个TextView和一个Button,当点击Button,TextView的内容将被修改。
我们的目的就是劫持这个TextView的setText方法,修改传入的参数,最后的text将不是“GG”
接下来创建一个Xposed插件工程。
首先修改AndroidMainfest的内容:
1 | <?xml version="1.0" encoding="utf-8"?> |
这个玩意是给XposedInstall提供的本插件的描述。
接下来在main文件夹下创建assets文件夹,在里面创建一个简单的文本文件xposed_init,这个名字是有要求的。
1 | com.zuliangwang.firstxposed.DIAO |
这个文件里只有一行代码,是一个类的名字,它告诉xposed我们这个插件的执行入口。
接下来就在这个类里编写具体的逻辑:
1 | package com.zuliangwang.firstxposed; |
通过Xposed提供的方法,我们可以修改另一个Android App的方法的参数,现在编译这个工程,你会在XposedInstall里看到这个新的插件。点击运行第一个Test工程,你可以看到结果如下:
可以看到,这个App的逻辑被我们写的插件给劫持了!
第一个插件到此完成。
XposedInstall和XposedSdk 传送门
GenyFlash 传送门
XposedBridge官方文档 传送门