currentactivity 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -2
- package/build/index.js +347 -16
- package/package.json +7 -5
- package/src/index.ts +417 -44
package/README.md
CHANGED
|
@@ -21,14 +21,107 @@ brew install android-platform-tools
|
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## Usage
|
|
24
|
-
|
|
24
|
+
### Show current activity's name
|
|
25
25
|
```
|
|
26
|
-
currentactivity
|
|
26
|
+
currentactivity -a
|
|
27
|
+
```
|
|
28
|
+
output example
|
|
29
|
+
```
|
|
30
|
+
com.tencent.mm/com.tencent.mm.ui.LauncherUI
|
|
31
|
+
```
|
|
32
|
+
### Show current activity's name in real time
|
|
33
|
+
```
|
|
34
|
+
currentactivity -a -w
|
|
35
|
+
```
|
|
36
|
+
### Show current activity's stack
|
|
37
|
+
```
|
|
38
|
+
currentactivity -s
|
|
39
|
+
```
|
|
40
|
+
output example
|
|
41
|
+
```
|
|
42
|
+
╔═══════════════════════════════════════════════════════════════╗
|
|
43
|
+
║ com.tencent.mm/.plugin.webview.ui.tools.WebViewUI ║
|
|
44
|
+
╟───────────────────────────────────────────────────────────────╢
|
|
45
|
+
║ com.tencent.mm/.plugin.brandservice.ui.timeline.BizTimeLineUI ║
|
|
46
|
+
╟───────────────────────────────────────────────────────────────╢
|
|
47
|
+
║ com.tencent.mm/.ui.LauncherUI ║
|
|
48
|
+
╚═══════════════════════════════════════════════════════════════╝
|
|
49
|
+
```
|
|
50
|
+
### Show current activity's fragments
|
|
51
|
+
```
|
|
52
|
+
currentactivity -f
|
|
53
|
+
```
|
|
54
|
+
output example
|
|
55
|
+
```
|
|
56
|
+
╔═════════════════════╤════════════════════════════════════════════════════════════════════════════════════════╗
|
|
57
|
+
║ activity │ com.tencent.mm/.ui.LauncherUI ║
|
|
58
|
+
╟─────────────────────┼────────────────────────────────────────────────────────────────────────────────────────╢
|
|
59
|
+
║ framework fragments │ └─ #0: ad{d7a01e4 #0 androidx.lifecycle.LifecycleDispatcher.report_fragment_tag} ║
|
|
60
|
+
║ │ ║
|
|
61
|
+
╟─────────────────────┼────────────────────────────────────────────────────────────────────────────────────────╢
|
|
62
|
+
║ androidx fragments │ ├─ MainUI{403dae2} (f74366df-8aa6-4cc2-b702-9b609620a895 id=0x7f092d4a) ║
|
|
63
|
+
║ │ ├─ MvvmAddressUIFragment{ef218ab} (fbc006c7-be02-47fa-be40-952dcc42293b id=0x7f092d4a) ║
|
|
64
|
+
║ │ ├─ MoreTabUI{dcc2cc6} (106e8aa9-d6da-48f2-b870-d0a95882d33f id=0x7f092d4a) ║
|
|
65
|
+
║ │ ├─ ChattingUIFragment{cad8b94} (3fccfb2c-fc14-4b3c-8b91-ba9d3e102759 id=0x7f0909d7) ║
|
|
66
|
+
║ │ └─ FindMoreFriendsUI{fdacb08} (b1b80b1b-ea6f-470b-b16c-cd76c853e8ad id=0x7f092d4a) ║
|
|
67
|
+
║ │ ║
|
|
68
|
+
╚═════════════════════╧════════════════════════════════════════════════════════════════════════════════════════╝
|
|
69
|
+
```
|
|
70
|
+
### Show all the info about the current activity
|
|
71
|
+
```
|
|
72
|
+
currentactivity -A
|
|
73
|
+
```
|
|
74
|
+
output example
|
|
75
|
+
```
|
|
76
|
+
╔═════════════════════════════════════════════╗
|
|
77
|
+
║ current window ║
|
|
78
|
+
╟─────────────────────────────────────────────╢
|
|
79
|
+
║ com.tencent.mm/com.tencent.mm.ui.LauncherUI ║
|
|
80
|
+
╚═════════════════════════════════════════════╝
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
╔═══════════════════════════════╗
|
|
85
|
+
║ activity stack ║
|
|
86
|
+
╟───────────────────────────────╢
|
|
87
|
+
║ com.tencent.mm/.ui.LauncherUI ║
|
|
88
|
+
╚═══════════════════════════════╝
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
╔══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
|
|
93
|
+
║ fragments ║
|
|
94
|
+
╟─────────────────────┬────────────────────────────────────────────────────────────────────────────────────────╢
|
|
95
|
+
║ framework fragments │ └─ #0: ad{d7a01e4 #0 androidx.lifecycle.LifecycleDispatcher.report_fragment_tag} ║
|
|
96
|
+
║ │ ║
|
|
97
|
+
╟─────────────────────┼────────────────────────────────────────────────────────────────────────────────────────╢
|
|
98
|
+
║ androidx fragments │ ├─ MainUI{403dae2} (f74366df-8aa6-4cc2-b702-9b609620a895 id=0x7f092d4a) ║
|
|
99
|
+
║ │ ├─ MvvmAddressUIFragment{ef218ab} (fbc006c7-be02-47fa-be40-952dcc42293b id=0x7f092d4a) ║
|
|
100
|
+
║ │ ├─ MoreTabUI{dcc2cc6} (106e8aa9-d6da-48f2-b870-d0a95882d33f id=0x7f092d4a) ║
|
|
101
|
+
║ │ ├─ ChattingUIFragment{cad8b94} (3fccfb2c-fc14-4b3c-8b91-ba9d3e102759 id=0x7f0909d7) ║
|
|
102
|
+
║ │ └─ FindMoreFriendsUI{fdacb08} (b1b80b1b-ea6f-470b-b16c-cd76c853e8ad id=0x7f092d4a) ║
|
|
103
|
+
║ │ ║
|
|
104
|
+
╚═════════════════════╧════════════════════════════════════════════════════════════════════════════════════════╝
|
|
105
|
+
```
|
|
106
|
+
### More Options
|
|
107
|
+
```
|
|
108
|
+
-h, --help Show help
|
|
109
|
+
-a, --activity Show the current activity's name
|
|
110
|
+
-s, --stack Show the current activity's stack
|
|
111
|
+
-f, --fragment Show all fragments in the current activity
|
|
112
|
+
-w, --watch Monitor activity or fragments changes in real time
|
|
113
|
+
-A, --all Show all information, including the current activity name, activity stack and fragments
|
|
27
114
|
```
|
|
28
115
|
That's it.
|
|
29
116
|
|
|
30
117
|
## Changelog
|
|
31
118
|
|
|
119
|
+
* 1.0.2
|
|
120
|
+
* Compatible with some Samsung phones
|
|
121
|
+
|
|
122
|
+
* 1.0.1
|
|
123
|
+
* Added more options for more flexible output
|
|
124
|
+
|
|
32
125
|
* 1.0.0
|
|
33
126
|
* Initial version
|
|
34
127
|
|
package/build/index.js
CHANGED
|
@@ -9,12 +9,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
10
|
});
|
|
11
11
|
};
|
|
12
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
12
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
16
|
const child_process_1 = require("child_process");
|
|
14
17
|
const table_1 = require("table");
|
|
15
18
|
const treeify_1 = require("treeify");
|
|
19
|
+
const yargs_1 = __importDefault(require("yargs"));
|
|
16
20
|
require("./extension");
|
|
17
|
-
function
|
|
21
|
+
function printAll() {
|
|
18
22
|
var _a, _b, _c, _d, _e, _f;
|
|
19
23
|
return __awaiter(this, void 0, void 0, function* () {
|
|
20
24
|
// exec adb shell dumpsys window displays
|
|
@@ -34,7 +38,7 @@ function printDumpInfo() {
|
|
|
34
38
|
const activityOutput = (0, child_process_1.execSync)("adb shell dumpsys activity " + currentApp, { encoding: "utf-8" });
|
|
35
39
|
const activityLines = activityOutput.split("\n");
|
|
36
40
|
// 1. find top activity
|
|
37
|
-
const activitesLines = findLines(activityLines, "ACTIVITY");
|
|
41
|
+
const activitesLines = findLines(activityLines, "ACTIVITY ");
|
|
38
42
|
let sliceStart = 0;
|
|
39
43
|
let sliceEnd = activityLines.length - 1;
|
|
40
44
|
activitesLines.forEach((v, index) => {
|
|
@@ -64,38 +68,56 @@ function printDumpInfo() {
|
|
|
64
68
|
frameworkRangeLines.sort((a, b) => a.start.index - b.start.index);
|
|
65
69
|
frameworkRangeLines.forEach((v) => {
|
|
66
70
|
const firstFragmentLine = frameworkLines === null || frameworkLines === void 0 ? void 0 : frameworkLines.at(v.start.index + 1);
|
|
67
|
-
if (firstFragmentLine) {
|
|
71
|
+
if (firstFragmentLine && !isNullLine(firstFragmentLine)) {
|
|
68
72
|
frameworkFragmentLines.push({
|
|
69
|
-
content: firstFragmentLine,
|
|
73
|
+
content: handleFragmentLine(firstFragmentLine),
|
|
70
74
|
index: v.start.index + 1,
|
|
71
75
|
});
|
|
72
76
|
}
|
|
73
77
|
frameworkLines === null || frameworkLines === void 0 ? void 0 : frameworkLines.forEach((item, index) => {
|
|
74
78
|
if (firstFragmentLine &&
|
|
79
|
+
!isNullLine(item) &&
|
|
75
80
|
spaceCount(item) == spaceCount(firstFragmentLine) &&
|
|
76
81
|
index > v.start.index + 1 &&
|
|
77
82
|
index < v.end.index) {
|
|
78
|
-
frameworkFragmentLines.push({
|
|
83
|
+
frameworkFragmentLines.push({
|
|
84
|
+
content: handleFragmentLine(item),
|
|
85
|
+
index: index,
|
|
86
|
+
});
|
|
79
87
|
}
|
|
80
88
|
});
|
|
81
89
|
});
|
|
82
90
|
if (androidxLines) {
|
|
91
|
+
const activeFragmentsLine = findFirstLines(androidxLines, "Active Fragments:");
|
|
92
|
+
if (activeFragmentsLine != undefined &&
|
|
93
|
+
!activeFragmentsLine.endsWith("Active Fragments:")) {
|
|
94
|
+
const androidxLinesText = androidxLines.join("\n");
|
|
95
|
+
const activeFragmentsSliceIndex = androidxLinesText.indexOf("Active Fragments:") +
|
|
96
|
+
"Active Fragments:".length;
|
|
97
|
+
androidxLines = (androidxLinesText.slice(0, activeFragmentsSliceIndex) +
|
|
98
|
+
"\n" +
|
|
99
|
+
androidxLinesText.slice(activeFragmentsSliceIndex)).split("\n");
|
|
100
|
+
}
|
|
83
101
|
const androidxRangeLines = findRangeLines(androidxLines, "Active Fragments", "Added Fragments");
|
|
84
102
|
androidxRangeLines.sort((a, b) => a.start.index - b.start.index);
|
|
85
103
|
androidxRangeLines.forEach((v) => {
|
|
86
104
|
const firstFragmentLine = androidxLines === null || androidxLines === void 0 ? void 0 : androidxLines.at(v.start.index + 1);
|
|
87
|
-
if (firstFragmentLine) {
|
|
105
|
+
if (firstFragmentLine && !isNullLine(firstFragmentLine)) {
|
|
88
106
|
androidxFragmentLines.push({
|
|
89
|
-
content: firstFragmentLine,
|
|
107
|
+
content: handleFragmentLine(firstFragmentLine),
|
|
90
108
|
index: v.start.index + 1,
|
|
91
109
|
});
|
|
92
110
|
}
|
|
93
111
|
androidxLines === null || androidxLines === void 0 ? void 0 : androidxLines.forEach((item, index) => {
|
|
94
112
|
if (firstFragmentLine &&
|
|
113
|
+
!isNullLine(item) &&
|
|
95
114
|
spaceCount(item) == spaceCount(firstFragmentLine) &&
|
|
96
115
|
index > v.start.index + 1 &&
|
|
97
116
|
index < v.end.index) {
|
|
98
|
-
androidxFragmentLines.push({
|
|
117
|
+
androidxFragmentLines.push({
|
|
118
|
+
content: handleFragmentLine(item),
|
|
119
|
+
index: index,
|
|
120
|
+
});
|
|
99
121
|
}
|
|
100
122
|
});
|
|
101
123
|
});
|
|
@@ -114,9 +136,10 @@ function printDumpInfo() {
|
|
|
114
136
|
if (stackId != undefined) {
|
|
115
137
|
const stackLines = windowLines.filter((v) => {
|
|
116
138
|
const s = v.trim();
|
|
117
|
-
return s.startsWith("*")
|
|
139
|
+
return ((s.startsWith("*") || s.startsWith("Activity #")) &&
|
|
140
|
+
s.indexOf(stackId) > 0);
|
|
118
141
|
});
|
|
119
|
-
const stacks = stackLines.map((v) => v.trim().split(" ")
|
|
142
|
+
const stacks = stackLines.map((v) => v.trim().split(" ").last(1));
|
|
120
143
|
if (stacks[0] != currentActivity) {
|
|
121
144
|
stacks.shift();
|
|
122
145
|
}
|
|
@@ -151,14 +174,32 @@ function printDumpInfo() {
|
|
|
151
174
|
}
|
|
152
175
|
});
|
|
153
176
|
}
|
|
177
|
+
function handleFragmentLine(content) {
|
|
178
|
+
var _a;
|
|
179
|
+
if (content.length > 160) {
|
|
180
|
+
if (content.trimStart().startsWith("SupportRequestManagerFragment")) {
|
|
181
|
+
const parentIndex = content.indexOf("{parent=");
|
|
182
|
+
const parentText = content.substring(parentIndex);
|
|
183
|
+
return (content.substring(0, parentIndex) + ((_a = parentText.split(" ")) === null || _a === void 0 ? void 0 : _a.at(0)) + "}");
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
return content.substring(0, 160);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return content;
|
|
190
|
+
}
|
|
191
|
+
function isNullLine(content) {
|
|
192
|
+
if (content.trim() == "null")
|
|
193
|
+
return true;
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
154
196
|
function toTreeArray(arr) {
|
|
155
197
|
const result = Array();
|
|
156
198
|
arr.forEach((v, index) => {
|
|
157
199
|
result.push({
|
|
158
200
|
id: index.toString(),
|
|
159
201
|
content: v.content.trim(),
|
|
160
|
-
parentId: findParentIndex(arr.map((item) => item.content), v.content)
|
|
161
|
-
.toString(),
|
|
202
|
+
parentId: findParentIndex(arr.map((item) => item.content), v.content).toString(),
|
|
162
203
|
children: null,
|
|
163
204
|
});
|
|
164
205
|
});
|
|
@@ -248,7 +289,7 @@ function spaceCount(value) {
|
|
|
248
289
|
function findLines(lines, target) {
|
|
249
290
|
const result = Array();
|
|
250
291
|
lines.forEach((v, i) => {
|
|
251
|
-
if (v.indexOf(target)
|
|
292
|
+
if (v.indexOf(target) >= 0) {
|
|
252
293
|
result.push({
|
|
253
294
|
content: v,
|
|
254
295
|
index: i,
|
|
@@ -261,6 +302,15 @@ function findFirstLines(lines, target) {
|
|
|
261
302
|
var _a;
|
|
262
303
|
return (_a = findLines(lines, target).at(0)) === null || _a === void 0 ? void 0 : _a.content;
|
|
263
304
|
}
|
|
305
|
+
function findFirstLineIndex(lines, target) {
|
|
306
|
+
const firstLine = findLines(lines, target).at(0);
|
|
307
|
+
if (firstLine == undefined) {
|
|
308
|
+
return -1;
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
return firstLine.index;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
264
314
|
function findLastLines(lines, target) {
|
|
265
315
|
var _a;
|
|
266
316
|
return (_a = findLines(lines, target).last(0)) === null || _a === void 0 ? void 0 : _a.content;
|
|
@@ -289,15 +339,296 @@ function findRangeLines(lines, start, end) {
|
|
|
289
339
|
return children;
|
|
290
340
|
}
|
|
291
341
|
let oldActivity = "";
|
|
292
|
-
function
|
|
342
|
+
function onCurrentWindowChanged(f) {
|
|
293
343
|
return __awaiter(this, void 0, void 0, function* () {
|
|
294
344
|
while (true) {
|
|
295
345
|
const currentActivity = (0, child_process_1.execSync)("adb shell dumpsys window displays | grep -E 'mCurrentFocus'", { encoding: "utf-8" });
|
|
296
346
|
if (oldActivity != currentActivity) {
|
|
297
|
-
|
|
347
|
+
f();
|
|
298
348
|
oldActivity = currentActivity;
|
|
299
349
|
}
|
|
300
350
|
}
|
|
301
351
|
});
|
|
302
352
|
}
|
|
303
|
-
|
|
353
|
+
let oldFragments = "";
|
|
354
|
+
function onFragmentsChanged(f) {
|
|
355
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
356
|
+
while (true) {
|
|
357
|
+
const activityOutput = (0, child_process_1.execSync)("adb shell dumpsys activity top", {
|
|
358
|
+
encoding: "utf-8",
|
|
359
|
+
});
|
|
360
|
+
const activityLines = activityOutput.split("\n");
|
|
361
|
+
const topActivityLine = findLastLines(activityLines, "TASK");
|
|
362
|
+
let sliceStart = activityLines.indexOf(topActivityLine);
|
|
363
|
+
let sliceEnd = activityLines.length - 1;
|
|
364
|
+
const topActivityLines = activityLines.slice(sliceStart, sliceEnd);
|
|
365
|
+
const frameworkFragmentSliceStart = findFirstLineIndex(topActivityLines, "Local Activity");
|
|
366
|
+
const frameworkFragmentSliceEnd = findFirstLineIndex(topActivityLines, "ViewRoot:");
|
|
367
|
+
const androidXFragmentSliceStart = findFirstLineIndex(topActivityLines, "Local FragmentActivity");
|
|
368
|
+
const androidXFragmentSliceEnd = topActivityLines.length - 1;
|
|
369
|
+
let frameworkFragmentLines = "";
|
|
370
|
+
if (frameworkFragmentSliceStart >= 0 &&
|
|
371
|
+
frameworkFragmentSliceEnd >= 0 &&
|
|
372
|
+
frameworkFragmentSliceStart < frameworkFragmentSliceEnd) {
|
|
373
|
+
frameworkFragmentLines = topActivityLines
|
|
374
|
+
.slice(frameworkFragmentSliceStart, frameworkFragmentSliceEnd)
|
|
375
|
+
.join("\n");
|
|
376
|
+
}
|
|
377
|
+
let androidXFragmentLines = "";
|
|
378
|
+
if (androidXFragmentSliceStart >= 0 &&
|
|
379
|
+
androidXFragmentSliceEnd >= 0 &&
|
|
380
|
+
androidXFragmentSliceStart < androidXFragmentSliceEnd) {
|
|
381
|
+
androidXFragmentLines = topActivityLines
|
|
382
|
+
.slice(androidXFragmentSliceStart, androidXFragmentSliceEnd)
|
|
383
|
+
.join("\n");
|
|
384
|
+
}
|
|
385
|
+
const fragmentLines = frameworkFragmentLines + "\n" + androidXFragmentLines;
|
|
386
|
+
if (oldFragments != fragmentLines) {
|
|
387
|
+
f();
|
|
388
|
+
oldFragments = fragmentLines;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
function printCurrentActivityName() {
|
|
394
|
+
var _a, _b;
|
|
395
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
396
|
+
const windowOutput = (0, child_process_1.execSync)("adb shell dumpsys window displays", {
|
|
397
|
+
encoding: "utf-8",
|
|
398
|
+
});
|
|
399
|
+
const windowLines = windowOutput.split("\n");
|
|
400
|
+
const currentFocusLine = findFirstLines(windowLines, "mCurrentFocus");
|
|
401
|
+
const currentWindow = (_b = (_a = currentFocusLine === null || currentFocusLine === void 0 ? void 0 : currentFocusLine.split(" ")) === null || _a === void 0 ? void 0 : _a.last(0)) === null || _b === void 0 ? void 0 : _b.removeLast(1);
|
|
402
|
+
if (currentWindow) {
|
|
403
|
+
console.clear();
|
|
404
|
+
console.log(currentWindow);
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
function printCurrentActivityStack() {
|
|
409
|
+
var _a, _b, _c;
|
|
410
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
411
|
+
const windowOutput = (0, child_process_1.execSync)("adb shell dumpsys window displays", {
|
|
412
|
+
encoding: "utf-8",
|
|
413
|
+
});
|
|
414
|
+
const windowLines = windowOutput.split("\n");
|
|
415
|
+
const currentFocusAppLine = findFirstLines(windowLines, "mFocusedApp");
|
|
416
|
+
const currentActivity = (_a = currentFocusAppLine === null || currentFocusAppLine === void 0 ? void 0 : currentFocusAppLine.split(" ")) === null || _a === void 0 ? void 0 : _a.last(1);
|
|
417
|
+
const stackId = (_c = (_b = currentFocusAppLine === null || currentFocusAppLine === void 0 ? void 0 : currentFocusAppLine.split(" ")) === null || _b === void 0 ? void 0 : _b.last(0)) === null || _c === void 0 ? void 0 : _c.removeLast(1);
|
|
418
|
+
if (stackId != undefined) {
|
|
419
|
+
const stackLines = windowLines.filter((v) => {
|
|
420
|
+
const s = v.trim();
|
|
421
|
+
return ((s.startsWith("*") || s.startsWith("Activity #")) &&
|
|
422
|
+
s.indexOf(stackId) > 0);
|
|
423
|
+
});
|
|
424
|
+
const stacks = stackLines.map((v) => v.trim().split(" ").last(1));
|
|
425
|
+
if (stacks[0] != currentActivity) {
|
|
426
|
+
stacks.shift();
|
|
427
|
+
}
|
|
428
|
+
const statckTable = Array();
|
|
429
|
+
stacks.forEach((v) => statckTable.push([v]));
|
|
430
|
+
console.clear();
|
|
431
|
+
console.log((0, table_1.table)(statckTable));
|
|
432
|
+
}
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
function printCurrentActivityFragments() {
|
|
436
|
+
var _a, _b;
|
|
437
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
438
|
+
const windowOutput = (0, child_process_1.execSync)("adb shell dumpsys window displays", {
|
|
439
|
+
encoding: "utf-8",
|
|
440
|
+
});
|
|
441
|
+
const windowLines = windowOutput.split("\n");
|
|
442
|
+
const currentFocusAppLine = findFirstLines(windowLines, "mFocusedApp");
|
|
443
|
+
const currentActivity = (_a = currentFocusAppLine === null || currentFocusAppLine === void 0 ? void 0 : currentFocusAppLine.split(" ")) === null || _a === void 0 ? void 0 : _a.last(1);
|
|
444
|
+
const currentApp = (_b = currentActivity === null || currentActivity === void 0 ? void 0 : currentActivity.split("/")) === null || _b === void 0 ? void 0 : _b.at(0);
|
|
445
|
+
const frameworkFragmentLines = Array();
|
|
446
|
+
const androidxFragmentLines = Array();
|
|
447
|
+
if (currentApp != undefined) {
|
|
448
|
+
const activityOutput = (0, child_process_1.execSync)("adb shell dumpsys activity " + currentApp, { encoding: "utf-8" });
|
|
449
|
+
const activityLines = activityOutput.split("\n");
|
|
450
|
+
// 1. find top activity
|
|
451
|
+
const activitesLines = findLines(activityLines, "ACTIVITY ");
|
|
452
|
+
let sliceStart = 0;
|
|
453
|
+
let sliceEnd = activityLines.length - 1;
|
|
454
|
+
activitesLines.forEach((v, index) => {
|
|
455
|
+
if (currentActivity && v.content.indexOf(currentActivity) > 0) {
|
|
456
|
+
sliceStart = v.index;
|
|
457
|
+
if (index + 1 <= activitesLines.length - 1) {
|
|
458
|
+
sliceEnd = activitesLines[index + 1].index;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
// 2. cut out the top activity lines
|
|
463
|
+
const topActivityLines = activityLines.slice(sliceStart, sliceEnd);
|
|
464
|
+
// 3. split into framework fragments and androidx fragments
|
|
465
|
+
const splitLine = findLastLines(topActivityLines, "Local FragmentActivity");
|
|
466
|
+
let frameworkLines;
|
|
467
|
+
let androidxLines;
|
|
468
|
+
if (splitLine != undefined) {
|
|
469
|
+
const splitLineIndex = topActivityLines.indexOf(splitLine);
|
|
470
|
+
frameworkLines = topActivityLines.slice(0, splitLineIndex);
|
|
471
|
+
androidxLines = topActivityLines.slice(splitLineIndex);
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
frameworkLines = topActivityLines;
|
|
475
|
+
}
|
|
476
|
+
// 4. find all children of between "Active Fragments" and "Added Fragments" node
|
|
477
|
+
const frameworkRangeLines = findRangeLines(frameworkLines, "Active Fragments", "Added Fragments");
|
|
478
|
+
frameworkRangeLines.sort((a, b) => a.start.index - b.start.index);
|
|
479
|
+
frameworkRangeLines.forEach((v) => {
|
|
480
|
+
const firstFragmentLine = frameworkLines === null || frameworkLines === void 0 ? void 0 : frameworkLines.at(v.start.index + 1);
|
|
481
|
+
if (firstFragmentLine && !isNullLine(firstFragmentLine)) {
|
|
482
|
+
frameworkFragmentLines.push({
|
|
483
|
+
content: handleFragmentLine(firstFragmentLine),
|
|
484
|
+
index: v.start.index + 1,
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
frameworkLines === null || frameworkLines === void 0 ? void 0 : frameworkLines.forEach((item, index) => {
|
|
488
|
+
if (firstFragmentLine &&
|
|
489
|
+
!isNullLine(item) &&
|
|
490
|
+
spaceCount(item) == spaceCount(firstFragmentLine) &&
|
|
491
|
+
index > v.start.index + 1 &&
|
|
492
|
+
index < v.end.index) {
|
|
493
|
+
frameworkFragmentLines.push({
|
|
494
|
+
content: handleFragmentLine(item),
|
|
495
|
+
index: index,
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
if (androidxLines) {
|
|
501
|
+
const activeFragmentsLine = findFirstLines(androidxLines, "Active Fragments:");
|
|
502
|
+
if (activeFragmentsLine != undefined &&
|
|
503
|
+
!activeFragmentsLine.endsWith("Active Fragments:")) {
|
|
504
|
+
const androidxLinesText = androidxLines.join("\n");
|
|
505
|
+
const activeFragmentsSliceIndex = androidxLinesText.indexOf("Active Fragments:") +
|
|
506
|
+
"Active Fragments:".length;
|
|
507
|
+
androidxLines = (androidxLinesText.slice(0, activeFragmentsSliceIndex) +
|
|
508
|
+
"\n" +
|
|
509
|
+
androidxLinesText.slice(activeFragmentsSliceIndex)).split("\n");
|
|
510
|
+
}
|
|
511
|
+
const androidxRangeLines = findRangeLines(androidxLines, "Active Fragments", "Added Fragments");
|
|
512
|
+
androidxRangeLines.sort((a, b) => a.start.index - b.start.index);
|
|
513
|
+
androidxRangeLines.forEach((v) => {
|
|
514
|
+
const firstFragmentLine = androidxLines === null || androidxLines === void 0 ? void 0 : androidxLines.at(v.start.index + 1);
|
|
515
|
+
if (firstFragmentLine && !isNullLine(firstFragmentLine)) {
|
|
516
|
+
androidxFragmentLines.push({
|
|
517
|
+
content: handleFragmentLine(firstFragmentLine),
|
|
518
|
+
index: v.start.index + 1,
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
androidxLines === null || androidxLines === void 0 ? void 0 : androidxLines.forEach((item, index) => {
|
|
522
|
+
if (firstFragmentLine &&
|
|
523
|
+
!isNullLine(item) &&
|
|
524
|
+
spaceCount(item) == spaceCount(firstFragmentLine) &&
|
|
525
|
+
index > v.start.index + 1 &&
|
|
526
|
+
index < v.end.index) {
|
|
527
|
+
androidxFragmentLines.push({
|
|
528
|
+
content: handleFragmentLine(item),
|
|
529
|
+
index: index,
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
});
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
if (frameworkFragmentLines.length > 0 || androidxFragmentLines.length > 0) {
|
|
537
|
+
const fragmentTable = Array();
|
|
538
|
+
fragmentTable.push(["activity", currentActivity]);
|
|
539
|
+
if (frameworkFragmentLines.length > 0) {
|
|
540
|
+
frameworkFragmentLines.sort((a, b) => a.index - b.index);
|
|
541
|
+
fragmentTable.push([
|
|
542
|
+
"framework fragments",
|
|
543
|
+
(0, treeify_1.asTree)(toTreeObject(listToTree(toTreeArray(frameworkFragmentLines))), true),
|
|
544
|
+
]);
|
|
545
|
+
}
|
|
546
|
+
if (androidxFragmentLines.length > 0) {
|
|
547
|
+
androidxFragmentLines.sort((a, b) => a.index - b.index);
|
|
548
|
+
fragmentTable.push([
|
|
549
|
+
"androidx fragments",
|
|
550
|
+
(0, treeify_1.asTree)(toTreeObject(listToTree(toTreeArray(androidxFragmentLines))), true),
|
|
551
|
+
]);
|
|
552
|
+
}
|
|
553
|
+
console.clear();
|
|
554
|
+
console.log((0, table_1.table)(fragmentTable));
|
|
555
|
+
}
|
|
556
|
+
else {
|
|
557
|
+
console.clear();
|
|
558
|
+
const fragmentTable = Array();
|
|
559
|
+
fragmentTable.push(["activity", currentActivity]);
|
|
560
|
+
console.log((0, table_1.table)(fragmentTable));
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
const argv = (0, yargs_1.default)(process.argv.slice(2))
|
|
565
|
+
.help("help")
|
|
566
|
+
.alias("help", "h")
|
|
567
|
+
.options({
|
|
568
|
+
activity: {
|
|
569
|
+
type: "boolean",
|
|
570
|
+
default: true,
|
|
571
|
+
alias: "a",
|
|
572
|
+
description: "Show the current activity's name",
|
|
573
|
+
},
|
|
574
|
+
stack: {
|
|
575
|
+
type: "boolean",
|
|
576
|
+
default: false,
|
|
577
|
+
alias: "s",
|
|
578
|
+
description: "Show the current activity's stack",
|
|
579
|
+
},
|
|
580
|
+
fragment: {
|
|
581
|
+
type: "boolean",
|
|
582
|
+
default: false,
|
|
583
|
+
alias: "f",
|
|
584
|
+
description: "Show all fragments in the current activity",
|
|
585
|
+
},
|
|
586
|
+
watch: {
|
|
587
|
+
type: "boolean",
|
|
588
|
+
default: false,
|
|
589
|
+
alias: "w",
|
|
590
|
+
description: "Monitor activity or fragments changes in real time",
|
|
591
|
+
},
|
|
592
|
+
all: {
|
|
593
|
+
type: "boolean",
|
|
594
|
+
default: false,
|
|
595
|
+
alias: "A",
|
|
596
|
+
description: "Show all information, including the current activity name, activity stack and fragments",
|
|
597
|
+
},
|
|
598
|
+
})
|
|
599
|
+
.locale("en")
|
|
600
|
+
.parseSync();
|
|
601
|
+
if (argv.all) {
|
|
602
|
+
if (argv.watch) {
|
|
603
|
+
onCurrentWindowChanged(() => printAll());
|
|
604
|
+
}
|
|
605
|
+
else {
|
|
606
|
+
printAll();
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
else if (argv.fragment) {
|
|
610
|
+
if (argv.watch) {
|
|
611
|
+
onFragmentsChanged(() => printCurrentActivityFragments());
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
printCurrentActivityFragments();
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
else if (argv.activity) {
|
|
618
|
+
if (argv.stack) {
|
|
619
|
+
if (argv.watch) {
|
|
620
|
+
onCurrentWindowChanged(() => printCurrentActivityStack());
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
printCurrentActivityStack();
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
else {
|
|
627
|
+
if (argv.watch) {
|
|
628
|
+
onCurrentWindowChanged(() => printCurrentActivityName());
|
|
629
|
+
}
|
|
630
|
+
else {
|
|
631
|
+
printCurrentActivityName();
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "currentactivity",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "A command line tool to display the current activity for android.",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/
|
|
11
|
+
"url": "git+https://github.com/dfshizhiqiang/currentactivity.git"
|
|
12
12
|
},
|
|
13
13
|
"keywords": [
|
|
14
14
|
"current activity",
|
|
@@ -19,19 +19,21 @@
|
|
|
19
19
|
"author": "Zech",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"bugs": {
|
|
22
|
-
"url": "https://github.com/
|
|
22
|
+
"url": "https://github.com/dfshizhiqiang/currentactivity/issues"
|
|
23
23
|
},
|
|
24
|
-
"homepage": "https://github.com/
|
|
24
|
+
"homepage": "https://github.com/dfshizhiqiang/currentactivity#readme",
|
|
25
25
|
"bin": {
|
|
26
26
|
"currentactivity": "./build/index.js"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
+
"@types/yargs": "^17.0.10",
|
|
29
30
|
"ts-node": "^10.4.0",
|
|
30
31
|
"typescript": "^4.5.5"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
33
34
|
"table": "^6.8.0",
|
|
34
|
-
"treeify": "^1.1.0"
|
|
35
|
+
"treeify": "^1.1.0",
|
|
36
|
+
"yargs": "^17.5.1"
|
|
35
37
|
},
|
|
36
38
|
"publishConfig": {
|
|
37
39
|
"access": "public"
|
package/src/index.ts
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
import { execSync } from "child_process";
|
|
3
3
|
import { table } from "table";
|
|
4
4
|
import { asTree } from "treeify";
|
|
5
|
+
import yargs from "yargs";
|
|
5
6
|
import "./extension";
|
|
6
7
|
|
|
7
|
-
async function
|
|
8
|
+
async function printAll() {
|
|
8
9
|
// exec adb shell dumpsys window displays
|
|
9
10
|
const windowOutput = execSync("adb shell dumpsys window displays", {
|
|
10
11
|
encoding: "utf-8",
|
|
@@ -24,12 +25,12 @@ async function printDumpInfo() {
|
|
|
24
25
|
if (currentApp != undefined) {
|
|
25
26
|
const activityOutput = execSync(
|
|
26
27
|
"adb shell dumpsys activity " + currentApp,
|
|
27
|
-
{ encoding: "utf-8" }
|
|
28
|
+
{ encoding: "utf-8" }
|
|
28
29
|
);
|
|
29
30
|
const activityLines = activityOutput.split("\n");
|
|
30
31
|
|
|
31
32
|
// 1. find top activity
|
|
32
|
-
const activitesLines = findLines(activityLines, "ACTIVITY");
|
|
33
|
+
const activitesLines = findLines(activityLines, "ACTIVITY ");
|
|
33
34
|
let sliceStart = 0;
|
|
34
35
|
let sliceEnd = activityLines.length - 1;
|
|
35
36
|
activitesLines.forEach((v, index) => {
|
|
@@ -44,10 +45,7 @@ async function printDumpInfo() {
|
|
|
44
45
|
// 2. cut out the top activity lines
|
|
45
46
|
const topActivityLines = activityLines.slice(sliceStart, sliceEnd);
|
|
46
47
|
// 3. split into framework fragments and androidx fragments
|
|
47
|
-
const splitLine = findLastLines(
|
|
48
|
-
topActivityLines,
|
|
49
|
-
"Local FragmentActivity",
|
|
50
|
-
);
|
|
48
|
+
const splitLine = findLastLines(topActivityLines, "Local FragmentActivity");
|
|
51
49
|
let frameworkLines: Array<string>;
|
|
52
50
|
let androidxLines: Array<string> | undefined;
|
|
53
51
|
if (splitLine != undefined) {
|
|
@@ -61,53 +59,79 @@ async function printDumpInfo() {
|
|
|
61
59
|
const frameworkRangeLines = findRangeLines(
|
|
62
60
|
frameworkLines,
|
|
63
61
|
"Active Fragments",
|
|
64
|
-
"Added Fragments"
|
|
62
|
+
"Added Fragments"
|
|
65
63
|
);
|
|
66
64
|
frameworkRangeLines.sort((a, b) => a.start.index - b.start.index);
|
|
67
65
|
frameworkRangeLines.forEach((v) => {
|
|
68
66
|
const firstFragmentLine = frameworkLines?.at(v.start.index + 1);
|
|
69
|
-
if (firstFragmentLine) {
|
|
67
|
+
if (firstFragmentLine && !isNullLine(firstFragmentLine)) {
|
|
70
68
|
frameworkFragmentLines.push({
|
|
71
|
-
content: firstFragmentLine,
|
|
69
|
+
content: handleFragmentLine(firstFragmentLine),
|
|
72
70
|
index: v.start.index + 1,
|
|
73
71
|
});
|
|
74
72
|
}
|
|
75
73
|
frameworkLines?.forEach((item, index) => {
|
|
76
74
|
if (
|
|
77
75
|
firstFragmentLine &&
|
|
76
|
+
!isNullLine(item) &&
|
|
78
77
|
spaceCount(item) == spaceCount(firstFragmentLine) &&
|
|
79
78
|
index > v.start.index + 1 &&
|
|
80
79
|
index < v.end.index
|
|
81
80
|
) {
|
|
82
|
-
frameworkFragmentLines.push({
|
|
81
|
+
frameworkFragmentLines.push({
|
|
82
|
+
content: handleFragmentLine(item),
|
|
83
|
+
index: index,
|
|
84
|
+
});
|
|
83
85
|
}
|
|
84
86
|
});
|
|
85
87
|
});
|
|
86
88
|
|
|
87
89
|
if (androidxLines) {
|
|
90
|
+
const activeFragmentsLine = findFirstLines(
|
|
91
|
+
androidxLines,
|
|
92
|
+
"Active Fragments:"
|
|
93
|
+
);
|
|
94
|
+
if (
|
|
95
|
+
activeFragmentsLine != undefined &&
|
|
96
|
+
!activeFragmentsLine.endsWith("Active Fragments:")
|
|
97
|
+
) {
|
|
98
|
+
const androidxLinesText = androidxLines.join("\n");
|
|
99
|
+
const activeFragmentsSliceIndex =
|
|
100
|
+
androidxLinesText.indexOf("Active Fragments:") +
|
|
101
|
+
"Active Fragments:".length;
|
|
102
|
+
androidxLines = (
|
|
103
|
+
androidxLinesText.slice(0, activeFragmentsSliceIndex) +
|
|
104
|
+
"\n" +
|
|
105
|
+
androidxLinesText.slice(activeFragmentsSliceIndex)
|
|
106
|
+
).split("\n");
|
|
107
|
+
}
|
|
88
108
|
const androidxRangeLines = findRangeLines(
|
|
89
109
|
androidxLines,
|
|
90
110
|
"Active Fragments",
|
|
91
|
-
"Added Fragments"
|
|
111
|
+
"Added Fragments"
|
|
92
112
|
);
|
|
93
113
|
androidxRangeLines.sort((a, b) => a.start.index - b.start.index);
|
|
94
114
|
|
|
95
115
|
androidxRangeLines.forEach((v) => {
|
|
96
116
|
const firstFragmentLine = androidxLines?.at(v.start.index + 1);
|
|
97
|
-
if (firstFragmentLine) {
|
|
117
|
+
if (firstFragmentLine && !isNullLine(firstFragmentLine)) {
|
|
98
118
|
androidxFragmentLines.push({
|
|
99
|
-
content: firstFragmentLine,
|
|
119
|
+
content: handleFragmentLine(firstFragmentLine),
|
|
100
120
|
index: v.start.index + 1,
|
|
101
121
|
});
|
|
102
122
|
}
|
|
103
123
|
androidxLines?.forEach((item, index) => {
|
|
104
124
|
if (
|
|
105
125
|
firstFragmentLine &&
|
|
126
|
+
!isNullLine(item) &&
|
|
106
127
|
spaceCount(item) == spaceCount(firstFragmentLine) &&
|
|
107
128
|
index > v.start.index + 1 &&
|
|
108
129
|
index < v.end.index
|
|
109
130
|
) {
|
|
110
|
-
androidxFragmentLines.push({
|
|
131
|
+
androidxFragmentLines.push({
|
|
132
|
+
content: handleFragmentLine(item),
|
|
133
|
+
index: index,
|
|
134
|
+
});
|
|
111
135
|
}
|
|
112
136
|
});
|
|
113
137
|
});
|
|
@@ -123,7 +147,7 @@ async function printDumpInfo() {
|
|
|
123
147
|
console.log(
|
|
124
148
|
table(windowTable, {
|
|
125
149
|
header: { content: "current window", alignment: "center" },
|
|
126
|
-
})
|
|
150
|
+
})
|
|
127
151
|
);
|
|
128
152
|
}
|
|
129
153
|
|
|
@@ -131,9 +155,12 @@ async function printDumpInfo() {
|
|
|
131
155
|
if (stackId != undefined) {
|
|
132
156
|
const stackLines = windowLines.filter((v) => {
|
|
133
157
|
const s = v.trim();
|
|
134
|
-
return
|
|
158
|
+
return (
|
|
159
|
+
(s.startsWith("*") || s.startsWith("Activity #")) &&
|
|
160
|
+
s.indexOf(stackId) > 0
|
|
161
|
+
);
|
|
135
162
|
});
|
|
136
|
-
const stacks = stackLines.map((v) => v.trim().split(" ")
|
|
163
|
+
const stacks = stackLines.map((v) => v.trim().split(" ").last(1));
|
|
137
164
|
if (stacks[0] != currentActivity) {
|
|
138
165
|
stacks.shift();
|
|
139
166
|
}
|
|
@@ -143,7 +170,7 @@ async function printDumpInfo() {
|
|
|
143
170
|
console.log(
|
|
144
171
|
table(statckTable, {
|
|
145
172
|
header: { content: "activity stack", alignment: "center" },
|
|
146
|
-
})
|
|
173
|
+
})
|
|
147
174
|
);
|
|
148
175
|
}
|
|
149
176
|
|
|
@@ -156,7 +183,7 @@ async function printDumpInfo() {
|
|
|
156
183
|
"framework fragments",
|
|
157
184
|
asTree(
|
|
158
185
|
toTreeObject(listToTree(toTreeArray(frameworkFragmentLines))),
|
|
159
|
-
true
|
|
186
|
+
true
|
|
160
187
|
),
|
|
161
188
|
]);
|
|
162
189
|
}
|
|
@@ -166,7 +193,7 @@ async function printDumpInfo() {
|
|
|
166
193
|
"androidx fragments",
|
|
167
194
|
asTree(
|
|
168
195
|
toTreeObject(listToTree(toTreeArray(androidxFragmentLines))),
|
|
169
|
-
true
|
|
196
|
+
true
|
|
170
197
|
),
|
|
171
198
|
]);
|
|
172
199
|
}
|
|
@@ -174,11 +201,31 @@ async function printDumpInfo() {
|
|
|
174
201
|
console.log(
|
|
175
202
|
table(fragmentTable, {
|
|
176
203
|
header: { content: "fragments", alignment: "center" },
|
|
177
|
-
})
|
|
204
|
+
})
|
|
178
205
|
);
|
|
179
206
|
}
|
|
180
207
|
}
|
|
181
208
|
|
|
209
|
+
function handleFragmentLine(content: string): string {
|
|
210
|
+
if (content.length > 160) {
|
|
211
|
+
if (content.trimStart().startsWith("SupportRequestManagerFragment")) {
|
|
212
|
+
const parentIndex = content.indexOf("{parent=");
|
|
213
|
+
const parentText = content.substring(parentIndex);
|
|
214
|
+
return (
|
|
215
|
+
content.substring(0, parentIndex) + parentText.split(" ")?.at(0) + "}"
|
|
216
|
+
);
|
|
217
|
+
} else {
|
|
218
|
+
return content.substring(0, 160);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return content;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function isNullLine(content: string): boolean {
|
|
225
|
+
if (content.trim() == "null") return true;
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
|
|
182
229
|
type Tree = {
|
|
183
230
|
id: string;
|
|
184
231
|
content: string;
|
|
@@ -192,18 +239,17 @@ function toTreeArray(arr: Array<Line>): Array<Tree> {
|
|
|
192
239
|
result.push({
|
|
193
240
|
id: index.toString(),
|
|
194
241
|
content: v.content.trim(),
|
|
195
|
-
parentId: findParentIndex(
|
|
196
|
-
.
|
|
242
|
+
parentId: findParentIndex(
|
|
243
|
+
arr.map((item) => item.content),
|
|
244
|
+
v.content
|
|
245
|
+
).toString(),
|
|
197
246
|
children: null,
|
|
198
247
|
});
|
|
199
248
|
});
|
|
200
249
|
return result;
|
|
201
250
|
}
|
|
202
251
|
|
|
203
|
-
function findParentIndex(
|
|
204
|
-
arr: Array<string>,
|
|
205
|
-
target: string,
|
|
206
|
-
): number {
|
|
252
|
+
function findParentIndex(arr: Array<string>, target: string): number {
|
|
207
253
|
const targetIndex = arr.indexOf(target);
|
|
208
254
|
if (targetIndex < 0) return -1;
|
|
209
255
|
let parentIndex = -1;
|
|
@@ -267,15 +313,15 @@ function findChildren(arr: Array<string>, target: string): Array<string> {
|
|
|
267
313
|
const result = Array<string>();
|
|
268
314
|
const targetIndex = arr.indexOf(target);
|
|
269
315
|
if (targetIndex < 0 || targetIndex == arr.length - 1) return result;
|
|
270
|
-
const nextBrotherIndex = arr.findIndex(
|
|
271
|
-
spaceCount(v) == spaceCount(target) && i > targetIndex
|
|
316
|
+
const nextBrotherIndex = arr.findIndex(
|
|
317
|
+
(v, i) => spaceCount(v) == spaceCount(target) && i > targetIndex
|
|
272
318
|
);
|
|
273
319
|
if (nextBrotherIndex == targetIndex + 1) return result;
|
|
274
320
|
const firstChild = arr.at(targetIndex + 1);
|
|
275
321
|
if (firstChild) {
|
|
276
322
|
const range = arr.slice(targetIndex, nextBrotherIndex);
|
|
277
|
-
const children = range.filter(
|
|
278
|
-
spaceCount(v) == spaceCount(firstChild)
|
|
323
|
+
const children = range.filter(
|
|
324
|
+
(v) => spaceCount(v) == spaceCount(firstChild)
|
|
279
325
|
);
|
|
280
326
|
result.concat(children);
|
|
281
327
|
}
|
|
@@ -292,13 +338,10 @@ type Line = {
|
|
|
292
338
|
index: number;
|
|
293
339
|
};
|
|
294
340
|
|
|
295
|
-
function findLines(
|
|
296
|
-
lines: Array<string>,
|
|
297
|
-
target: string,
|
|
298
|
-
): Array<Line> {
|
|
341
|
+
function findLines(lines: Array<string>, target: string): Array<Line> {
|
|
299
342
|
const result = Array<Line>();
|
|
300
343
|
lines.forEach((v, i) => {
|
|
301
|
-
if (v.indexOf(target)
|
|
344
|
+
if (v.indexOf(target) >= 0) {
|
|
302
345
|
result.push({
|
|
303
346
|
content: v,
|
|
304
347
|
index: i,
|
|
@@ -310,14 +353,23 @@ function findLines(
|
|
|
310
353
|
|
|
311
354
|
function findFirstLines(
|
|
312
355
|
lines: Array<string>,
|
|
313
|
-
target: string
|
|
356
|
+
target: string
|
|
314
357
|
): string | undefined {
|
|
315
358
|
return findLines(lines, target).at(0)?.content;
|
|
316
359
|
}
|
|
317
360
|
|
|
361
|
+
function findFirstLineIndex(lines: Array<string>, target: string): number {
|
|
362
|
+
const firstLine = findLines(lines, target).at(0);
|
|
363
|
+
if (firstLine == undefined) {
|
|
364
|
+
return -1;
|
|
365
|
+
} else {
|
|
366
|
+
return firstLine.index;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
318
370
|
function findLastLines(
|
|
319
371
|
lines: Array<string>,
|
|
320
|
-
target: string
|
|
372
|
+
target: string
|
|
321
373
|
): string | undefined {
|
|
322
374
|
return findLines(lines, target).last(0)?.content;
|
|
323
375
|
}
|
|
@@ -330,7 +382,7 @@ type RangeLine = {
|
|
|
330
382
|
function findRangeLines(
|
|
331
383
|
lines: Array<string>,
|
|
332
384
|
start: string,
|
|
333
|
-
end: string
|
|
385
|
+
end: string
|
|
334
386
|
): Array<RangeLine> {
|
|
335
387
|
const startLines = findLines(lines, start);
|
|
336
388
|
const endLines = findLines(lines, end);
|
|
@@ -355,17 +407,338 @@ function findRangeLines(
|
|
|
355
407
|
}
|
|
356
408
|
|
|
357
409
|
let oldActivity = "";
|
|
358
|
-
async function
|
|
410
|
+
async function onCurrentWindowChanged(f: () => void) {
|
|
359
411
|
while (true) {
|
|
360
412
|
const currentActivity = execSync(
|
|
361
413
|
"adb shell dumpsys window displays | grep -E 'mCurrentFocus'",
|
|
362
|
-
{ encoding: "utf-8" }
|
|
414
|
+
{ encoding: "utf-8" }
|
|
363
415
|
);
|
|
364
416
|
if (oldActivity != currentActivity) {
|
|
365
|
-
|
|
417
|
+
f();
|
|
366
418
|
oldActivity = currentActivity;
|
|
367
419
|
}
|
|
368
420
|
}
|
|
369
421
|
}
|
|
370
422
|
|
|
371
|
-
|
|
423
|
+
let oldFragments = "";
|
|
424
|
+
async function onFragmentsChanged(f: () => void) {
|
|
425
|
+
while (true) {
|
|
426
|
+
const activityOutput = execSync("adb shell dumpsys activity top", {
|
|
427
|
+
encoding: "utf-8",
|
|
428
|
+
});
|
|
429
|
+
const activityLines = activityOutput.split("\n");
|
|
430
|
+
const topActivityLine = findLastLines(activityLines, "TASK");
|
|
431
|
+
let sliceStart = activityLines.indexOf(topActivityLine);
|
|
432
|
+
let sliceEnd = activityLines.length - 1;
|
|
433
|
+
const topActivityLines = activityLines.slice(sliceStart, sliceEnd);
|
|
434
|
+
const frameworkFragmentSliceStart = findFirstLineIndex(
|
|
435
|
+
topActivityLines,
|
|
436
|
+
"Local Activity"
|
|
437
|
+
);
|
|
438
|
+
const frameworkFragmentSliceEnd = findFirstLineIndex(
|
|
439
|
+
topActivityLines,
|
|
440
|
+
"ViewRoot:"
|
|
441
|
+
);
|
|
442
|
+
const androidXFragmentSliceStart = findFirstLineIndex(
|
|
443
|
+
topActivityLines,
|
|
444
|
+
"Local FragmentActivity"
|
|
445
|
+
);
|
|
446
|
+
const androidXFragmentSliceEnd = topActivityLines.length - 1;
|
|
447
|
+
let frameworkFragmentLines = "";
|
|
448
|
+
if (
|
|
449
|
+
frameworkFragmentSliceStart >= 0 &&
|
|
450
|
+
frameworkFragmentSliceEnd >= 0 &&
|
|
451
|
+
frameworkFragmentSliceStart < frameworkFragmentSliceEnd
|
|
452
|
+
) {
|
|
453
|
+
frameworkFragmentLines = topActivityLines
|
|
454
|
+
.slice(frameworkFragmentSliceStart, frameworkFragmentSliceEnd)
|
|
455
|
+
.join("\n");
|
|
456
|
+
}
|
|
457
|
+
let androidXFragmentLines = "";
|
|
458
|
+
if (
|
|
459
|
+
androidXFragmentSliceStart >= 0 &&
|
|
460
|
+
androidXFragmentSliceEnd >= 0 &&
|
|
461
|
+
androidXFragmentSliceStart < androidXFragmentSliceEnd
|
|
462
|
+
) {
|
|
463
|
+
androidXFragmentLines = topActivityLines
|
|
464
|
+
.slice(androidXFragmentSliceStart, androidXFragmentSliceEnd)
|
|
465
|
+
.join("\n");
|
|
466
|
+
}
|
|
467
|
+
const fragmentLines = frameworkFragmentLines + "\n" + androidXFragmentLines;
|
|
468
|
+
if (oldFragments != fragmentLines) {
|
|
469
|
+
f();
|
|
470
|
+
oldFragments = fragmentLines;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
async function printCurrentActivityName() {
|
|
476
|
+
const windowOutput = execSync("adb shell dumpsys window displays", {
|
|
477
|
+
encoding: "utf-8",
|
|
478
|
+
});
|
|
479
|
+
const windowLines = windowOutput.split("\n");
|
|
480
|
+
const currentFocusLine = findFirstLines(windowLines, "mCurrentFocus");
|
|
481
|
+
const currentWindow = currentFocusLine?.split(" ")?.last(0)?.removeLast(1);
|
|
482
|
+
if (currentWindow) {
|
|
483
|
+
console.clear();
|
|
484
|
+
console.log(currentWindow);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
async function printCurrentActivityStack() {
|
|
489
|
+
const windowOutput = execSync("adb shell dumpsys window displays", {
|
|
490
|
+
encoding: "utf-8",
|
|
491
|
+
});
|
|
492
|
+
const windowLines = windowOutput.split("\n");
|
|
493
|
+
|
|
494
|
+
const currentFocusAppLine = findFirstLines(windowLines, "mFocusedApp");
|
|
495
|
+
const currentActivity = currentFocusAppLine?.split(" ")?.last(1);
|
|
496
|
+
const stackId = currentFocusAppLine?.split(" ")?.last(0)?.removeLast(1);
|
|
497
|
+
|
|
498
|
+
if (stackId != undefined) {
|
|
499
|
+
const stackLines = windowLines.filter((v) => {
|
|
500
|
+
const s = v.trim();
|
|
501
|
+
return (
|
|
502
|
+
(s.startsWith("*") || s.startsWith("Activity #")) &&
|
|
503
|
+
s.indexOf(stackId) > 0
|
|
504
|
+
);
|
|
505
|
+
});
|
|
506
|
+
const stacks = stackLines.map((v) => v.trim().split(" ").last(1));
|
|
507
|
+
if (stacks[0] != currentActivity) {
|
|
508
|
+
stacks.shift();
|
|
509
|
+
}
|
|
510
|
+
const statckTable = Array<Array<string>>();
|
|
511
|
+
stacks.forEach((v) => statckTable.push([v]));
|
|
512
|
+
console.clear();
|
|
513
|
+
console.log(table(statckTable));
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
async function printCurrentActivityFragments() {
|
|
518
|
+
const windowOutput = execSync("adb shell dumpsys window displays", {
|
|
519
|
+
encoding: "utf-8",
|
|
520
|
+
});
|
|
521
|
+
const windowLines = windowOutput.split("\n");
|
|
522
|
+
|
|
523
|
+
const currentFocusAppLine = findFirstLines(windowLines, "mFocusedApp");
|
|
524
|
+
const currentActivity = currentFocusAppLine?.split(" ")?.last(1);
|
|
525
|
+
|
|
526
|
+
const currentApp = currentActivity?.split("/")?.at(0);
|
|
527
|
+
|
|
528
|
+
const frameworkFragmentLines = Array<Line>();
|
|
529
|
+
const androidxFragmentLines = Array<Line>();
|
|
530
|
+
if (currentApp != undefined) {
|
|
531
|
+
const activityOutput = execSync(
|
|
532
|
+
"adb shell dumpsys activity " + currentApp,
|
|
533
|
+
{ encoding: "utf-8" }
|
|
534
|
+
);
|
|
535
|
+
const activityLines = activityOutput.split("\n");
|
|
536
|
+
|
|
537
|
+
// 1. find top activity
|
|
538
|
+
const activitesLines = findLines(activityLines, "ACTIVITY ");
|
|
539
|
+
let sliceStart = 0;
|
|
540
|
+
let sliceEnd = activityLines.length - 1;
|
|
541
|
+
activitesLines.forEach((v, index) => {
|
|
542
|
+
if (currentActivity && v.content.indexOf(currentActivity) > 0) {
|
|
543
|
+
sliceStart = v.index;
|
|
544
|
+
if (index + 1 <= activitesLines.length - 1) {
|
|
545
|
+
sliceEnd = activitesLines[index + 1].index;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
// 2. cut out the top activity lines
|
|
551
|
+
const topActivityLines = activityLines.slice(sliceStart, sliceEnd);
|
|
552
|
+
// 3. split into framework fragments and androidx fragments
|
|
553
|
+
const splitLine = findLastLines(topActivityLines, "Local FragmentActivity");
|
|
554
|
+
let frameworkLines: Array<string>;
|
|
555
|
+
let androidxLines: Array<string> | undefined;
|
|
556
|
+
if (splitLine != undefined) {
|
|
557
|
+
const splitLineIndex = topActivityLines.indexOf(splitLine);
|
|
558
|
+
frameworkLines = topActivityLines.slice(0, splitLineIndex);
|
|
559
|
+
androidxLines = topActivityLines.slice(splitLineIndex);
|
|
560
|
+
} else {
|
|
561
|
+
frameworkLines = topActivityLines;
|
|
562
|
+
}
|
|
563
|
+
// 4. find all children of between "Active Fragments" and "Added Fragments" node
|
|
564
|
+
const frameworkRangeLines = findRangeLines(
|
|
565
|
+
frameworkLines,
|
|
566
|
+
"Active Fragments",
|
|
567
|
+
"Added Fragments"
|
|
568
|
+
);
|
|
569
|
+
frameworkRangeLines.sort((a, b) => a.start.index - b.start.index);
|
|
570
|
+
frameworkRangeLines.forEach((v) => {
|
|
571
|
+
const firstFragmentLine = frameworkLines?.at(v.start.index + 1);
|
|
572
|
+
if (firstFragmentLine && !isNullLine(firstFragmentLine)) {
|
|
573
|
+
frameworkFragmentLines.push({
|
|
574
|
+
content: handleFragmentLine(firstFragmentLine),
|
|
575
|
+
index: v.start.index + 1,
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
frameworkLines?.forEach((item, index) => {
|
|
579
|
+
if (
|
|
580
|
+
firstFragmentLine &&
|
|
581
|
+
!isNullLine(item) &&
|
|
582
|
+
spaceCount(item) == spaceCount(firstFragmentLine) &&
|
|
583
|
+
index > v.start.index + 1 &&
|
|
584
|
+
index < v.end.index
|
|
585
|
+
) {
|
|
586
|
+
frameworkFragmentLines.push({
|
|
587
|
+
content: handleFragmentLine(item),
|
|
588
|
+
index: index,
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
});
|
|
593
|
+
|
|
594
|
+
if (androidxLines) {
|
|
595
|
+
const activeFragmentsLine = findFirstLines(
|
|
596
|
+
androidxLines,
|
|
597
|
+
"Active Fragments:"
|
|
598
|
+
);
|
|
599
|
+
if (
|
|
600
|
+
activeFragmentsLine != undefined &&
|
|
601
|
+
!activeFragmentsLine.endsWith("Active Fragments:")
|
|
602
|
+
) {
|
|
603
|
+
const androidxLinesText = androidxLines.join("\n");
|
|
604
|
+
const activeFragmentsSliceIndex =
|
|
605
|
+
androidxLinesText.indexOf("Active Fragments:") +
|
|
606
|
+
"Active Fragments:".length;
|
|
607
|
+
androidxLines = (
|
|
608
|
+
androidxLinesText.slice(0, activeFragmentsSliceIndex) +
|
|
609
|
+
"\n" +
|
|
610
|
+
androidxLinesText.slice(activeFragmentsSliceIndex)
|
|
611
|
+
).split("\n");
|
|
612
|
+
}
|
|
613
|
+
const androidxRangeLines = findRangeLines(
|
|
614
|
+
androidxLines,
|
|
615
|
+
"Active Fragments",
|
|
616
|
+
"Added Fragments"
|
|
617
|
+
);
|
|
618
|
+
androidxRangeLines.sort((a, b) => a.start.index - b.start.index);
|
|
619
|
+
|
|
620
|
+
androidxRangeLines.forEach((v) => {
|
|
621
|
+
const firstFragmentLine = androidxLines?.at(v.start.index + 1);
|
|
622
|
+
if (firstFragmentLine && !isNullLine(firstFragmentLine)) {
|
|
623
|
+
androidxFragmentLines.push({
|
|
624
|
+
content: handleFragmentLine(firstFragmentLine),
|
|
625
|
+
index: v.start.index + 1,
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
androidxLines?.forEach((item, index) => {
|
|
629
|
+
if (
|
|
630
|
+
firstFragmentLine &&
|
|
631
|
+
!isNullLine(item) &&
|
|
632
|
+
spaceCount(item) == spaceCount(firstFragmentLine) &&
|
|
633
|
+
index > v.start.index + 1 &&
|
|
634
|
+
index < v.end.index
|
|
635
|
+
) {
|
|
636
|
+
androidxFragmentLines.push({
|
|
637
|
+
content: handleFragmentLine(item),
|
|
638
|
+
index: index,
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
});
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
if (frameworkFragmentLines.length > 0 || androidxFragmentLines.length > 0) {
|
|
647
|
+
const fragmentTable = Array<Array<string>>();
|
|
648
|
+
fragmentTable.push(["activity", currentActivity]);
|
|
649
|
+
if (frameworkFragmentLines.length > 0) {
|
|
650
|
+
frameworkFragmentLines.sort((a, b) => a.index - b.index);
|
|
651
|
+
fragmentTable.push([
|
|
652
|
+
"framework fragments",
|
|
653
|
+
asTree(
|
|
654
|
+
toTreeObject(listToTree(toTreeArray(frameworkFragmentLines))),
|
|
655
|
+
true
|
|
656
|
+
),
|
|
657
|
+
]);
|
|
658
|
+
}
|
|
659
|
+
if (androidxFragmentLines.length > 0) {
|
|
660
|
+
androidxFragmentLines.sort((a, b) => a.index - b.index);
|
|
661
|
+
fragmentTable.push([
|
|
662
|
+
"androidx fragments",
|
|
663
|
+
asTree(
|
|
664
|
+
toTreeObject(listToTree(toTreeArray(androidxFragmentLines))),
|
|
665
|
+
true
|
|
666
|
+
),
|
|
667
|
+
]);
|
|
668
|
+
}
|
|
669
|
+
console.clear();
|
|
670
|
+
console.log(table(fragmentTable));
|
|
671
|
+
} else {
|
|
672
|
+
console.clear();
|
|
673
|
+
const fragmentTable = Array<Array<string>>();
|
|
674
|
+
fragmentTable.push(["activity", currentActivity]);
|
|
675
|
+
console.log(table(fragmentTable));
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
const argv = yargs(process.argv.slice(2))
|
|
680
|
+
.help("help")
|
|
681
|
+
.alias("help", "h")
|
|
682
|
+
.options({
|
|
683
|
+
activity: {
|
|
684
|
+
type: "boolean",
|
|
685
|
+
default: true,
|
|
686
|
+
alias: "a",
|
|
687
|
+
description: "Show the current activity's name",
|
|
688
|
+
},
|
|
689
|
+
stack: {
|
|
690
|
+
type: "boolean",
|
|
691
|
+
default: false,
|
|
692
|
+
alias: "s",
|
|
693
|
+
description: "Show the current activity's stack",
|
|
694
|
+
},
|
|
695
|
+
fragment: {
|
|
696
|
+
type: "boolean",
|
|
697
|
+
default: false,
|
|
698
|
+
alias: "f",
|
|
699
|
+
description: "Show all fragments in the current activity",
|
|
700
|
+
},
|
|
701
|
+
watch: {
|
|
702
|
+
type: "boolean",
|
|
703
|
+
default: false,
|
|
704
|
+
alias: "w",
|
|
705
|
+
description: "Monitor activity or fragments changes in real time",
|
|
706
|
+
},
|
|
707
|
+
all: {
|
|
708
|
+
type: "boolean",
|
|
709
|
+
default: false,
|
|
710
|
+
alias: "A",
|
|
711
|
+
description:
|
|
712
|
+
"Show all information, including the current activity name, activity stack and fragments",
|
|
713
|
+
},
|
|
714
|
+
})
|
|
715
|
+
.locale("en")
|
|
716
|
+
.parseSync();
|
|
717
|
+
|
|
718
|
+
if (argv.all) {
|
|
719
|
+
if (argv.watch) {
|
|
720
|
+
onCurrentWindowChanged(() => printAll());
|
|
721
|
+
} else {
|
|
722
|
+
printAll();
|
|
723
|
+
}
|
|
724
|
+
} else if (argv.fragment) {
|
|
725
|
+
if (argv.watch) {
|
|
726
|
+
onFragmentsChanged(() => printCurrentActivityFragments());
|
|
727
|
+
} else {
|
|
728
|
+
printCurrentActivityFragments();
|
|
729
|
+
}
|
|
730
|
+
} else if (argv.activity) {
|
|
731
|
+
if (argv.stack) {
|
|
732
|
+
if (argv.watch) {
|
|
733
|
+
onCurrentWindowChanged(() => printCurrentActivityStack());
|
|
734
|
+
} else {
|
|
735
|
+
printCurrentActivityStack();
|
|
736
|
+
}
|
|
737
|
+
} else {
|
|
738
|
+
if (argv.watch) {
|
|
739
|
+
onCurrentWindowChanged(() => printCurrentActivityName());
|
|
740
|
+
} else {
|
|
741
|
+
printCurrentActivityName();
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
}
|