在线程中通过 xposed 运行 以挂钩方法显示对话框
Show dialog in hooked method by xposed running in thread
我尝试在 xposed 的挂钩方法中显示 AlertDialog。
问题是方法在一个线程中是运行,这个线程在一个线程中是运行,等等...
例如:
Activity -> 线程 -> 线程 -> ... -> 函数
有没有办法显示我的 AlertDialog ?我有Context,但是hook的函数不在主线程,没用
编辑(一些代码):
public class Xposed implements IXposedHookLoadPackage {
private Context ctx;
private Queue<String> queue = new LinkedList<>();
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("xxx.xxx.xxx")) {
return;
}
// Here I get the context from the static class extending Application
findAndHookMethod("xxx.xxx.xxx", lpparam.classLoader, "attachBaseContext", Context.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("context modified");
ctx = (Context) param.args[0];
}
});
findAndHookMethod("com.xxx.xxx.xxx", lpparam.classLoader, "e", "com.xxx.xxx.xxx", String.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(final MethodHookParam param) throws Throwable {
if (!(param.args[1]).equals("xxxxxxxxxxxxxx")) {
return ;
}
XposedBridge.log("New element detected detected");
Object param = param.args[0];
Object info = callMethod(param, "q");
// Here, I want to show my alertdialog
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
}
}
};
// I get the classic error like what I can't modify the ui
// in a thread that has not called Looper.prepare()
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setMessage("Are you sure ?")
.setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener)
.show();
}
});
}
谢谢
如果您是 运行 此代码在 activity 或片段中,则可以使用 runOnUiThread(runnable)
方法执行此操作。
由于您无权访问 activity,您可以获得主循环器,然后 post ui 相关任务。
注意:当您需要在 xposed 模块中获取当前应用程序上下文时,您不需要像 attachBaseContext
那样挂钩任何东西。 xposed api 提供了一个获取当前应用程序上下文的辅助方法 AndroidAppHelper.currentApplication()
.
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
//Do ui related stuff in here
AlertDialog.Builder builder = new AlertDialog.Builder(AndroidAppHelper.currentApplication());
builder.setMessage("Are you sure ?")
.setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener)
.show();
}
});
Looper.getMainLooper()
文档:http://developer.android.com/reference/android/os/Looper.html#getMainLooper()
Handler.post
文档:
http://developer.android.com/reference/android/os/Handler.html#post(java.lang.Runnable)
AndroidAppHelper.currentApplication()
源代码:
https://github.com/rovo89/XposedBridge/blob/art/src/android/app/AndroidAppHelper.java#L143-L145
您始终可以保留当前 Activity (android.app.Instrumentation.newActivity) 的引用。它是这样的:
Class<?> instrumentation = XposedHelpers.findClass(
"android.app.Instrumentation", lpparam.classLoader);
Method method = instrumentation.getMethod("newActivity",
ClassLoader.class, String.class, Intent.class);
XposedBridge.hookMethod(method, iHook);
在这种情况下,ihook 将是您的一个挂钩,它只静态存储当前 Activity,因此您可以从任何地方调用 runOnUiThread:
public class ActivityHook extends XC_MethodHook{
/* Assure latest read of write */
private static volatile Activity _currentActivity = null;
public static Activity getCurrentActivity() {
return _currentActivity;
}
@Override
protected Object afterHookedMethod(MethodHookParam param)
throws Throwable {
_currentActivity = (Activity) param.getResult();
}
}
那么您将可以在任何地方进行:
ActivityHook.getCurrentActivity().runOnUiThread(...);
祝你好运!
我尝试在 xposed 的挂钩方法中显示 AlertDialog。 问题是方法在一个线程中是运行,这个线程在一个线程中是运行,等等...
例如: Activity -> 线程 -> 线程 -> ... -> 函数
有没有办法显示我的 AlertDialog ?我有Context,但是hook的函数不在主线程,没用
编辑(一些代码):
public class Xposed implements IXposedHookLoadPackage {
private Context ctx;
private Queue<String> queue = new LinkedList<>();
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("xxx.xxx.xxx")) {
return;
}
// Here I get the context from the static class extending Application
findAndHookMethod("xxx.xxx.xxx", lpparam.classLoader, "attachBaseContext", Context.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("context modified");
ctx = (Context) param.args[0];
}
});
findAndHookMethod("com.xxx.xxx.xxx", lpparam.classLoader, "e", "com.xxx.xxx.xxx", String.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(final MethodHookParam param) throws Throwable {
if (!(param.args[1]).equals("xxxxxxxxxxxxxx")) {
return ;
}
XposedBridge.log("New element detected detected");
Object param = param.args[0];
Object info = callMethod(param, "q");
// Here, I want to show my alertdialog
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
}
}
};
// I get the classic error like what I can't modify the ui
// in a thread that has not called Looper.prepare()
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setMessage("Are you sure ?")
.setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener)
.show();
}
});
}
谢谢
如果您是 运行 此代码在 activity 或片段中,则可以使用 runOnUiThread(runnable)
方法执行此操作。
由于您无权访问 activity,您可以获得主循环器,然后 post ui 相关任务。
注意:当您需要在 xposed 模块中获取当前应用程序上下文时,您不需要像 attachBaseContext
那样挂钩任何东西。 xposed api 提供了一个获取当前应用程序上下文的辅助方法 AndroidAppHelper.currentApplication()
.
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
//Do ui related stuff in here
AlertDialog.Builder builder = new AlertDialog.Builder(AndroidAppHelper.currentApplication());
builder.setMessage("Are you sure ?")
.setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener)
.show();
}
});
Looper.getMainLooper()
文档:http://developer.android.com/reference/android/os/Looper.html#getMainLooper()
Handler.post
文档:
http://developer.android.com/reference/android/os/Handler.html#post(java.lang.Runnable)
AndroidAppHelper.currentApplication()
源代码:
https://github.com/rovo89/XposedBridge/blob/art/src/android/app/AndroidAppHelper.java#L143-L145
您始终可以保留当前 Activity (android.app.Instrumentation.newActivity) 的引用。它是这样的:
Class<?> instrumentation = XposedHelpers.findClass(
"android.app.Instrumentation", lpparam.classLoader);
Method method = instrumentation.getMethod("newActivity",
ClassLoader.class, String.class, Intent.class);
XposedBridge.hookMethod(method, iHook);
在这种情况下,ihook 将是您的一个挂钩,它只静态存储当前 Activity,因此您可以从任何地方调用 runOnUiThread:
public class ActivityHook extends XC_MethodHook{
/* Assure latest read of write */
private static volatile Activity _currentActivity = null;
public static Activity getCurrentActivity() {
return _currentActivity;
}
@Override
protected Object afterHookedMethod(MethodHookParam param)
throws Throwable {
_currentActivity = (Activity) param.getResult();
}
}
那么您将可以在任何地方进行:
ActivityHook.getCurrentActivity().runOnUiThread(...);
祝你好运!