# 【开始前的准备】
1. 掌握基本的android开发知识,搭建好android开发环境(环境怎么搭啥的也有一堆蛋疼问题,这里就不说了,改天我仔细探索整理一下)
2. 有xposed框架作为环境(真机或者模拟器,我下面直接真机调试)
3. Xposed框架API(网上各种坑爹教程附各种不知啥时候会挂掉,资源老,老子可能要账号才能下载的坑爹链接,也不给个官网地址,所以)
4. 由于它是不断更新的,请大家直接到官网页面进行下载:[https://jcenter.bintray.com/de/robv/android/xposed/api/](https://jcenter.bintray.com/de/robv/android/xposed/api/)
下载如下两个文件:
[api-82-sources.jar](https://bintray.com/rovo89/de.robv.android.xposed/download_file?file_path=de%2Frobv%2Fandroid%2Fxposed%2Fapi%2F82%2Fapi-82-sources.jar)
[api-82.jar](https://bintray.com/rovo89/de.robv.android.xposed/download_file?file_path=de%2Frobv%2Fandroid%2Fxposed%2Fapi%2F82%2Fapi-82.jar)
# 【环境的搭建】
## 就是将Xposed框架API引用到项目中,这样就能进行Xposed模块的开发了
1. 使用android studio构建一个项目
(小提示,注意设置为project查看,这样项目结构看得更加清楚)
![](https://img.kancloud.cn/8a/90/8a900ccef5677d5caee3718de8473345_355x784.png)
下方修改处皆在上图中用箭头指出(build.gradle是app文件夹中的,注意不要搞错)
**1.将下载下来的两个文件复制到文件夹libs中**
**2.在build.gradle中将添加图中两句**
![](https://img.kancloud.cn/c2/fc/c2fc543e029288397cf66ee5e9159d42_763x226.png)
~~~
provided 'de.robv.android.xposed:api:82'
provided 'de.robv.android.xposed:api:82:sources'
~~~
**3.在AndroidManifest.xml将自己标识为一个Xposed模块,语句添加在如下位置**
![](https://img.kancloud.cn/76/86/76861af82c6932388ced294872845a9e_792x811.png)
```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框架中看到,举个栗子
![](https://img.kancloud.cn/9e/a1/9ea18e24fd36e6adcbcfd04151a945e9_1080x1920.png)
情迁抢包是项目名,后面一堆文字描述就是在xposeddescription的value中标注的(这个抢红包贼稳)
**xposedminversion:xposed最低版本,这些应该都是向下兼容的吧?所以直接填最低版本好了**
**4.下面就可以开车啦**
## 【第一个Xposed模块的编写】
直接输出日志什么的太low了,找其他软件hook我怕被举报(放屁,其实是我特么也还不会),所以就自己写个类来hook练练手吧!
我们先写一个MainActivity类输出一个Toast提示,然后再写一个HookToast类作为Xposed模块来hook它,实现修改
**0.在界面中添加一个可爱的小button**
![](https://img.kancloud.cn/e8/79/e8790268943c9de92f252e00f70a1c57_427x688.png)
**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("你已被劫持");
}
});
}
}
}
```
到此,所有代码已经写完,之前在AndroidManifest.xml中标识了我们的项目是一个Xposed模块,可是我们可能会有许多Activity,
它怎么才能知道模块的入口在哪呢?
所以,下面要告诉Xposed框架,我们的应用中,Xposed模块的入口到底在哪。
**3.标注Xposed模块入口**
右键点击 main , 选择new --> Folder -->Assets Folder,然后确认即可。
![](https://img.kancloud.cn/20/68/2068c1a40ebb8c176bd89ef3079bff90_869x829.png)
在assets中new一个file,文件名为xposed_init(文件类型选text),并在其中写上入口类的完整路径(下面是我的类路径,你们填自己的,就是activity中packege后面的包名)
![](https://img.kancloud.cn/5e/18/5e189e70d1365372480cce19dc7146d0_706x202.png)
![](https://img.kancloud.cn/e8/6a/e86a49c01871d2db7ac6a91ea1bc7099_460x87.png)
这样,xposed框架就能够读取xposed\_init中的信息来找到模块的入口
**4.Run**
请确保禁用Instant Run(File -> Settings -> Build, Execution, Deployment -> Instant Run),否则您的类不会直接包含在APK中,导致HOOK失败!!!
![](https://img.kancloud.cn/8f/97/8f97a8f76e9daab41573fd319e7b7f88_1038x743.png)
以上是来自官方的警告,一定要注意,之前我死活hook不了,日志也输出不了,就是因为这个!!!
**如果你不这样做,你会惊喜地发现发现xposed日志反复给你抛出类似这样一个错误:**
**xposed didn't find class on dexpathlist:……(省略一长串)**
**而这个错误是你百度到死(google也没用)也不一定查的到解决方案的(这个故事提醒我们要仔细阅读官方文档)**
**Run成功后……**
可以发现,xposed模块里出现了我们的模块
XposedTest是应用名
后面的文字注释正是我们之前在AndroidManifest.xml中的xposeddescription里所标注的信息
# 在新版本的Androi Studio 3.5.1上踩的坑
```
~~~
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.gyk.xposedmodule"
minSdkVersion 16
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compileOnly files('libs/api-82.jar')
// compileOnly 'de.robv.android.xposed:api:82:sources'
// 有这句我们就hook不了,我日他妈
// implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
~~~
```