最近心血來(lái)潮躏尉,開始折騰xposed框架蚯根,xposed框架可以說(shuō)得上是款A(yù)ndroid系統(tǒng)God級(jí)別的開源hook框架,擁有非常高的權(quán)限胀糜,不過(guò)目前還暫不支持Android 7.0 以上的系統(tǒng)颅拦。這也是我一直沒(méi)有升級(jí)的原因
什么是xposed
Xposed框架是一款可以在不修改APK的情況下影響程序運(yùn)行(修改系統(tǒng))的框架服務(wù),基于它可以制作出許多功能強(qiáng)大的模塊教藻,且在功能不沖突的情況下同時(shí)運(yùn)作距帅。Xposed理論上能夠hook到系統(tǒng)任意一個(gè)Java進(jìn)程,由于是從底層hook括堤,所以需要root權(quán)限碌秸,并且每次更新都要重新啟動(dòng)
Xposed官方git上面有幾個(gè)開源項(xiàng)目,包括XposedInstaller悄窃、Xposed哮肚、XposedBridge、XposedTools广匙,這里就不具體介紹了允趟,感興趣的可以查找相關(guān)資料,附上官方git地址:https://github.com/rovo89
Xposed模擬器環(huán)境搭建
由于Xposed項(xiàng)目每次安裝都要重新啟動(dòng)鸦致,在真機(jī)上是非常耗時(shí)間的潮剪,所以在這里選擇Genymotion模擬器涣楷,老版本的Genymotion模擬器有免費(fèi)版本的,我提供一款mac版的模擬器抗碰。win自己百度下載狮斗,mac版下載地址:https://pan.baidu.com/s/1pLDbymn ,密碼:j3rf弧蝇。鏡像選擇Android5.0系統(tǒng)碳褒,其他版本類似。然后到官網(wǎng)下載Android5.0對(duì)應(yīng)的框架看疗,飛機(jī)直達(dá)沙峻,選擇.zip結(jié)尾的文件,下載完成后運(yùn)行模擬器两芳,將zip包拖到模擬器界面刷入即可摔寨,完成后重啟模擬器。安裝XposedInstaller_3.1.1 .apk應(yīng)用怖辆,再次重啟是复。進(jìn)入剛剛安裝的app,提示已激活即安裝成功

第一個(gè)項(xiàng)目
創(chuàng)建Xposed工程
為了方便今后的教程竖螃,工程已傳到github淑廊,可以直接clone該工程到本地。項(xiàng)目地址:https://github.com/WrBug/XposedDemo ,后面的教程的代碼也都將在這個(gè)工程里面特咆,通過(guò)clone的可忽略下面創(chuàng)建工程的步驟蒋纬。通過(guò)命令切換到提交:
git checkout 20195ce
創(chuàng)建一個(gè)新工程,build.gradle添加依賴:
provided 'de.robv.android.xposed:api:82'
編輯AndroidManifest.xml坚弱,添加:
<meta-data
android:name="xposedmodule"
android:value="true"/>
<meta-data
android:name="xposeddescription"
android:value="hello xposed"/>
<meta-data
android:name="xposedminversion"
android:value="82"/>
配置完成后,安裝到模擬器关摇,狀態(tài)欄彈出如下提示:

第一個(gè)框架:Hello Xposed
git提交:43e4ba39e95988f0fa699ad5eddb1e55b9613638
Activity創(chuàng)建
編輯activity_main.xml荒叶,放入一個(gè)TextView:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.wrbug.xposeddemo.MainActivity">
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</LinearLayout>
MainActivity 里面設(shè)置文本信息:
public class MainActivity extends AppCompatActivity {
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textview);
textView.setText("WrBug");
}
}
Activity很簡(jiǎn)單。就是一個(gè)textview的顯示输虱。安裝到模擬器上些楣,界面顯示一行WrBug,下面通過(guò)xposed將WrBug修改成Hello Xposed顯示宪睹。
思路:Xposed hook onCreate方法愁茁。在該方法執(zhí)行完后獲取TextView的實(shí)例。通過(guò)setText方法設(shè)置文本
Xposed實(shí)現(xiàn)
新建一個(gè)類XposedInit實(shí)現(xiàn)IXposedHookLoadPackage亭病,關(guān)于IXposedHookLoadPackage等接口鹅很,后面的文章會(huì)有說(shuō)明。
public class XposedInit implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam){
//app啟動(dòng)時(shí)調(diào)用
}
}
新建assets文件夾罪帖,文件夾下新建xposed_init文件促煮,編輯文件邮屁,填寫XposedInit的完整包名:com.wrbug.xposeddemo.XposedInit
在XposedInit中handleLoadPackage方法會(huì)在應(yīng)用啟動(dòng)時(shí)調(diào)用。所以需要篩選需要hook的app的包名菠齿,這里選擇同個(gè)應(yīng)用:
@Override
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam){
if (lpparam.packageName.equals("com.wrbug.xposeddemo")) {
}
}
通過(guò)XposedHelpers的findAndHookMethod方法hook onCreate 方法佑吝,獲取到TextView實(shí)例,在方法執(zhí)行后通過(guò)setText設(shè)置方法绳匀。
public class XposedInit implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) {
if (lpparam.packageName.equals("com.wrbug.xposeddemo")) {
XposedHelpers.findAndHookMethod("com.wrbug.xposeddemo.MainActivity", lpparam.classLoader, "onCreate", Bundle.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//不能通過(guò)Class.forName()來(lái)獲取Class 芋忿,在跨應(yīng)用時(shí)會(huì)失效
Class c=lpparam.classLoader.loadClass("com.wrbug.xposeddemo.MainActivity");
Field field=c.getDeclaredField("textView");
field.setAccessible(true);
//param.thisObject 為執(zhí)行該方法的對(duì)象,在這里指MainActivity
TextView textView= (TextView) field.get(param.thisObject);
textView.setText("Hello Xposed");
}
});
}
}
}
除了上面通過(guò)反射的方法來(lái)獲取以外疾棵,還可以通過(guò)findViewById等方法獲取TextView對(duì)象戈钢,有興趣的可以思考下如果xml里面沒(méi)有設(shè)置TextView的ID,并且不是MainActivity的成員變量陋桂,該怎么獲取這個(gè)View逆趣,歡迎大家在下方進(jìn)行討論。安裝重啟模擬器后嗜历,打開app宣渗,這時(shí)textView將顯示Hello Xposed
后面的文章會(huì)講解具體的使用,歡迎大家關(guān)注
更多精彩文章請(qǐng)關(guān)注:http://www.mandroid.cn