吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 116|回复: 3
收起左侧

[经验求助] Android7.0 xposed hook到activity对象如何保存该对象为全局变量供外部类调用

[复制链接]
tyc600 发表于 2024-11-15 08:02
200吾爱币
本帖最后由 tyc600 于 2024-11-15 08:18 编辑

如下图所示我已经成功hook到activity后注册了一个动态广播来响应外部类的调用。

代码1:hook到activity对象
[Java] 纯文本查看 复制代码
import android.app.Activity;
import android.os.Bundle;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;

public class MyRecHook {
    public MyRecHook() {
        XposedBridge.log("MyHook start MyRecHook");
        XposedHelpers.findAndHookMethod(Activity.class, "onCreate", new Object[]{Bundle.class, new MyRecHook$1(this)});
    }
}

代码2:内部类,注册动态广播
[Java] 纯文本查看 复制代码
import android.app.Activity;
import android.content.IntentFilter;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;

class MyRecHook$1 extends XC_MethodHook {
    final MyRecHook this$0;

    MyRecHook$1(MyRecHook myRecHook) {
        this.this$0 = myRecHook;
    }

    protected void beforeHookedMethod(XC_MethodHook.MethodHookParam methodHookParam) throws Throwable {
        super.beforeHookedMethod(methodHookParam);
    }

    protected void afterHookedMethod(XC_MethodHook.MethodHookParam methodHookParam) throws Throwable {
        super.afterHookedMethod(methodHookParam);
        try {
            XposedBridge.log("MyHook start hook");
            ((Activity) methodHookParam.thisObject).registerReceiver(new MyRecHook$1$1(this, methodHookParam), new IntentFilter("my.screen.action"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

代码3:内部类,响应外部对activity的调用
[Java] 纯文本查看 复制代码
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import github.xposed.MyRecHook;

class MyRecHook$1$1 extends BroadcastReceiver {
    final MyRecHook.1 this$1;
    final XC_MethodHook.MethodHookParam val$param;

    MyRecHook$1$1(MyRecHook.1 r1, XC_MethodHook.MethodHookParam methodHookParam) {
        this.this$1 = r1;
        this.val$param = methodHookParam;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        int intExtra = intent.getIntExtra("screen", 0);
        XposedBridge.log(context.getPackageName() + "收到屏幕旋转事件" + intExtra);
        ((Activity) this.val$param.thisObject).setRequestedOrientation(intExtra);
    }
}

为了避免频繁的注册动态广播【因为实际上这个activity只在部分需要的场合才需要被调用,显然每次都hook到对象都注册动态广播对系统资源造成负担】,后来我尝试将获取到的activity对象保存为全局变量,
[Java] 纯文本查看 复制代码
import android.app.Activity;
import android.content.IntentFilter;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;

class MyRecHook$1 extends XC_MethodHook {
    final MyRecHook this$0;

    MyRecHook$1(MyRecHook myRecHook) {
        this.this$0 = myRecHook;
    }

    protected void beforeHookedMethod(XC_MethodHook.MethodHookParam methodHookParam) throws Throwable {
        super.beforeHookedMethod(methodHookParam);
    }

    protected void afterHookedMethod(XC_MethodHook.MethodHookParam methodHookParam) throws Throwable {
        super.afterHookedMethod(methodHookParam);
        try {
            XposedBridge.log("MyHook start hook");
            new IntentFilter("my.screen.action");
【★★★修改了此行★★★】AppEnv.j().setActivity((Activity) methodHookParam.thisObject);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

用于存储activity对象,并响应外部调用类如下,但是运行后报错如下【[Error: ui.requestScreenOrientation(0): Attempt to invoke virtual method 'void android.app.Activity.setRequestedOrientation(int)' on a null object reference],】,如何保存activity为全局变量还请路过的大虾指点一下。
[Java] 纯文本查看 复制代码
import android.app.Activity;
import java.lang.ref.WeakReference;

public class AppEnv {
    private static final AppEnv o = new AppEnv$1();
    private WeakReference<Activity> myactivity;

    public static AppEnv j() {
        return o;
    }

    public final void setRequestedOrientation(int i) {
        WeakReference<Activity> weakReference = this.myactivity;
        if (weakReference != null) {
            weakReference.get().setRequestedOrientation(i);
        }
    }

    public final void setActivity(Activity activity) {
        WeakReference<Activity> weakReference = this.myactivity;
        if (weakReference != null) {
            weakReference.clear();
        }
        this.myactivity = new WeakReference<>(activity);
    }
}

内部类赋值操作如下:
[Java] 纯文本查看 复制代码
import android.app.Activity;

class AppEnv$1 extends AppEnv {
    AppEnv$1() {
        setActivity((Activity) null);
    }
}

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

linglingsan 发表于 2024-11-16 09:45
试一下扔给国内的大模型来帮你分析一下呢,以下是我扔给大模型给的回答;
  • 使用弱引用(WeakReference)保存 Activity
    • 弱引用允许垃圾回收器在对象不再被强引用时回收它,这有助于避免因 Activity 被销毁而导致的内存泄漏问题。
    • 在 Xposed 模块中,修改代码如下:
    import android.app.Activity;import android.content.Intent;import android.content.IntentFilter;import android.content.res.Configuration;import android.util.Log;import android.view.WindowManager;import de.robv.android.xposed.IXposedHookLoadPackage;import de.robv.android.xposed.XC_MethodHook;import de.robv.android.xposed.XposedBridge;import de.robv.android.xposed.XposedHelpers;import de.robv.android.xposed.callbacks.XC_LoadPackage;import java.lang.ref.WeakReference;public class HookModule implements IXposedHookLoadPackage {    private static WeakReference<Activity> activityWeakReference;    @Override    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {        if ("目标应用包名".equals(lpparam.packageName)) {            XposedHelpers.findAndHookMethod(Activity.class, "onCreate", Bundle.class, new XC_MethodHook() {                @Override                protected void afterHookedMethod(MethodHookParam param) throws Throwable {                    super.afterHookedMethod(param);                    Activity activity = (Activity) param.thisObject;                    activityWeakReference = new WeakReference<>(activity);                    Log.d("HookModule", "Activity onCreate: " + activity);                    // 注册广播接收者                    registerBroadcastReceiver(activity);                }            });        }    }    private void registerBroadcastReceiver(Activity activity) {        BroadcastReceiver receiver = new BroadcastReceiver() {            @Override            public void onReceive(Context context, Intent intent) {                if (intent.getAction().equals("your_action")) {                    Log.d("HookModule", "Received broadcast in Activity: " + activityWeakReference.get());                    if (activityWeakReference.get()!= null) {                        int orientation = intent.getIntExtra("orientation", Configuration.ORIENTATION_UNDEFINED);                        activityWeakReference.get().setRequestedOrientation(orientation);                    }                }            }        };        IntentFilter filter = new IntentFilter("your_action");        activity.registerReceiver(receiver, filter);    }}



  • 在广播接收者中处理 Activity 可能为空的情况
    • 在广播接收者的 onReceive 方法中,每次使用 activityWeakReference 之前,都要检查它是否为空。
    • 如果为空,可能表示 Activity 已经被销毁,此时不执行与 Activity 相关的操作,或者根据需求进行其他处理,例如重新获取 Activity(如果可能的话)或记录错误信息。

linglingsan 发表于 2024-11-16 09:49
试一下扔给国内的大模型来帮你分析一下呢,以下是我扔给大模型给的回答;
  • 使用弱引用(WeakReference)保存 Activity
    • 弱引用允许垃圾回收器在对象不再被强引用时回收它,这有助于避免因 Activity 被销毁而导致的内存泄漏问题。
    • 在 Xposed 模块中,修改代码如下:
[Java] 纯文本查看 复制代码
java
import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.util.Log;
import android.view.WindowManager;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

import java.lang.ref.WeakReference;

public class HookModule implements IXposedHookLoadPackage {

private static WeakReference<Activity> activityWeakReference;

@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
if ("目标应用包名".equals(lpparam.packageName)) {
XposedHelpers.findAndHookMethod(Activity.class, "onCreate", Bundle.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Activity activity = (Activity) param.thisObject;
activityWeakReference = new WeakReference<>(activity);
Log.d("HookModule", "Activity onCreate: " + activity);

// 注册广播接收者
registerBroadcastReceiver(activity);
}
});
}
}

private void registerBroadcastReceiver(Activity activity) {
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("your_action")) {
Log.d("HookModule", "Received broadcast in Activity: " + activityWeakReference.get());
if (activityWeakReference.get()!= null) {
int orientation = intent.getIntExtra("orientation", Configuration.ORIENTATION_UNDEFINED);
activityWeakReference.get().setRequestedOrientation(orientation);
}
}
}
};
IntentFilter filter = new IntentFilter("your_action");
activity.registerReceiver(receiver, filter);
}
}



  • 在广播接收者中处理 Activity 可能为空的情况
    • 在广播接收者的 onReceive 方法中,每次使用 activityWeakReference 之前,都要检查它是否为空。
    • 如果为空,可能表示 Activity 已经被销毁,此时不执行与 Activity 相关的操作,或者根据需求进行其他处理,例如重新获取 Activity(如果可能的话)或记录错误信息。

 楼主| tyc600 发表于 2024-11-16 18:33
linglingsan 发表于 2024-11-16 09:49
试一下扔给国内的大模型来帮你分析一下呢,以下是我扔给大模型给的回答;
  • 使用弱引用(WeakReference) ...

  • 谢谢回答,但是大模型的回答好像和我一开始已经超过的方式一样:使用了动态广播来响应外部调用,我要求回避这种方式。有没有更贴合要求的方案?
    您需要登录后才可以回帖 登录 | 注册[Register]

    本版积分规则

    返回列表

    RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

    GMT+8, 2024-11-24 14:26

    Powered by Discuz!

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表