You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android使用类反射实现无Context调用Toast的AndHook场景问题求解

解决方案

原有代码错误原因

你编写的Class.forName("com.example.activity.MainActivity").this属于语法错误:

  • Class.forName()返回的是类的描述对象Class<?>,不是MainActivity的运行时实例
  • 类名.this是Java内部类引用外部类实例的专属语法,不能直接作用于反射拿到的Class对象,因此会直接编译失败

方案1:使用全局Application Context(优先推荐)

这个方案不需要依赖任何业务侧的Activity类,通用性最强,也不会出现内存泄漏风险,核心通过系统API反射拿到全局应用上下文:

第一步:新增获取全局Context的工具方法

private static Context getApplicationContext() throws Exception {
    Class<?> activityThreadCls = Class.forName("android.app.ActivityThread");
    // 获取当前ActivityThread实例
    Object activityThread = activityThreadCls.getDeclaredMethod("currentActivityThread").invoke(null);
    // 获取Application实例,本身就是Context子类
    return (Context) activityThreadCls.getDeclaredMethod("getApplication").invoke(activityThread);
}

第二步:修改Hook逻辑,注意Toast要在主线程执行

@HookHelper.Hook(clazz = BitmapFactory.class)
private static Bitmap decodeFile(BitmapFactory thiz, String path) {
    try {
        Context appContext = getApplicationContext();
        // 切主线程弹Toast,避免子线程调用时报错
        appContext.getMainLooper().runWithScissors(() -> 
            Toast.makeText(appContext, "Bitmap.decodeFile(" + path + ")", Toast.LENGTH_LONG).show(), 
        0);
    } catch (Exception e) {
        // 异常捕获避免影响原方法执行
        e.printStackTrace();
    }
    return (Bitmap) HookHelper.invokeObjectOrigin(thiz, path);
}

方案2:缓存Activity实例(仅在需要Activity上下文时使用)

如果你必须使用Activity作为Context,可以提前Hook目标Activity的生命周期方法缓存实例,注意用弱引用避免内存泄漏:

第一步:定义弱引用存储Activity实例

private static WeakReference<Activity> sCachedActivity = new WeakReference<>(null);

第二步:Hook MainActivity的onCreate方法缓存实例

@HookHelper.Hook(clazz = "com.example.activity.MainActivity")
private static void onCreate(Activity thiz, Bundle savedInstanceState) {
    sCachedActivity = new WeakReference<>(thiz);
    // 调用原onCreate逻辑,不能省略
    HookHelper.invokeVoidOrigin(thiz, savedInstanceState);
}

第三步:在decodeFile中使用缓存的Activity

@HookHelper.Hook(clazz = BitmapFactory.class)
private static Bitmap decodeFile(BitmapFactory thiz, String path) {
    Activity targetActivity = sCachedActivity.get();
    if (targetActivity != null) {
        targetActivity.runOnUiThread(() -> 
            Toast.makeText(targetActivity, "Bitmap.decodeFile(" + path + ")", Toast.LENGTH_LONG).show()
        );
    }
    return (Bitmap) HookHelper.invokeObjectOrigin(thiz, path);
}

该方案缺点是如果目标Activity被销毁,缓存会为空导致无法弹出Toast,非必要场景优先选择方案1。


内容的提问来源于stack exchange,提问作者Amin Guermazi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 03:21:00