Android7.0 xposed hook到activity对象如何保存该对象为全局变量供外部类调用
本帖最后由 tyc600 于 2024-11-15 08:18 编辑如下图所示我已经成功hook到activity后注册了一个动态广播来响应外部类的调用。
代码1:hook到activity对象
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:内部类,注册动态广播
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的调用
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对象保存为全局变量,
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对象,并响应外部调用类如下,但是运行后报错如下【,】,如何保存activity为全局变量还请路过的大虾指点一下。
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);
}
}
内部类赋值操作如下:
import android.app.Activity;
class AppEnv$1 extends AppEnv {
AppEnv$1() {
setActivity((Activity) null);
}
}
试一下扔给国内的大模型来帮你分析一下呢,以下是我扔给大模型给的回答;
[*]使用弱引用(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(如果可能的话)或记录错误信息。
试一下扔给国内的大模型来帮你分析一下呢,以下是我扔给大模型给的回答;
[*]使用弱引用(WeakReference)保存 Activity
[*]弱引用允许垃圾回收器在对象不再被强引用时回收它,这有助于避免因 Activity 被销毁而导致的内存泄漏问题。
[*]在 Xposed 模块中,修改代码如下:
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(如果可能的话)或记录错误信息。
linglingsan 发表于 2024-11-16 09:49
试一下扔给国内的大模型来帮你分析一下呢,以下是我扔给大模型给的回答;
[*]使用弱引用(WeakReference) ...
谢谢回答,但是大模型的回答好像和我一开始已经超过的方式一样:使用了动态广播来响应外部调用,我要求回避这种方式。有没有更贴合要求的方案?
页:
[1]