Xposed Module Development
Copyright
Copyright (c) 2026 Ninthless. All rights reserved. This skill may not be copied, modified, redistributed, or used to create derivative works without prior written permission.
Triggers
- The user wants to build, review, migrate, or debug an Android Xposed or LSPosed module.
- The task mentions libxposed, XposedBridge, hooks, scope.list, module.prop, xposed_init, or logcat.
- The user needs help with module activation, module not showing in LSPosed, scope problems, or metadata files.
- The user asks to migrate from legacy XposedBridge to modern libxposed.
- The user says
写 Xposed 模块,LSPosed 模块,hook 安卓 App,模块不显示,作用域, or迁移到 libxposed.
Use this skill to help users develop correct Android Xposed/LSPosed modules. Prefer current LSPosed/libxposed patterns for new modules, but recognize and support legacy XposedBridge projects when the repository already uses them or the user explicitly targets old API compatibility.
First Decision
Before writing code, identify which API family the project uses:
- Modern libxposed API: entry class extends
io.github.libxposed.api.XposedModule; registration lives undersrc/main/resources/META-INF/xposed/; hook code useshook(Executable)and interceptor chains. - Legacy XposedBridge API: entry class implements
IXposedHookLoadPackage,IXposedHookZygoteInit, or resource hook interfaces; registration is usuallysrc/main/assets/xposed_init; hook code usesXposedHelpers.findAndHookMethod,XC_MethodHook, orXC_MethodReplacement.
Do not mix modern io.github.libxposed.api with legacy de.robv.android.xposed in the same module unless the user has a very specific compatibility plan. The two systems have different entry registration, lifecycle, metadata, and hook APIs.
Modern Module Checklist
For a new LSPosed module, produce or verify this structure:
app/src/main/AndroidManifest.xml
app/src/main/java/<package>/<Entry>.java
app/src/main/resources/META-INF/xposed/java_init.list
app/src/main/resources/META-INF/xposed/module.prop
app/src/main/resources/META-INF/xposed/scope.list
Use Android resources for the module name and description:
<application
android:label="@string/app_name"
android:description="@string/module_description">
</application>
Use module.prop for framework API requirements:
minApiVersion=101
targetApiVersion=101
staticScope=true
Declare the modern Xposed API dependency as compileOnly; it is provided by the framework at runtime. If the Android Gradle plugin strips Java resources, configure packaging so META-INF/xposed/* stays in the APK. In Kotlin DSL projects, the official example uses this shape:
packaging {
resources {
merges += "META-INF/xposed/*"
excludes += "**"
}
}
dependencies {
compileOnly("io.github.libxposed:api:<version>")
}
Use java_init.list with one fully qualified entry class per line:
com.example.module.MainHook
Use scope.list with one target package per line:
com.target.app
system
For system hooks, use system when the code runs inside system_server. Keep android only for Android package components that actually load outside system_server.
Modern Entry Pattern
Use this shape as the baseline. Adjust names and target classes to the user's project.
package com.example.module;
import android.util.Log;
import io.github.libxposed.api.XposedModule;
import java.lang.reflect.Method;
public final class MainHook extends XposedModule {
private static final String TAG = "ExampleModule";
@Override
public void onPackageReady(PackageReadyParam param) {
if (!"com.target.app".equals(param.getPackageName())) {
return;
}
try {
Class<?> clazz = param.getClassLoader().loadClass("com.target.app.TargetClass");
Method method = clazz.getDeclaredMethod("targetMethod", String.class);
hook(method).intercept(chain -> {
Object arg = chain.getArg(0);
Log.i(TAG, "targetMethod arg=" + arg);
Object result = chain.proceed();
return result;
});
} catch (ReflectiveOperationException e) {
Log.e(TAG, "Failed to install hook", e);
}
}
}
Prefer onPackageReady() for app hooks because the app classloader is ready. Use onPackageLoaded() only when the hook must happen before AppComponentFactory or very early app initialization. Use onSystemServerStarting() for system server hooks.
Legacy Module Checklist
For existing legacy projects, verify:
app/src/main/assets/xposed_init
app/src/main/AndroidManifest.xml
app/build.gradle(.kts)
Legacy xposed_init contains one fully qualified entry class per line:
com.example.module.MainHook
Legacy metadata is normally declared on the application element:
<meta-data android:name="xposedmodule" android:value="true" />
<meta-data android:name="xposeddescription" android:value="@string/module_description" />
<meta-data android:name="xposedminversion" android:value="93" />
Declare the Xposed API dependency as compileOnly; it is provided by the framework at runtime and should not be packaged into the APK.
Legacy Entry Pattern
package com.example.module;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
public final class MainHook implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
if (!"com.target.app".equals(lpparam.packageName)) {
return;
}
XposedHelpers.findAndHookMethod(
"com.target.app.TargetClass",
lpparam.classLoader,
"targetMethod",
String.class,
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) {
String value = (String) param.args[0];
}
}
);
}
}
Hooking Rules
- Filter by
packageNameand, when relevant,processName. Modules can be injected into processes where multiple packages are observed. - Use the target app's classloader, not the module app's classloader, for target classes.
- Hook the narrowest stable method you can identify. Avoid broad hooks such as
Application.attach()as the final behavior unless it is only used to obtain context or classloader. - Avoid doing heavy work in early callbacks. Install hooks quickly and defer I/O, networking, or long analysis.
- Catch reflection lookup failures around optional targets so one missing class does not crash the target process.
- Log the package, process, and hook installation result. Ask the user for
adb logcataround the target process when debugging crashes. - Treat obfuscated apps as moving targets. Prefer finding classes by stable behavior, signatures, resources, or call chains, and document the app version used for analysis.
- Do not hook banking, payment, DRM, anti-cheat, or third-party security controls for bypass or unauthorized access. Keep work scoped to legitimate debugging, customization, research on owned devices, or user-controlled apps.
Common Failure Modes
- Module not appearing in LSPosed: missing registration file, wrong resources path, malformed
module.prop, or APK installed for another Android user. - Module appears but hook never runs: target package missing from scope, no reboot/restart after enabling, wrong process, or package name mismatch.
- Class not found: using the wrong classloader, hooking too early, dynamic feature not loaded, app obfuscation changed, or target code is native.
- Target app crashes: uncaught exception in callback, bad cast, wrong parameter list, returning an invalid replacement value, or triggering recursion by calling a hooked method incorrectly.
- Modern module ignored: old
assets/xposed_initused instead ofMETA-INF/xposed/java_init.list, or modern API called by reflection. - Legacy module broken after migration: metadata, entry registration, resource hooks, and helper APIs were not translated to modern equivalents.
Development Workflow
- Inspect the repository before changing files. Determine Gradle DSL, Kotlin vs Java, AGP version, namespace, minSdk, and whether it already uses modern or legacy Xposed APIs.
- Identify the target package, target process, Android/LSPosed version, and expected behavior change.
- Add the smallest valid module skeleton for the selected API family.
- Write hook code with explicit package/process filters and defensive reflection handling.
- Build with Gradle. Fix compile errors before speculating about runtime behavior.
- Install the APK, enable the module, set scope, force-stop or reboot as required, then inspect
adb logcatfiltered by module tag, LSPosed, and target package. - When debugging runtime failures, ask for or collect the exact stack trace and target app version. Do not guess from symptoms alone.
When Explaining To Users
Respond in the user's language when practical. For Chinese users, explain the split clearly:
- 新项目默认建议现代
libxposedAPI。 - 旧项目或追求广泛兼容时继续用
XposedBridgelegacy API。 - 两套 API 的入口文件、Manifest/metadata、scope 和 hook 写法不同,不能随意拼接。
If you provide code, include the files that must exist and where each snippet belongs. If the user only asks "怎么写", give a minimal working skeleton plus the build/install/enable/debug steps.
References
Read references/xposed-reference.md when you need source-backed details about modern registration, lifecycle callbacks, scope behavior, or legacy API names.