程序包 io.github.libxposed.api


package io.github.libxposed.api
现代 Xposed 模块 API。

该包提供用于使用现代 Xposed 框架开发 Xposed 模块的公共 API。 它用一个重新设计、类型安全的接口替代了旧的 XposedBridge API。

快速开始

模块入口类应继承 XposedModule。 框架会自动调用 attachFramework();模块不应onModuleLoaded() 被调用之前执行任何初始化工作。

入口注册

Java 入口类需要在 META-INF/xposed/java_init.list 中列出(每行一个完整类名); native 入口使用 META-INF/xposed/native_init.list。 将这些文件放在 src/main/resources/META-INF/xposed/ 下,Gradle 会自动将其打包进 APK。

模块配置

模块元数据通过标准 Android 资源文件指定(android:label 用于模块名称, android:description 用于描述)以及 META-INF/xposed/module.prop(Java Properties 格式)。 必需属性:

  • minApiVersion —— 所需的最低 Xposed API 版本
  • targetApiVersion —— 目标 Xposed API 版本

可选属性:

  • staticScope(boolean)—— 模块作用域是否固定,用户不应将模块应用到 scope 列表之外的应用
  • exceptionMode(string)[protective|passthrough] —— 默认值为 protective,参见 XposedInterface.ExceptionMode

作用域(Scope)

模块作用域通过 META-INF/xposed/scope.list 中的包名列表定义。 框架会将模块注入到这些包所声明的所有常规进程中。 注入后,该进程中所有已加载的包都会触发回调。 因此模块可能会收到超出原始 scope 的回调, 应始终根据进程名和包名进行过滤。

特殊情况:对于在 android:sharedUserId="android.uid.system" 的包中声明 android:process="system" 的组件,它们运行在 system server 中。 如果一个包的所有组件都运行在 system server 中,那么将该包名加入 scope 是无效的。 此时 system server 使用特殊虚拟包名 system 表示,必须显式使用。

注意 android 包仍然是合法的 scope 目标,因为其中部分组件声明了 android:process=":ui",因此不运行在 system server。 作用域包含 android 的模块仍然可以接收 android 包加载事件, 即使该包本身没有代码。 相比之下,com.android.providers.settings 不是合法 scope 目标, 模块应使用 system scope,然后等待该包的加载事件。

Hook 模型

该 API 使用拦截器链(interceptor-chain)模型(类似 OkHttp interceptor)。 模块实现 Hooker 并重写 intercept(Chain) 方法。 通过 hook(Executable) 返回的 builder 进行 hook:


 HookHandle handle = hook(method)
     .setPriority(PRIORITY_DEFAULT)
     .setExceptionMode(ExceptionMode.PROTECTIVE)
     .intercept(chain -> {
         // 前置处理
         Object result = chain.proceed();
         // 后置处理
         return result;
     });
 

Invoker 系统

为了在绕过访问检查的情况下调用原始(或被 hook 的)方法,可以通过 getInvoker(Method)getInvoker(Constructor) 获取 Invoker。 Invoker 类型决定执行 hook 链的哪一部分(见 Invoker.Type)。

模块生命周期回调

XposedModule 中可重写以下回调:

错误处理

框架级错误通过 XposedFrameworkError 的子类报告。 其中 HookFailedError 表示致命 hook 失败, 应上报给框架维护者,而不是由模块自行处理。

另请参阅: