Xpoded模块开发教程

当然,你可以去学习如何创建一个Xposed模块。所以你可以阅读这篇教程(官方教程)去学习怎样解决这个问题。这不仅仅讲解如何新建模块、如何编写模块,我们要往更深处思考,为什么按照这些步骤,为什么要新建这个类。如果你是“TL博士”那样的人,那么可以直接阅读"Making the project an Xposed module" 这一章节。如果你想看完整个教程那么你需要很好的理解能力。你将会花费时间去阅读这篇文章,因为你不能但靠自己解决任何的问题。

一、修正通告

你可以在Github中找到重新创建红色时钟的例子,它包括状态栏时钟的颜色改为红色和添加一个笑脸,我选择这个例子,因为它是一个相当小,但很容易看到变化。此外,它使用了一些由框架提供的基本方法。

二、Xposed是如何工作的

在你修改之前,你应该思考一下Xposed是如何工作的(如果你觉得太无聊可以跳过这一节)。方法如下:

有个进程叫做“Zygote ”。这是Android运行环境的的核心。每一个应用程序启动都是通过它fork出来的。当手机被启动就会执行/init.rc这个脚本,这个进程会启动/system/bin/app_process ,然后他会调加载所需的类并调用初始化函数。

现在说说Xposed什么时候开始启动。当您安装了Xposed,它会把修改的app_process可执行文件复制到/system/bin中。这个修改过的启动进程增加了一个额外的jar包到classpath路径,并在某些地方调用那里的方法。例如,在虚拟机刚刚创建后,在Zygote 的main方法调用后。我们的jar包也可以Zygote里面工作。

这个jar包位于:/data/data/de.robv.android.xposed.installer/bin/XposedBridge.jar和它的源代码可以在这里找到(here)。综观类XposedBridge,你可以看到的main 方法。这就是我上面写的,这个类会在进程启动之前被调用。在那时候执行一些初始化和模块的加载(我会在后面讲解模块的加载)。

三、Method hooking/replacing

Xposed真正的能力在于可以hook函数的调用。当您修改完反编译后的APK,你可以直接插入命令或者修改命令。但是您将需要重新编译/签名APK,并且重新安装这个安装包。你可以用Xposed的hooks,你不用修改内部函数的任何代码(这无法清晰地定义什么叫“没有修改”这个词语)。相反,你可以注入java里最小的单元(每一句代码)到函数的前面和后面,这可以清晰地解决问题。

XposedBridge有一个私有的本地方法叫hookMethodNative。此方法同样的会在扩展的app_process进程中应用。它会将方法类型改变为“native ”并且将这方法的实现替换为它自己本地的泛型方法。这意味着任何时候调用这个被hook的方法,方法调用者并不知道已经被native 方法给代替了java层的方法。在该方法中,在XposedBridge的方法handleHookedMethod会被调用,用来传递需要的参数和自身的引用。并且这个方法负责调用给这个函数注册过的回调方法。他可以改变传进来的参数,可以更改实例变量和静态变量、可以调用其他方法、处理一下返回值,或者跳过任何你想跳过的代码。这是非常灵活的。

好了,理论讲解完了。现在,让我们创建一个模块!

四、创建项目

模块是正常的应用程序,只需用一些特殊的元数据和文件。因此,首先创建一个新的Android项目。我假设你之前已经做到了这一点。如果不是,官方文档非常详细。当被问及对于SDK中,我选择了4.0.3(API15)。我建议你试试这个,因为已经做过测试了。你不需要创建一个activity ,因为修改没有任何用户界面。回答完这个问题之后,你应该有一个空白的项目。

五、Making the project an Xposed module

现在我们开始讲解如何加载Xposed 模块 。需要按以下几个步骤来进行的。

1.AndroidManifest.xml

Xposed Installer根据模块列表查找模块程序的详细信息是通过meta-data这个标签的。您可以这样创建它:AndroidManifest.xml => Application => Application Nodes (在底部) => Add => Meta Data。这个名字应该是xposedmodule和值为true。让资源为空。然后重复相同的操作填写xposedminversion(见下文)和xposeddescription(你的模块的一个非常简短的描述)。 XML源代码现在看起来像这样:

2.XposedBridgeApi.jar

接下来,让项目认识XposedBridge API 。你可以从这里下载XposedBridgeApi-<version>.jar 。把它复制到子文件夹名为lib目录下。然后在其上单击右键,选择Build Path => Add to Build Path 。你需要将版本名插入到xposedminversion的声明清单中。

可以选择库引用的方式。但是确保你的API类被正确地编译到APK文件中 ,否则你会得到一个IllegalAccessError 。通过引用libs 文件(有“s”),通过Eclipse的简单设置可以不用把XposedBridgeApi-<version>.jar 包含进去。

3.模块的实现

现在,您可以创建一个类的模块。我的被命名为“Tutorial ”,并在包de.robv.android.xposed.mods.tutorial里面:

用于第一步骤中,我们将只做一些记录以显示被加载的模块。一个模块可以有几个入口点。选择哪一个取决于您要修改的内容。您可以在Android系统启动时、当一个app将要被加载时、一个app的资源将要被初始化时,通过Xposed调用你模块中的一个函数。

本教程往下一点 ,您将学习必要的更改需要在一个特定的应用程序中完成,所以让我们一起去看看“当一个新的应用程序被载入的时候”的入口点。所有入口点都标有IXposedMod的子接口。在这种情况下,你需要实现IXposedHookLoadPackage这个函数。它实际上只是一个方法加上一个参数,它提供了有关环境的实现模块的更多信息。在我们的例子中,我们记录的加载应用程序的名称:

这个log方法将日志输出到标准logcat窗口中和/data/data/de.robv.android.xposed.installer/log/debug.log文件中。(通过它很容易了解Xposed Installer )

4.assets/xposed_init

现在需要关心的事情是仍然丢失了XposedBridge 的一些类包含的入口点的追踪。这是通过一个名为xposed_init的文件,在assets  文件夹中用它的名字创建一个新的文本文件。在这个文件中,每一行包含一个完全限定的类名,就像这样,这里的是:de.robv.android.xposed.mods.tutorial.Tutorial

六、Trying it out

保存文件。然后运行你的项目为Android应用程序。因为这是你第一次安装它,在使用它之前您需要启用它。打开Xposed安装的应用程序,并确保你已经安装了框架。然后去了“模块”选项卡。你应该找到你的应用程序在里面。选中该复选框来启用它。然后重新启动。你不会看到有任何的变化,但如果你检查日志,你应该看到的东西是这样的:

瞧!它这工作了。现在你有一个Xposed模块。它仅仅只有写log的作用。。。

七、探索你的目标,找到一个方法来修改它

好了,现在开始这一话题,可以是非常不同,这取决于你想要做什么。如果你以前有修改过的APK,你可能知道我在说什么。在一般情况下,你首先需要获得有关目标的实现的一些细节。在本教程中,目标是在状态栏的那个时钟。它有助于知道状态栏和一部分SystemUI的细节。因此,让我们开始搜索。

可能性之一:反编译。这将给你准确的实现 ,但是它是难以阅读和理解的,因为你得到smali格式的代码。可能性二:获取AOSP源( here )并且浏览他。但这官方ROM可能与你的不一样,但在这种情况下,它是一个类似甚至相同的实现。第一,我想看看AOSP,看看是否是一样的。如果我需要更多的细节,看看实际的反编译代码。

你可以寻找与“时钟”类名称或包含该字符串的类。下一步就是,寻找他所使用的资源和布局。如果您下载了官方AOSP的代码,就可以开始在这里开始寻找:frameworks/base/packages/SystemUI 。你会发现不少地方出现“时钟”。这是正常的,的确会有不同的方式来实现修改。请记住,你仅仅可以hook方法 。所以,你必须要找到一个可以在他之前、之后、或全部替换可以插入一些代码的地方。你应该hook 住尽可能具体的方法,而不是那些会被调用上千次的方法,去避免性能问题和意想不到的副作用。

在这种情况下,您可能会发现这个layout布局res/layout/status_bar.xml  包含了一个自定义视图类:com.android.systemui.statusbar.policy.Clock。多个想法可能会现在你的头脑中。文字颜色的定义是通过textAppearance属性,所以最简单的方法就是改变它,将会改变外观的定义 。然而,这可能有效也可能无效(因为它可能存在于更深的native  代码中)。更换布局状态栏将是可能的,但是你们只可以做最小的变化去更改他,相反,看看这个类。有一个叫updateClock方法,它看上去会被每分钟调用去更新时间

看起来完美的修改,因为它是这似乎是唯一设置文本时钟的非常具体的方法。假如我们改变了这个clock的颜色或者字体,那么任何调用这个方法的都会受此影响。就达成我们的需求了,我们立刻行动.

(单独的文本颜色,这里有一种更好的方式.看到“修改布局”的例子在 "Replacing resources".)

八、使用反射来查找和hook一个方法

什么是我们已经知道的?我们找到一个方法:updateClock 在com.android.systemui.statusbar.policy.Clock,我们要拦截它。我们发现这个类是在SystemUI sources 里面,所以它只能对SystemUI的进程有效。修改一些其他的归属于框架的类是会任何地方都有效的。如果我们试图获得任何信息和直接引用此类在handleLoadPackage 方法中,这会失败的,因为它们在不同的进程中。所以,当一个指定的包将被加载时,让我们来实现一个执行特定代码的条件。

使用参数,我们可以很容易地检查,我们是否选中正确的包。一旦我们证实,我们可以从包中获得这个类通过也是从这个变量引用的类加载器。现在我们来看看在com.android.systemui.statusbar.policy.Clock类及其updateClock方法,可以告诉XposedBridge把它hook了:

findAndHookMethod是 helper 类的一个方法。请注意,它是静态导入的,如果你配置了它描述的链接页面就会自动添加 。此方法通过ClassLoader  在ClassLoader  包中查找Clock类 。然后,它会在里面寻找updateClock方法。如果这种方法有任何参数,那你就必须列出这些参数的类型。不同的情况不一样的处理,但我们的方法没有任何参数,可以跳过这个假设。作为最后一个参数,你需要提供XC_MethodHook类的实现。对于较小的改动,就可以使用一个匿名类。如果你有太多的代码,最好创建一个普通的类,只在这里创建实例。随后,helper 将尽一切方法hook住以上的函数。

你可以重写XC_MethodHook的两个方法。您可以同时覆盖,甚至不做操作,但后者是完全没有意义的。这两个方法是beforeHookedMethod和afterHookedMethod。这不是太难猜测,这两个方法会在原始的方法的之前和之后执行。您可以使用beforeHookedMethod 方法来评价/篡改方法调用的参数(通过param.args) ,甚至阻止调用原来的方法(发送自己的结果)。afterHookedMethod 方法可以用来做基于原始方法的结果的事情。您还可以用它来操纵结果 。当然,你可以添加自己的代码,它将会准确地在原始方法的前或后执行。

(如果你想完全取代方法,看看子类XC_MethodReplacement相反,你只需要覆盖replaceHookedMethod )

XposedBridge保留着一个记录了每个已经hook了的函数的注册回调函数 的列表。那些具有最高优先级(如hookMethod定义)会首先调用。原始方法始终是优先级最低的。所以,假如你hook了一个函数并注册了回调A(PRIO高点)和B(PRIO默认值),那么每当hook的方法被调用,控制流将是这样的:A.before - > B.before - >原始的方法 - > B.after - > A.after。因此,A修改了的参数,B是可以看到的,这样可以在传递给原始方法之前多步地改变它。原方法的结果首先会被B处理,但是这个原始方法最终返回的结果是由A来决定的。

九、最后一个步骤:执行自己的代码在方法调用之前/之后

好了,你现在有一个每次updateClock  调用时,都会被调用的方法,而且可以精确到原始方法的前后(你已经在SystemUI  的进程里面了)。现在,让我们来修改一些东西。

首先要检查:我们有没有得到具体的时钟对象?是的,我们有,它在param.thisObject参数里。因此,如果该方法被myClock.updateClock()调用,然后param.thisObject将会使myClock这个对象。

下一步:我们可以做什么用的时钟?这个Clock  类是不可以利用的,你可以不转换param.thisObject变成类(甚至不要去尝试)。然而,它继承自TextView的。所以,你可以使用像的setText,gettext和setTextColor的方法,一旦你已经把Clock引用映射成TextView。这些改变应该在原始方法调用后去设置新的时间。由于在方法调用前没有事做,我们就不考虑 beforeHookedMethod。调用 (empty) "super" 方法是没有必要的。所以不要重写这方法。

这是完整的源代码 :

十、对结果满意

现在安装/重新启动您的应用程序。正如你在运行之前已经在XposedInstaller  启用了它,你就不需要再来一次了,重新启动就足够了。不过,如果你想使用它停用这个红色时钟的例子。两者都使用缺省的优先级给他们的updateClock处理程序,那么你不知道哪一个会胜出(它实际上取决于处理方法的字符串表示形式,但并不依赖于此)。

十一、结论

我知道,这个教程很长。但我希望你现在不仅可以实现一个绿色的时钟,还可以实现和这个完全不同的东西。找到好的方法来hook是一个经验上的问题,所以开始的东西比较容易。尝试刚开始就多使用日志功能去确保被调用的是预期的事件。现在:玩得开心!

翻译:https://github.com/rovo89/XposedBridge/wiki/Development-tutorial

转自:http://blog.csdn.net/comeonhacker/article/details/38826367

Xpoded模块开发教程相关推荐

  1. (译)Xposed模块开发教程

    (译)Xposed模块开发教程 原文地址.这是开发者所写的,可以说是官方开发指南.文章讲述了Xposed的原理,以及怎么开发Xposed框架的模块.头一次翻译技术文档,有错误的话请多包涵. 好了,你想 ...

  2. Xposed模块开发教程整理

    Xposed模块开发教程 Xposed官网 Xposed官方文档 Xposed框架介绍 了解和使用Android神器Xposed框架 Xposed模块开发 Xposed模块开发入门 在手机状态栏增加显 ...

  3. 物联网国赛LORA模块开发教程(通用库)—Keil添加注释的快捷键

    LORA模块开发教程目录 物联网国赛LORA模块开发教程-开发环境配置 物联网国赛LORA模块开发教程-Keil添加注释的快捷键 物联网国赛LORA模块开发教程-点亮第一颗LED灯 物联网国赛LORA ...

  4. Xposed模块开发教程(一) 了解并使用Xposed

    系列教程: Xposed模块开发教程(一) 了解并使用Xposed http://blog.csdn.net/u014418171/article/details/52910768 Xposed模块开 ...

  5. Xposed模块开发教程,该篇讲解通俗易懂,所以转发

    原文章地址:http://vbill.github.io/2015/02/10/xposed-1/ 文章讲述了Xposed的原理,以及怎么开发Xposed框架的模块.头一次翻译技术文档,有错误的话请多 ...

  6. Xposed模块开发教程

    转:http://vbill.github.io/2015/02/10/xposed-1/ 原文地址.这是开发者所写的,可以说是官方开发指南.文章讲述了Xposed的原理,以及怎么开发Xposed框架 ...

  7. 多多云手机【语音引流】创新吸粉模式 -- 语音播放功能模块开发教程

    多多云手机[语音引流]创新吸粉模式,接口完全免费开放给开发者,可用于第三方APP语音引流软件开发,互联网引流等等,例如微商语音吸粉.游戏语音推广.应用喊话推广,替代传统枯燥的文字引流方法,自动化的操作 ...

  8. 来自damon的zencart二次开发教程-2.2登录模块分析

    我们在制作zencart的模板时,经常会遇到需要将zencart的登陆页面与注册账户页面分离的情况(在 默认情况下,点击"Login"按钮会进入登陆页面与注册账号页面,登录zenc ...

  9. phpcmsV9视频模块插件 - 手把手开发教程

    phpcmsV9官方的视频模块,一点也不完整不系统. 官方给出的文档说明.文件下载.等等都太缺了. 这里给出个人开发过程后,总结出的经验精华,请及时汲取. 1. 准备工作 安装完整地 wampserv ...

最新文章

  1. html的学习小结(3):HTML 4.0 事件属性
  2. c++ :MFC 如何遍历窗口同类型控件ID
  3. WebSocket FlashSocket
  4. Win32程序中使用Combo box控件
  5. JVM对象内存分配详细过程(栈上分配->TLAB->老年代->Eden区)
  6. mahout0.7 示例运行纪实
  7. php array 删除末尾,PHP array_pop():删除数组末尾的元素
  8. 老也有错?科技行业对大龄程序员的歧视
  9. 使用Nativefier将web页面打包为桌面应用
  10. Julia的Dates库是重要和必要的补充!
  11. 百款 TWS蓝牙耳机 蓝牙天线拆机分析与仿真
  12. SQL连接查询语句(内、外、交叉和合并查询)
  13. JS match() 方法 使用
  14. 1125 斐波那契数列
  15. 数据库复习-3.常用的概念模型
  16. 计算机命令无法到达打印机,Win7打印机发送打印命令后不打印自动消失怎么办...
  17. 一种基于Android、iOS系统的移动端车牌识别方法,实现手机拍照识别车牌
  18. httpsproxy2http(一个开源的反向代理服务器)
  19. Linux下搭建TPshop商城(阿里云)
  20. 目录:吴恩达机器学习课后作业

热门文章

  1. 蚂蚁金服面试经历(内含大量干货)
  2. VUE使用docxtemplater导出word(带图片)
  3. Golang zip流式解析器
  4. html六边形空心,六边形空心预制块模具基本知识
  5. HDMI2.1定义以及物理转换Bypass芯片详解
  6. 什么是创意啊?这才是创意
  7. 小程序源码:独家全新娱乐性超高的喝酒神器
  8. 我国影视行业的痛点——影视链的目标
  9. .net framework 官方下载地址
  10. 《强化学习与最优控制》学习笔记(一):确定性动态规划和随机性动态规划