Sunday, February 23, 2014

Simple steps to start a new module for Xposed Framework

This is a concise version of official tutorial published on Xposed Framework's Wiki.

Reference
  1. Official tutorial: https://github.com/rovo89/XposedBridge/wiki/Development-tutorial



1. Declare the module in AndroidManifest.xml
<application
    ...>
    <meta-data android:name="xposedmodule" android:value="true"/>
    <meta-data android:name="xposedminversion" android:value="2.0*" />
    <meta-data android:name="xposeddescription" android:value="..." />
</application>

2. Create a text file called xposed_init (without .txt) in your assets folder with your main class as the content.
com.example.YourXposedModuleMainClass

3. Inject package loading process using handleLoadPackage() method
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
    if (!lpparam.packageName.equals("com.android.systemui"))
        return; 
    XposedBridge.log("we are in SystemUI!");
}

4. Hook and replace your methods of choice. Don't forget to static import this method:
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;

Run your code before/after a method. You can determine the returned result of the method using the MethodHookParam.
findAndHookMethod("com.example.TheClassYouWantToModify", lpparam.classLoader, "isThisTheMethodToBeHooked", new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
        // this will be called before the original method is executed
        if (somethingHappens) {
            // modify the result of the original method
            param.setResult(false);
        }
    }

    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
        // this will be called after
    }
}

You can also replace the method completely. If the function has some params, make sure you include them in the findAndHookMethod function call.

findAndHookMethod("com.example.SomeClass", loadPackageParam.classLoader, "getAudioEnabled", Context.class, String.class, new XC_MethodReplacement() {
    @Override
    protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
        return true;
    }
});