看了一下文檔,發現Xposed這貨實在太強大了,它直接對Zygote做了一些手腳,簡直是無所不能。缺點就是需要安裝一下框架。基本原理就是把Android 系統的app_process給替換了,然后啟動Zygote的時候多加載點東西,通過一些特殊手段直接把Zygote和Dalvki給劫持了。本文就將帶領讀者去完成一個簡單的Xposed的Module,讓大家領略一下Xposed的威力。
要想能看到程序運行的結果,你首先要有一部Root過,安裝過Xposed框架和XposedInstaller的手機。這部分不在本篇教程范圍內,請自行百度。Xposed的官方下載地址
項目的源碼地址:click me
一,建立項目
AS工程,本人AS版本2.0 p8,這個版本建立完工程需要做一個特殊操作,要把Project的build文件里的
classpath 'com.android.tools.build:gradle:2.0.0-alpha8'
換成
classpath 'com.android.tools.build:gradle:1.5.0'
不然無法開發Xposed Module。
然后需要在這里 下載XposedBridgeApi-XX.jar,XX為最新版本號。這個是Xposed Module開發需要的Lib。
將XposedBridgeApi-XX.jar引入項目。
二,Android App部分開發。
這部分就很簡單了,是一個EditText,一個按鈕,在EditText中輸入數字3然后點擊按鈕后會顯示yes,否則就是no。
AS建立項目后默認會有一個名為app的module(這個是安卓項目的module),在這個module下開發就行,不需要另外開modu。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" > <EditText android:id="@+id/edit" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="請輸入3" /> <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/edit" android:layout_centerHorizontal="true" android:text="測試" /> </RelativeLayout>
public class MainActivity extends AppCompatActivity { Button btn; EditText edit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = (Button) findViewById(R.id.btn); edit = (EditText) findViewById(R.id.edit); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int a; try { a = Integer.parseInt(edit.getText().toString()); } catch (Exception e) { Toast.makeText(MainActivity.this, "Oh!No!!", Toast.LENGTH_SHORT).show(); return; } if (isEquals(a)) { Toast.makeText(MainActivity.this, "Yes!you got it!!", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "Oh!No!!", Toast.LENGTH_SHORT).show(); } } }); } private boolean isEquals(int a) { if (a == 3) { return true; } return false; } }
很簡單的一個安卓程序,不需要過多解釋了。
三,Xposed部分開發
這個項目的xposed module的功能是hook本項目Android 程序部分,讓 Activity的isEquls(int a)方法始終返回true,這樣無論我們輸入什么數字,最終都會顯示yes。
修改清單文件:
<meta-data android:name="xposedmodule" android:value="true" /> <meta-data android:name="xposeddescription" android:value="Test Xposed" /> <meta-data android:name="xposedminversion" android:value="46" />
這些是聲明這個項目是一個xposed module。其中xposedminversion表示支持的最低的xposed api版本。
建立一個Java Class文件:
/** * Created by csonezp on 16-2-2. */ public class HookDemo implements IXposedHookLoadPackage { @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable { //你想操作的應用的包名,這里為這個項目自身的包名 if (loadPackageParam.packageName.equals("com.csonezp.xposeddemo2")) { Class clasz = loadPackageParam.classLoader.loadClass("com.csonezp.xposeddemo2.MainActivity"); //hook MainActivity的 isEquls 方法 XposedHelpers.findAndHookMethod(clasz, "isEquals", int.class, new XC_MethodHook() { //這倆個方法任選其一就可以達到效果 //方法執行前進行的操作 @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { Integer para1 = (Integer) param.args[0]; //獲取參數1 String s1 = Integer.toString(para1); Log.v("hook before param1:", s1); param.args[0] = 3; //設置參數1,也就是將isEquls的參數恆定設為3 Log.v("hook", "before hook!"); XposedBridge.log("hook before param1:" + s1); } @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { boolean res = (boolean) param.getResult(); Log.v("hook after result :", res + ""); Integer para1 = (Integer) param.args[0]; //獲取參數1 String s1 = Integer.toString(para1); param.setResult(true); //設置返回值,始終為true XposedBridge.log("hook after result:true"); Log.v("hook param1:", s1); } }); } } }
這就是這個Xposed Module的核心方法了。這個類實現了IXposedHookLoadPackage接口,當讀取系統Package的時候,就會調用handleLoadPackage方法。
這里handleLoadPackage主要對“com.csonezp.xposeddemo2” 這個包(也就是本項目)的MainActivity 的 isEquals方法進行一些操作,讓這個方法始終返回true。
然后就要添加一個assets文件夾。
右鍵點擊 app這個module --> new --> Folder -->Assets Folder,然后確認即可。
在assets文件夾中建立一個xposed_init文件
文件內容就是我們上面寫的那個Java Class的類名,Xposed框架就是通過這里加載我們的類的,所以一定不要寫錯。
OK,大功告成,將程序裝到手機上,在XposedInstaller中開啟我們的Module,重啟手機,再打開App,你會發現無論在EditText中輸入什么數字,顯示的都是Yes了