Skip to content

Commit

Permalink
add getFragments
Browse files Browse the repository at this point in the history
  • Loading branch information
GangJust authored and 5ec1cff committed Nov 10, 2024
1 parent 18ad352 commit 64a9e4b
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ private synchronized void initializeStetho(Context context) throws InterruptedEx
try {
scope.defineProperty("activities", null, Utils.class.getDeclaredMethod("getActivities", ScriptableObject.class), null, ScriptableObject.READONLY);
scope.defineProperty("current", null, Utils.class.getDeclaredMethod("getCurrentActivity", ScriptableObject.class), null, ScriptableObject.READONLY);
scope.defineProperty("fragments", null, Utils.class.getDeclaredMethod("getFragments", ScriptableObject.class), null, ScriptableObject.READONLY);
ScriptableObject.defineClass(scope, HookFunction.class);
ScriptableObject.defineClass(scope, UnhookFunction.class);
ScriptableObject.defineClass(scope, HookParam.class);
Expand Down
70 changes: 69 additions & 1 deletion app/src/main/java/io/github/a13e300/tools/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ScriptableObject;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import de.robv.android.xposed.XposedHelpers;
import io.github.a13e300.tools.node.Node;

public class Utils {
public static ActivityThread getActivityThread() {
Expand All @@ -31,11 +36,74 @@ public static Activity[] getActivities(ScriptableObject ignore) {
public static Activity getCurrentActivity(ScriptableObject ignore) {
var activities = (Map<?, ?>) XposedHelpers.getObjectField(getActivityThread(), "mActivities");
var acr = activities.values().stream().filter(v ->
!XposedHelpers.getBooleanField(v, "paused")
!XposedHelpers.getBooleanField(v, "paused")
).findFirst();
return acr.map(o -> (Activity) XposedHelpers.getObjectField(o, "activity")).orElse(null);
}

public static Object getSupportFragmentManager(ScriptableObject ignore) {
var currentActivity = getCurrentActivity(ignore);
if (currentActivity == null) return null;

var clazz = XposedHelpers.findClass("androidx.fragment.app.FragmentActivity", currentActivity.getClassLoader());
Method method = XposedHelpers.findMethodExactIfExists(clazz, "getSupportFragmentManager");
try {
return method.invoke(currentActivity);
} catch (InvocationTargetException | IllegalAccessException e) {
return null;
}
}

public static ArrayList<Node<Object>> getFragments(ScriptableObject ignore) {
Object manager = getSupportFragmentManager(ignore);
if (manager == null) return null;

var rootNodes = new ArrayList<Node<Object>>();
var nodeStack = new ArrayList<List<Node<Object>>>();
nodeStack.add(rootNodes);

var fragmentMgrStack = new ArrayList<>();
fragmentMgrStack.add(manager);

var loader = manager.getClass().getClassLoader();
var fragmentMgrClazz = XposedHelpers.findClass("androidx.fragment.app.FragmentManager", loader);
var fragmentClazz = XposedHelpers.findClass("androidx.fragment.app.Fragment", loader);

while (!fragmentMgrStack.isEmpty()) {
Object currentManager = fragmentMgrStack.remove(fragmentMgrStack.size() - 1);
List<Node<Object>> currentNode = nodeStack.remove(nodeStack.size() - 1);
// Object currentManager = fragmentMgrStack.remove(0);
// List<Node<Object>> currentNode = nodeStack.remove(0);

try {
Method method = XposedHelpers.findMethodExactIfExists(fragmentMgrClazz, "getFragments");
var fragments = (List<?>) method.invoke(currentManager);

for (int i = 0; i < fragments.size(); i++) {
Object fragment = fragments.get(i);

var childNode = new Node<>();
childNode.index = i;
childNode.value = fragment;
childNode.children = new ArrayList<>();
currentNode.add(childNode);

Method childMethod = XposedHelpers.findMethodExactIfExists(fragmentClazz, "getChildFragmentManager");
Object childManager = childMethod.invoke(fragment);
if (childManager == null) continue;

fragmentMgrStack.add(childManager);
nodeStack.add(childNode.children);
}

} catch (InvocationTargetException | IllegalAccessException e) {
// Ignore: the exception and continue with the next fragment
}
}

return rootNodes;
}

public static String getStackTrace(boolean hide) {
var sb = new StringBuilder();
var st = Thread.currentThread().getStackTrace();
Expand Down
27 changes: 27 additions & 0 deletions app/src/main/java/io/github/a13e300/tools/node/Node.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.github.a13e300.tools.node;

import androidx.annotation.NonNull;

import java.util.List;

public class Node<T> {
public int index;
public T value;
public List<Node<T>> children;

public String getValueName() {
return value == null ? "" : value.getClass().getName();
}

@NonNull
@Override
public String toString() {
// json format
return "{"
+ "\"index\":" + index
+ ",\"name\":\"" + getValueName() + "\""
+ ",\"value\":\"" + value + "\""
+ ",\"children\":" + children
+ "}";
}
}

0 comments on commit 64a9e4b

Please sign in to comment.