本帖最后由 MingKing 于 2018-1-18 14:59 编辑
【Xposed模块开发入门】真·第一课
之前按网上的教程来,遇到各种问题,所幸问题一一得到解决,下面整理一篇详细的入门教程,细节地方皆详细说明(如有不懂的地方,评论区问我,以便我稍加修改)
本次在android studio上进行讲解,因为感觉现在用这个的人比较多,问题也多
【开始前的准备】
1.掌握基本的android开发知识,搭建好android开发环境(环境怎么搭啥的也有一堆蛋疼问题,这里就不说了,改天我仔细探索整理一下)
2.有xposed框架作为环境(真机或者模拟器,我下面直接真机调试)
3.Xposed框架API(网上各种坑爹教程附各种不知啥时候会挂掉,资源老,老子可能要账号才能下载的坑爹链接,也不给个官网地址,所以)
由于它是不断更新的,请大家直接到官网页面进行下载:https://jcenter.bintray.com/de/robv/android/xposed/api/
下载如下两个文件:api-82-sources.jar
api-82.jar
下方括号中是使用eclipse要注意的,android studio不用管
(在Eclipse中,你必须从这里手动下载jar:https : //jcenter.bintray.com/de/robv/android/xposed/api/我建议将这些文件放到一个名为的子目录中lib。不要把它们放到libs子目录中!Jar文件libs将自动使Eclipse将API类编译到您的APK中,但它们只能被引用(参见上文)。现在右键单击该api-XX.jar文件并选择Build Path -> Add to Build Path。您还可以添加一个源api-XX-sources.jar文件(在文件中),以便在Eclipse中直接查看文档。)(懒得打了,直接官网copy)
【环境的搭建】
就是将Xposed框架API引用到项目中,这样就能进行Xposed模块的开发了
1.使用android studio构建一个项目
(小提示,注意设置为project查看,这样项目结构看得更加清楚)
下方修改处皆在上图中用箭头指出(build.gradle是app文件夹中的,注意不要搞错)
1.将下载下来的两个文件复制到文件夹libs中
2.在build.gradle中将添加图中两句
[Java] 纯文本查看 复制代码 provided 'de.robv.android.xposed:api:82'
provided 'de.robv.android.xposed:api:82:sources'
有人说
provided 'de.robv.android.xposed:api:82:sources'
这句不是必要的,确实,它里面存放了javadoc,方便Ctrl+Q快速查阅,反正也是一堆英文看着晕,不写这句也行
作用:将libs中的Xposed框架API引用到项目中(构建依赖)
可能会遇到的问题:
1.这两句报错!?
provided 'de.robv.android.xposed:api:82'
provided 'de.robv.android.xposed:api:82:sources'
异常:
[Asm] 纯文本查看 复制代码 Error:A problem occurred configuring project ':app'.
> Could not resolve all dependencies for configuration ':app:_debugApkCopy'.
> Could not resolve com.squareup.okhttp3:okhttp:3.5.0.
Required by:
retrofit-rxjava-okhttp:app:unspecified > com.squareup.retrofit2:retrofit:2.1.0
> No cached version of com.squareup.okhttp3:okhttp:3.5.0 available for offline mode.
这个问题是因为之前我android环境没有搭建好,改动了一些配置导致,大家通常应该不会遇到这个问题
解决方法:
Settings-Build.Execution,Deployment-Gradle–取消勾选的Offline Work,重新编译即可
2.使用compile fileTree(dir: 'libs', include: ['*.jar'])导致出错
一定要使用 provided ,不要使用 compile! compile 会将整个 API 类 编译进你的apk中而导致出问题。provided 则只是提供了API 类的引用,
API 类真正的实现则在 Xposed FramWork中。 在大多数情况下,repositories已经存在,并且已经有一些依赖,所以只需要将provided 这一
行添加到存在的dependcies模块中即可。
(之前我使用provided失败,就转而使用compile,结果还是失败,真的无语了,大家要注意)
3.在AndroidManifest.xml将自己标识为一个Xposed模块,语句添加在如下位置
[XML] 纯文本查看 复制代码 <meta-data
android:name="xposedmodule"
android:value="true" />
<meta-data
android:name="xposeddescription"
android:value="我是一个Xposed例程" />
<meta-data
android:name="xposedminversion"
android:value="53" />
作用:
xposedmodule:value为true,表示自己是一个xposed模块
xposeddescription:value中的文字就是对模块的描述,这些能够在手机上的Xposed框架中看到,举个栗子
情迁抢包是项目名,后面一堆文字描述就是在xposeddescription的value中标注的(这个抢红包贼稳)
xposedminversion:xposed最低版本,这些应该都是向下兼容的吧?所以直接填最低版本好了
4.下面就可以开车啦
【第一个Xposed模块的编写】
直接输出日志什么的太low了,找其他软件hook我怕被举报(放屁,其实是我特么也还不会),所以就自己写个类来hook练练手吧!
我们先写一个MainActivity类输出一个Toast提示,然后再写一个HookToast类作为Xposed模块来hook它,实现修改
0.在界面中添加一个可爱的小button
1.代码逻辑如下:
[Java] 纯文本查看 复制代码 public class MainActivity extends AppCompatActivity {
private Button button;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(MainActivity.this, toastMessage(), Toast.LENGTH_SHORT).show();
}
});
}
public String toastMessage() {
return "我未被劫持";
}
}
比较容易理解,这个类的功能是,点击按钮,弹出一个toast提示,内容由toastMessage()方法提供,而toastMessage()的返回值为“我未被劫持”
下面我们正式开始写我们的xposed模块,来hook我们的MainActivity,修改toastMessage()方法的返回值为“你已被劫持”
2.我们新建一个HookToast类
[Java] 纯文本查看 复制代码 public class HookToast implements IXposedHookLoadPackage {
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (loadPackageParam.packageName.equals("com.example.mingking.xposedtest")) {
Class clazz = loadPackageParam.classLoader.loadClass("com.example.mingking.xposedtest.MainActivity");
XposedHelpers.findAndHookMethod(clazz, "toastMessage", new XC_MethodHook() {
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
}
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
param.setResult("你已被劫持");
}
});
}
}
}
这个类实现IXposedHookLoadPackage接口,并实现IXposedHookLoadPackage接口中的handleLoadPackage方法
代码中,hook的包名记得改成自己的
在handleLoadPackage方法中先筛选到我们本程序的包名,然后用XposedHelpers里的findAndHookMethod方法对
MainActivity中的toastMessage方法进行劫持,在其Hook的回调中的beforeHookedMethod或afterHookedMethod
方法里进行劫持操作
afterHookedMethod方法中,我们修改了toastMessage()方法的返回值为“你已被劫持”
beforeHookedMethod方法中,我们什么也不用做,当然,我们也可以在xposed日志中输出一点调试信息玩耍一下,
方法中添加语句:
[Java] 纯文本查看 复制代码 XposedBridge.log("别看了,老子已经成功Hook");
到此,所有代码已经写完,之前在AndroidManifest.xml中标识了我们的项目是一个Xposed模块,可是我们可能会有许多Activity,
它怎么才能知道模块的入口在哪呢?
所以,下面要告诉Xposed框架,我们的应用中,Xposed模块的入口到底在哪。
3.标注Xposed模块入口
右键点击 main , 选择new --> Folder -->Assets Folder,然后确认即可。
在assets中new一个file,文件名为xposed_init(文件类型选text),并在其中写上入口类的完整路径(下面是我的类路径,你们填自己的,就是activity中packege后面的包名)
这样,xposed框架就能够读取xposed_init中的信息来找到模块的入口
4.Run
请确保禁用Instant Run(File -> Settings -> Build, Execution, Deployment -> Instant Run),否则您的类不会直接包含在APK中,导致HOOK失败!!!
以上是来自官方的警告,一定要注意,之前我死活hook不了,日志也输出不了,就是因为这个!!!
如果你不这样做,你会惊喜地发现发现xposed日志反复给你抛出类似这样一个错误:
xposed didn't find class on dexpathlist:……(省略一长串)
而这个错误是你百度到死(google也没用)也不一定查的到解决方案的(这个故事提醒我们要仔细阅读官方文档)
Run成功后……
可以发现,xposed模块里出现了我们的模块
XposedTest是应用名
后面的文字注释正是我们之前在AndroidManifest.xml中的xposeddescription里所标注的信息
xposed模块生效前
勾选并重启
啦啦啦,成功!!!
再让我们看看xposed框架里的日志
完全没毛病!!!(hook的是toastMessage()方法,它每次被调用都会在hook之前输出日志,hook之后修改返回值,我之前点击了三次,所以输出了三条)
到此,你就算是入坑xposed了,当然,上面的例程比较简单,实际的应用要复杂得多,大家可以到github找些开源项目学习一下,不懂的地方多多参照官方API文档:
http://api.xposed.info/reference/packages.html
【参考资料】
1.http://blog.csdn.net/mrglaucusss/article/details/50963542
2.https://www.52pojie.cn/thread-533120-1-1.html
3.https://www.cnblogs.com/dacainiao/p/6002609.html
4.https://github.com/rovo89/XposedBridge/wiki/Development-tutorial
5.https://github.com/rovo89/Xposed ... posed-Framework-API
6.http://blog.csdn.net/w958796636/article/details/52919582
7.http://blog.csdn.net/aa464971/article/details/68948650
后续暂时没有时间深入学习,如果有,我再分享新的教程,当然,我可能在那之前你们可能已经更牛了,当然也欢迎你们分享学习成果
如果大家遇到什么新的问题,可以在评论区反馈,以便我及时更新整理完善,帮助后来之人 |