CommunityWriting & Editinggithub.com

Marukon/skill-upgrade-libxposed-102

agent-skill

What is skill-upgrade-libxposed-102?

skill-upgrade-libxposed-102 is a Claude Code agent skill that agent-skill.

Works with~Claude Code~Codex CLI~Cursor
npx skills add Marukon/skill-upgrade-libxposed-102

Installed? Explore more Writing & Editing skills: steipete/notion, affaan-m/seo, affaan-m/brand-voice · View all 6 →

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Xposed 模块升级至 LibXposed API 102 完全指南

本文档总结了将传统 Xposed 模块(基于 XposedBridge API 54-93)升级至现代 LibXposed API 102(适用于 LSPosed 1.9.3+、Vector 等现代框架)的标准流程、代码范式、元数据规范与性能优化策略。

后续对任何其他模块执行升级指示时,可直接参照本规范执行。


一、核心变更对比

特性 / 维度传统 Xposed (API 54-93)现代 LibXposed (API 102)
依赖坐标de.robv.android.xposed:api:82 (或 93)io.github.libxposed:api:102.0.0
入口基类/接口IXposedHookLoadPackage, IXposedHookZygoteInit继承 io.github.libxposed.api.XposedModule
入口声明assets/xposed_initMETA-INF/xposed/java_init.list
模块属性配置AndroidManifest.xml 中的 <meta-data>META-INF/xposed/module.prop
作用域声明xposedscope resource arrayMETA-INF/xposed/scope.list
Hook 编程模型XC_MethodHook (before / after) 回调类 OkHttp 的链式拦截器 Hooker (chain.proceed())
热重载 (Hot Reload)不支持(需重启目标应用甚至系统)原生支持(重写 onHotReloading / onHotReloaded
Zygote 注入支持 initZygote 全局注入禁止 Zygote 注入,仅注入到作用域目标进程
混淆/R8 支持需严格保留 Hook 方法名与类名原生支持 R8 混淆,声明适配规则即可

二、标准迁移四步法

第一步:构建与依赖迁移 (build.gradle)

  1. 更新依赖项: 在模块的 build.gradle(如 app/build.gradlehook/build.gradle)中替换依赖:

    dependencies {
        // 移除: compileOnly 'de.robv.android.xposed:api:82'
        // 引入现代 LibXposed 102 API
        compileOnly 'io.github.libxposed:api:102.0.0'
        compileOnly 'androidx.annotation:annotation:1.5.0'
    }
    
  2. Java 编译兼容性

    android {
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_11
            targetCompatibility JavaVersion.VERSION_11
        }
    }
    
  3. 配置 ProGuard / R8 规则 (proguard-rules.pro)

    -dontwarn io.github.libxposed.annotation.**
    -adaptresourcefilecontents META-INF/xposed/java_init.list
    -keep,allowoptimization,allowobfuscation public class * extends io.github.libxposed.api.XposedModule {
        public <init>();
    }
    

第二步:现代元数据文件配置 (META-INF/xposed/)

在模块源码目录 src/main/resources/META-INF/xposed/ 下创建以下文件:

1. module.prop(模块元数据)

minApiVersion=102
targetApiVersion=102
autoHotReload=true
exceptionMode=protective
  • minApiVersion: 最低支持的 API 版本,设为 102
  • targetApiVersion: 目标 API 版本,设为 102
  • autoHotReload: 设为 true 表示模块更新安装时自动触发热重载。
  • exceptionMode: protective(默认保护模式,Hook 抛异常不影响宿主崩溃)或 passthrough

2. java_init.list(入口类声明)

单行声明模块入口全限定类名:

com.example.myhook.MainHook

3. scope.list(推荐作用域)

每行一个目标包名,声明模块默认需要注入的应用:

com.android.chrome
com.microsoft.emmx
com.example.targetapp

第三步:清单文件配置 (AndroidManifest.xml)

更新模块的 AndroidManifest.xml

<application ...>
    <!-- 传统元数据保持兼容,关键将 xposedminversion 设为 102 -->
    <meta-data
        android:name="xposedmodule"
        android:value="true" />
    <meta-data
        android:name="xposeddescription"
        android:value="模块功能描述" />
    <meta-data
        android:name="xposedminversion"
        android:value="102" />
    <meta-data
        android:name="xposedscope"
        android:resource="@array/xposed_scope" />
</application>

第四步:Hook 逻辑重构 (XposedModule)

1. 基础模板与生命周期

package com.example.myhook;

import android.util.Log;
import androidx.annotation.NonNull;
import io.github.libxposed.api.XposedInterface;
import io.github.libxposed.api.XposedModule;

public class MainHook extends XposedModule {

    private static final String TAG = "MyHookModule";
    private volatile boolean mHooked = false;

    public MainHook() {
        super();
    }

    /**
     * 宿主应用 ClassLoader 就绪且即将创建 Application 时触发
     */
    @Override
    public void onPackageReady(@NonNull PackageReadyParam param) {
        if (mHooked) return;
        synchronized (this) {
            if (mHooked) return;
            mHooked = true;
            initHooks(param.getPackageName(), param.getClassLoader());
        }
    }

    /**
     * 热重载准备回调(运行在旧版本代码中)
     * 返回 true 允许框架替换为新版本
     */
    @Override
    public boolean onHotReloading(@NonNull HotReloadingParam param) {
        return true;
    }

    /**
     * 热重载完成回调(运行在新版本代码中)
     */
    @Override
    public void onHotReloaded(@NonNull HotReloadedParam param) {
        // 解除旧版本注册的所有 Hook
        param.getOldHookHandles().forEach(XposedInterface.HookHandle::unhook);
        synchronized (this) {
            mHooked = false;
            initHooks("hot-reload", getClass().getClassLoader());
        }
    }

    private void initHooks(String packageName, ClassLoader classLoader) {
        // 执行具体 Hook 逻辑
    }
}

2. 核心 Hook 语法对照

目标操作传统 Xposed 写法LibXposed 102 现代写法
查找并 Hook 方法XposedHelpers.findAndHookMethod("类名", cl, "方法", argTypes..., callback)Method m = Clazz.class.getDeclaredMethod("方法", argTypes...);hook(m).intercept(chain -> { ... });
执行原方法默认直接执行;调用 param.getResult()Object result = chain.proceed();
修改参数并调用param.args[0] = newVal;Object result = chain.proceed(new Object[]{ newVal, ... });
拦截并替换返回值param.setResult(customVal);直接返回自定义值(不调用 chain.proceed()):hook(m).intercept(chain -> customVal);
获取入参param.args[i]chain.getArg(i)chain.getArgs()
获取 this 实例param.thisObjectchain.getThisObject()
Hook 构造函数findAndHookConstructor(...)Constructor<?> ctor = ...;hook(ctor).intercept(chain -> ...);
Hook 静态代码块传统不支持标准 APIhookClassInitializer(TargetClass.class).intercept(...)

三、高频 Hook 场景与性能深度优化模式

针对高频调用(如 isEnabledView 绘制、触摸派发)的黄金优化法则:

  1. 零开销快速路径(嗅探直通): 若方法是状态查询方法(如 isEnabled()isLoaded()),先调用轻量级的原生字段读取 chain.proceed()。如果真实状态本身即为假,直接返回假,跳过所有后续逻辑与堆栈检查。

  2. Android 14+ (API 34+) 采用 StackWalker 惰性遍历: 传统 new Throwable().getStackTrace() 会导致全线程栈深度展开(Native Unwind)和几百个字符串分配,极易引起 GC 掉帧。 使用 Java 9 / Android 14+ 的 java.lang.StackWalker,按需逐层扫描,零全栈分配。

  3. Android < 34 动态栈定位(杜绝硬编码): 仅单次执行 new Throwable().getStackTrace(),向下遍历查找目标方法所在的系统类(如 AccessibilityManager),紧随其后的栈帧即为真实调用者。绝不硬编码 [3][4],保证跨 LSPosed 版本稳定运行。

性能优化示范代码:

// 检查 Android 14+ StackWalker
private static final boolean HAS_STACK_WALKER;
static {
    boolean has;
    try {
        Class.forName("java.lang.StackWalker");
        has = (Build.VERSION.SDK_INT >= 34);
    } catch (Throwable t) {
        has = false;
    }
    HAS_STACK_WALKER = has;
}

// 高频方法 Hook 示范
Method isEnabled = AccessibilityManager.class.getDeclaredMethod("isEnabled");
hook(isEnabled).intercept(chain -> {
    Object real = chain.proceed();
    if (Boolean.FALSE.equals(real)) {
        return false; // 系统本就是关的,零开销直通返回
    }
    return isCallerWhitelisted() ? real : false;
});

private static boolean isCallerWhitelisted() {
    if (HAS_STACK_WALKER) {
        try {
            return Api34StackWalker.check();
        } catch (Throwable ignored) {}
    }
    return checkLegacy();
}

@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
private static final class Api34StackWalker {
    private static final StackWalker WALKER = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);

    static boolean check() {
        return Boolean.TRUE.equals(WALKER.walk(frames -> {
            boolean foundTarget = false;
            var it = frames.iterator();
            while (it.hasNext()) {
                var f = it.next();
                if ("android.view.accessibility.AccessibilityManager".equals(f.getClassName())) {
                    foundTarget = true;
                } else if (foundTarget) {
                    return isPackageAllowed(f.getClassName());
                }
            }
            return false;
        }));
    }
}

四、升级常见陷阱与排查清单

  1. assets/xposed_init 是否仍需保留?
    • 现代 API 102 仅读取 META-INF/xposed/java_init.list。如果保留 assets/xposed_init,旧版框架可能尝试使用传统反射加载它而报错,推荐直接移除或保持为空。
  2. compileSdk 与 Android SDK 平台
    • 建议将 compileSdktargetSdk 升级至 Android 33 或 34,以便顺利使用现代接口和 Java 11/17 语言特性。
  3. Gradle 兼容性
    • 如果构建环境使用的是 JDK 17 / 21,必须确保 Gradle Wrapper 升级至 7.4+(推荐 7.5.18.x),AGP 升级至 7.3+
  4. 验证模块识别
    • 使用解压工具查看最终 APK 根目录,必须包含:
      • META-INF/xposed/module.prop
      • META-INF/xposed/java_init.list
      • META-INF/xposed/scope.list

Related Skills

steipete/notion

Notion CLI/API for pages, Markdown content, data sources, files, comments, search, Workers, and raw API calls.

community

affaan-m/seo

Audit, plan, and implement SEO improvements across technical SEO, on-page optimization, structured data, Core Web Vitals, and content strategy. Use when the user wants better search visibility, SEO remediation, schema markup, sitemap/robots work, or keyword mapping.

community

affaan-m/brand-voice

Build a source-derived writing style profile from real posts, essays, launch notes, docs, or site copy, then reuse that profile across content, outreach, and social workflows. Use when the user wants voice consistency without generic AI writing tropes.

community

affaan-m/crosspost

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

community

affaan-m/x-api

X/Twitter API integration for posting tweets, threads, reading timelines, search, and analytics. Covers OAuth auth patterns, rate limits, and platform-native content posting. Use when the user wants to interact with X programmatically.

community

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

community