-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathview_dump.js
92 lines (82 loc) · 2.91 KB
/
view_dump.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
const Activity = Java.use('android.app.Activity')
const Android_R_Id = Java.use('android.R$id')
const HashMap = Java.use('java.util.HashMap')
const View = Java.use('android.view.View')
const ViewGroup = Java.use('android.view.ViewGroup')
const Stack = Java.use('java.util.Stack')
const ActivityThread = Java.use('android.app.ActivityThread')
const ActivityManager = Java.use('android.app.ActivityManager')
const ActivityManager_RunningTaskInfo = Java.use('android.app.ActivityManager$RunningTaskInfo')
class HashMapBuilder {
static build(key, value) {
const map = HashMap.$new()
map.put('key', key)
map.put('value', value)
return map
}
}
function logViewHierarchyActivity(activity) {
activity = Java.cast(activity, Activity)
logViewHierarchy(activity.findViewById(Android_R_Id.content.value))
}
function resolveIdToName(resources, view) {
if (resources === null) return '';
try {
return ' / ' + resources.getResourceEntryName(view.getId())
} catch (_) {
return ''
}
}
function logViewHierarchy(root) {
root = Java.cast(root, View)
let resources = root.getResources()
let stack = Stack.$new()
stack.push(HashMapBuilder.build('', root))
let output = []
while (!stack.empty()) {
let map = stack.pop()
map = Java.cast(map, HashMap)
let key = map.get('key')
let view = map.get('value')
view = Java.cast(view, View)
let isLastOnLevel = stack.empty()
if (!isLastOnLevel) {
let i = stack.peek()
i = Java.cast(i, HashMap)
isLastOnLevel = key == i.get('key')
}
let graphics = '' + key + (isLastOnLevel ? '└── ' : '├── ')
let className = view.getClass().getSimpleName()
let line = graphics + className + ' id=' + view.getId() + resolveIdToName(resources, view)
output.push(line)
if (ViewGroup.class.isInstance(view)) {
let viewGroup = Java.cast(view, ViewGroup)
for (let i = 0; i < viewGroup.getChildCount(); i++) {
stack.push(HashMapBuilder.build(key + (isLastOnLevel ? ' ' : '│ '), viewGroup.getChildAt(i)))
}
}
}
console.log(output.join('\n'))
}
function getFrontmostActivity(callback) {
let am = ActivityThread.currentApplication().getSystemService('activity')
am = Java.cast(am, ActivityManager)
let taskInfo = am.getRunningTasks(1).get(0)
taskInfo = Java.cast(taskInfo, ActivityManager_RunningTaskInfo)
let activityName = taskInfo.topActivity.value.getClassName()
let find = false
Java.choose(activityName, {
onMatch: (instance) => {
if (!find) {
callback(instance)
find = true
}
},
onComplete: () => {}
})
}
Java.perform(() => {
getFrontmostActivity(function(instance) {
logViewHierarchyActivity(instance);
})
})