currentactivity 1.0.0 → 1.0.1
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 +92 -2
- package/build/index.js +343 -14
- package/package.json +7 -5
- package/src/index.ts +409 -42
package/README.md
CHANGED
|
@@ -21,14 +21,104 @@ 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.1
|
|
120
|
+
* Added more options for more flexible output
|
|
121
|
+
|
|
32
122
|
* 1.0.0
|
|
33
123
|
* Initial version
|
|
34
124
|
|
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
|
});
|
|
@@ -151,14 +173,32 @@ function printDumpInfo() {
|
|
|
151
173
|
}
|
|
152
174
|
});
|
|
153
175
|
}
|
|
176
|
+
function handleFragmentLine(content) {
|
|
177
|
+
var _a;
|
|
178
|
+
if (content.length > 160) {
|
|
179
|
+
if (content.trimStart().startsWith("SupportRequestManagerFragment")) {
|
|
180
|
+
const parentIndex = content.indexOf("{parent=");
|
|
181
|
+
const parentText = content.substring(parentIndex);
|
|
182
|
+
return (content.substring(0, parentIndex) + ((_a = parentText.split(" ")) === null || _a === void 0 ? void 0 : _a.at(0)) + "}");
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
return content.substring(0, 160);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return content;
|
|
189
|
+
}
|
|
190
|
+
function isNullLine(content) {
|
|
191
|
+
if (content.trim() == "null")
|
|
192
|
+
return true;
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
154
195
|
function toTreeArray(arr) {
|
|
155
196
|
const result = Array();
|
|
156
197
|
arr.forEach((v, index) => {
|
|
157
198
|
result.push({
|
|
158
199
|
id: index.toString(),
|
|
159
200
|
content: v.content.trim(),
|
|
160
|
-
parentId: findParentIndex(arr.map((item) => item.content), v.content)
|
|
161
|
-
.toString(),
|
|
201
|
+
parentId: findParentIndex(arr.map((item) => item.content), v.content).toString(),
|
|
162
202
|
children: null,
|
|
163
203
|
});
|
|
164
204
|
});
|
|
@@ -248,7 +288,7 @@ function spaceCount(value) {
|
|
|
248
288
|
function findLines(lines, target) {
|
|
249
289
|
const result = Array();
|
|
250
290
|
lines.forEach((v, i) => {
|
|
251
|
-
if (v.indexOf(target)
|
|
291
|
+
if (v.indexOf(target) >= 0) {
|
|
252
292
|
result.push({
|
|
253
293
|
content: v,
|
|
254
294
|
index: i,
|
|
@@ -261,6 +301,15 @@ function findFirstLines(lines, target) {
|
|
|
261
301
|
var _a;
|
|
262
302
|
return (_a = findLines(lines, target).at(0)) === null || _a === void 0 ? void 0 : _a.content;
|
|
263
303
|
}
|
|
304
|
+
function findFirstLineIndex(lines, target) {
|
|
305
|
+
const firstLine = findLines(lines, target).at(0);
|
|
306
|
+
if (firstLine == undefined) {
|
|
307
|
+
return -1;
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
return firstLine.index;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
264
313
|
function findLastLines(lines, target) {
|
|
265
314
|
var _a;
|
|
266
315
|
return (_a = findLines(lines, target).last(0)) === null || _a === void 0 ? void 0 : _a.content;
|
|
@@ -289,15 +338,295 @@ function findRangeLines(lines, start, end) {
|
|
|
289
338
|
return children;
|
|
290
339
|
}
|
|
291
340
|
let oldActivity = "";
|
|
292
|
-
function
|
|
341
|
+
function onCurrentWindowChanged(f) {
|
|
293
342
|
return __awaiter(this, void 0, void 0, function* () {
|
|
294
343
|
while (true) {
|
|
295
344
|
const currentActivity = (0, child_process_1.execSync)("adb shell dumpsys window displays | grep -E 'mCurrentFocus'", { encoding: "utf-8" });
|
|
296
345
|
if (oldActivity != currentActivity) {
|
|
297
|
-
|
|
346
|
+
f();
|
|
298
347
|
oldActivity = currentActivity;
|
|
299
348
|
}
|
|
300
349
|
}
|
|
301
350
|
});
|
|
302
351
|
}
|
|
303
|
-
|
|
352
|
+
let oldFragments = "";
|
|
353
|
+
function onFragmentsChanged(f) {
|
|
354
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
355
|
+
while (true) {
|
|
356
|
+
const activityOutput = (0, child_process_1.execSync)("adb shell dumpsys activity top", {
|
|
357
|
+
encoding: "utf-8",
|
|
358
|
+
});
|
|
359
|
+
const activityLines = activityOutput.split("\n");
|
|
360
|
+
const topActivityLine = findLastLines(activityLines, "TASK");
|
|
361
|
+
let sliceStart = activityLines.indexOf(topActivityLine);
|
|
362
|
+
let sliceEnd = activityLines.length - 1;
|
|
363
|
+
const topActivityLines = activityLines.slice(sliceStart, sliceEnd);
|
|
364
|
+
const frameworkFragmentSliceStart = findFirstLineIndex(topActivityLines, "Local Activity");
|
|
365
|
+
const frameworkFragmentSliceEnd = findFirstLineIndex(topActivityLines, "ViewRoot:");
|
|
366
|
+
const androidXFragmentSliceStart = findFirstLineIndex(topActivityLines, "Local FragmentActivity");
|
|
367
|
+
const androidXFragmentSliceEnd = topActivityLines.length - 1;
|
|
368
|
+
let frameworkFragmentLines = "";
|
|
369
|
+
if (frameworkFragmentSliceStart >= 0 &&
|
|
370
|
+
frameworkFragmentSliceEnd >= 0 &&
|
|
371
|
+
frameworkFragmentSliceStart < frameworkFragmentSliceEnd) {
|
|
372
|
+
frameworkFragmentLines = topActivityLines
|
|
373
|
+
.slice(frameworkFragmentSliceStart, frameworkFragmentSliceEnd)
|
|
374
|
+
.join("\n");
|
|
375
|
+
}
|
|
376
|
+
let androidXFragmentLines = "";
|
|
377
|
+
if (androidXFragmentSliceStart >= 0 &&
|
|
378
|
+
androidXFragmentSliceEnd >= 0 &&
|
|
379
|
+
androidXFragmentSliceStart < androidXFragmentSliceEnd) {
|
|
380
|
+
androidXFragmentLines = topActivityLines
|
|
381
|
+
.slice(androidXFragmentSliceStart, androidXFragmentSliceEnd)
|
|
382
|
+
.join("\n");
|
|
383
|
+
}
|
|
384
|
+
const fragmentLines = frameworkFragmentLines + "\n" + androidXFragmentLines;
|
|
385
|
+
if (oldFragments != fragmentLines) {
|
|
386
|
+
f();
|
|
387
|
+
oldFragments = fragmentLines;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
function printCurrentActivityName() {
|
|
393
|
+
var _a, _b;
|
|
394
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
395
|
+
const windowOutput = (0, child_process_1.execSync)("adb shell dumpsys window displays", {
|
|
396
|
+
encoding: "utf-8",
|
|
397
|
+
});
|
|
398
|
+
const windowLines = windowOutput.split("\n");
|
|
399
|
+
const currentFocusLine = findFirstLines(windowLines, "mCurrentFocus");
|
|
400
|
+
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);
|
|
401
|
+
if (currentWindow) {
|
|
402
|
+
console.clear();
|
|
403
|
+
console.log(currentWindow);
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
function printCurrentActivityStack() {
|
|
408
|
+
var _a, _b, _c;
|
|
409
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
410
|
+
const windowOutput = (0, child_process_1.execSync)("adb shell dumpsys window displays", {
|
|
411
|
+
encoding: "utf-8",
|
|
412
|
+
});
|
|
413
|
+
const windowLines = windowOutput.split("\n");
|
|
414
|
+
const currentFocusAppLine = findFirstLines(windowLines, "mFocusedApp");
|
|
415
|
+
const currentActivity = (_a = currentFocusAppLine === null || currentFocusAppLine === void 0 ? void 0 : currentFocusAppLine.split(" ")) === null || _a === void 0 ? void 0 : _a.last(1);
|
|
416
|
+
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);
|
|
417
|
+
if (stackId != undefined) {
|
|
418
|
+
const stackLines = windowLines.filter((v) => {
|
|
419
|
+
const s = v.trim();
|
|
420
|
+
return s.startsWith("*") && s.indexOf(stackId) > 0;
|
|
421
|
+
});
|
|
422
|
+
const stacks = stackLines.map((v) => v.trim().split(" ")[3]);
|
|
423
|
+
if (stacks[0] != currentActivity) {
|
|
424
|
+
stacks.shift();
|
|
425
|
+
}
|
|
426
|
+
const statckTable = Array();
|
|
427
|
+
stacks.forEach((v) => statckTable.push([v]));
|
|
428
|
+
console.clear();
|
|
429
|
+
console.log((0, table_1.table)(statckTable));
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
function printCurrentActivityFragments() {
|
|
434
|
+
var _a, _b;
|
|
435
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
436
|
+
const windowOutput = (0, child_process_1.execSync)("adb shell dumpsys window displays", {
|
|
437
|
+
encoding: "utf-8",
|
|
438
|
+
});
|
|
439
|
+
const windowLines = windowOutput.split("\n");
|
|
440
|
+
const currentFocusAppLine = findFirstLines(windowLines, "mFocusedApp");
|
|
441
|
+
const currentActivity = (_a = currentFocusAppLine === null || currentFocusAppLine === void 0 ? void 0 : currentFocusAppLine.split(" ")) === null || _a === void 0 ? void 0 : _a.last(1);
|
|
442
|
+
const currentApp = (_b = currentActivity === null || currentActivity === void 0 ? void 0 : currentActivity.split("/")) === null || _b === void 0 ? void 0 : _b.at(0);
|
|
443
|
+
const frameworkFragmentLines = Array();
|
|
444
|
+
const androidxFragmentLines = Array();
|
|
445
|
+
if (currentApp != undefined) {
|
|
446
|
+
const activityOutput = (0, child_process_1.execSync)("adb shell dumpsys activity " + currentApp, { encoding: "utf-8" });
|
|
447
|
+
const activityLines = activityOutput.split("\n");
|
|
448
|
+
// 1. find top activity
|
|
449
|
+
const activitesLines = findLines(activityLines, "ACTIVITY ");
|
|
450
|
+
let sliceStart = 0;
|
|
451
|
+
let sliceEnd = activityLines.length - 1;
|
|
452
|
+
activitesLines.forEach((v, index) => {
|
|
453
|
+
if (currentActivity && v.content.indexOf(currentActivity) > 0) {
|
|
454
|
+
sliceStart = v.index;
|
|
455
|
+
if (index + 1 <= activitesLines.length - 1) {
|
|
456
|
+
sliceEnd = activitesLines[index + 1].index;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
// 2. cut out the top activity lines
|
|
461
|
+
const topActivityLines = activityLines.slice(sliceStart, sliceEnd);
|
|
462
|
+
// 3. split into framework fragments and androidx fragments
|
|
463
|
+
const splitLine = findLastLines(topActivityLines, "Local FragmentActivity");
|
|
464
|
+
let frameworkLines;
|
|
465
|
+
let androidxLines;
|
|
466
|
+
if (splitLine != undefined) {
|
|
467
|
+
const splitLineIndex = topActivityLines.indexOf(splitLine);
|
|
468
|
+
frameworkLines = topActivityLines.slice(0, splitLineIndex);
|
|
469
|
+
androidxLines = topActivityLines.slice(splitLineIndex);
|
|
470
|
+
}
|
|
471
|
+
else {
|
|
472
|
+
frameworkLines = topActivityLines;
|
|
473
|
+
}
|
|
474
|
+
// 4. find all children of between "Active Fragments" and "Added Fragments" node
|
|
475
|
+
const frameworkRangeLines = findRangeLines(frameworkLines, "Active Fragments", "Added Fragments");
|
|
476
|
+
frameworkRangeLines.sort((a, b) => a.start.index - b.start.index);
|
|
477
|
+
frameworkRangeLines.forEach((v) => {
|
|
478
|
+
const firstFragmentLine = frameworkLines === null || frameworkLines === void 0 ? void 0 : frameworkLines.at(v.start.index + 1);
|
|
479
|
+
if (firstFragmentLine && !isNullLine(firstFragmentLine)) {
|
|
480
|
+
frameworkFragmentLines.push({
|
|
481
|
+
content: handleFragmentLine(firstFragmentLine),
|
|
482
|
+
index: v.start.index + 1,
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
frameworkLines === null || frameworkLines === void 0 ? void 0 : frameworkLines.forEach((item, index) => {
|
|
486
|
+
if (firstFragmentLine &&
|
|
487
|
+
!isNullLine(item) &&
|
|
488
|
+
spaceCount(item) == spaceCount(firstFragmentLine) &&
|
|
489
|
+
index > v.start.index + 1 &&
|
|
490
|
+
index < v.end.index) {
|
|
491
|
+
frameworkFragmentLines.push({
|
|
492
|
+
content: handleFragmentLine(item),
|
|
493
|
+
index: index,
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
if (androidxLines) {
|
|
499
|
+
const activeFragmentsLine = findFirstLines(androidxLines, "Active Fragments:");
|
|
500
|
+
if (activeFragmentsLine != undefined &&
|
|
501
|
+
!activeFragmentsLine.endsWith("Active Fragments:")) {
|
|
502
|
+
const androidxLinesText = androidxLines.join("\n");
|
|
503
|
+
const activeFragmentsSliceIndex = androidxLinesText.indexOf("Active Fragments:") +
|
|
504
|
+
"Active Fragments:".length;
|
|
505
|
+
androidxLines = (androidxLinesText.slice(0, activeFragmentsSliceIndex) +
|
|
506
|
+
"\n" +
|
|
507
|
+
androidxLinesText.slice(activeFragmentsSliceIndex)).split("\n");
|
|
508
|
+
}
|
|
509
|
+
const androidxRangeLines = findRangeLines(androidxLines, "Active Fragments", "Added Fragments");
|
|
510
|
+
androidxRangeLines.sort((a, b) => a.start.index - b.start.index);
|
|
511
|
+
androidxRangeLines.forEach((v) => {
|
|
512
|
+
const firstFragmentLine = androidxLines === null || androidxLines === void 0 ? void 0 : androidxLines.at(v.start.index + 1);
|
|
513
|
+
if (firstFragmentLine && !isNullLine(firstFragmentLine)) {
|
|
514
|
+
androidxFragmentLines.push({
|
|
515
|
+
content: handleFragmentLine(firstFragmentLine),
|
|
516
|
+
index: v.start.index + 1,
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
androidxLines === null || androidxLines === void 0 ? void 0 : androidxLines.forEach((item, index) => {
|
|
520
|
+
if (firstFragmentLine &&
|
|
521
|
+
!isNullLine(item) &&
|
|
522
|
+
spaceCount(item) == spaceCount(firstFragmentLine) &&
|
|
523
|
+
index > v.start.index + 1 &&
|
|
524
|
+
index < v.end.index) {
|
|
525
|
+
androidxFragmentLines.push({
|
|
526
|
+
content: handleFragmentLine(item),
|
|
527
|
+
index: index,
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
if (frameworkFragmentLines.length > 0 || androidxFragmentLines.length > 0) {
|
|
535
|
+
const fragmentTable = Array();
|
|
536
|
+
fragmentTable.push(["activity", currentActivity]);
|
|
537
|
+
if (frameworkFragmentLines.length > 0) {
|
|
538
|
+
frameworkFragmentLines.sort((a, b) => a.index - b.index);
|
|
539
|
+
fragmentTable.push([
|
|
540
|
+
"framework fragments",
|
|
541
|
+
(0, treeify_1.asTree)(toTreeObject(listToTree(toTreeArray(frameworkFragmentLines))), true),
|
|
542
|
+
]);
|
|
543
|
+
}
|
|
544
|
+
if (androidxFragmentLines.length > 0) {
|
|
545
|
+
androidxFragmentLines.sort((a, b) => a.index - b.index);
|
|
546
|
+
fragmentTable.push([
|
|
547
|
+
"androidx fragments",
|
|
548
|
+
(0, treeify_1.asTree)(toTreeObject(listToTree(toTreeArray(androidxFragmentLines))), true),
|
|
549
|
+
]);
|
|
550
|
+
}
|
|
551
|
+
console.clear();
|
|
552
|
+
console.log((0, table_1.table)(fragmentTable));
|
|
553
|
+
}
|
|
554
|
+
else {
|
|
555
|
+
console.clear();
|
|
556
|
+
const fragmentTable = Array();
|
|
557
|
+
fragmentTable.push(["activity", currentActivity]);
|
|
558
|
+
console.log((0, table_1.table)(fragmentTable));
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
const argv = (0, yargs_1.default)(process.argv.slice(2))
|
|
563
|
+
.help("help")
|
|
564
|
+
.alias("help", "h")
|
|
565
|
+
.options({
|
|
566
|
+
activity: {
|
|
567
|
+
type: "boolean",
|
|
568
|
+
default: true,
|
|
569
|
+
alias: "a",
|
|
570
|
+
description: "Show the current activity's name",
|
|
571
|
+
},
|
|
572
|
+
stack: {
|
|
573
|
+
type: "boolean",
|
|
574
|
+
default: false,
|
|
575
|
+
alias: "s",
|
|
576
|
+
description: "Show the current activity's stack",
|
|
577
|
+
},
|
|
578
|
+
fragment: {
|
|
579
|
+
type: "boolean",
|
|
580
|
+
default: false,
|
|
581
|
+
alias: "f",
|
|
582
|
+
description: "Show all fragments in the current activity",
|
|
583
|
+
},
|
|
584
|
+
watch: {
|
|
585
|
+
type: "boolean",
|
|
586
|
+
default: false,
|
|
587
|
+
alias: "w",
|
|
588
|
+
description: "Monitor activity or fragments changes in real time",
|
|
589
|
+
},
|
|
590
|
+
all: {
|
|
591
|
+
type: "boolean",
|
|
592
|
+
default: false,
|
|
593
|
+
alias: "A",
|
|
594
|
+
description: "Show all information, including the current activity name, activity stack and fragments",
|
|
595
|
+
},
|
|
596
|
+
})
|
|
597
|
+
.locale("en")
|
|
598
|
+
.parseSync();
|
|
599
|
+
if (argv.all) {
|
|
600
|
+
if (argv.watch) {
|
|
601
|
+
onCurrentWindowChanged(() => printAll());
|
|
602
|
+
}
|
|
603
|
+
else {
|
|
604
|
+
printAll();
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
else if (argv.fragment) {
|
|
608
|
+
if (argv.watch) {
|
|
609
|
+
onFragmentsChanged(() => printCurrentActivityFragments());
|
|
610
|
+
}
|
|
611
|
+
else {
|
|
612
|
+
printCurrentActivityFragments();
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
else if (argv.activity) {
|
|
616
|
+
if (argv.stack) {
|
|
617
|
+
if (argv.watch) {
|
|
618
|
+
onCurrentWindowChanged(() => printCurrentActivityStack());
|
|
619
|
+
}
|
|
620
|
+
else {
|
|
621
|
+
printCurrentActivityStack();
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
else {
|
|
625
|
+
if (argv.watch) {
|
|
626
|
+
onCurrentWindowChanged(() => printCurrentActivityName());
|
|
627
|
+
}
|
|
628
|
+
else {
|
|
629
|
+
printCurrentActivityName();
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "currentactivity",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
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
|
|
|
@@ -143,7 +167,7 @@ async function printDumpInfo() {
|
|
|
143
167
|
console.log(
|
|
144
168
|
table(statckTable, {
|
|
145
169
|
header: { content: "activity stack", alignment: "center" },
|
|
146
|
-
})
|
|
170
|
+
})
|
|
147
171
|
);
|
|
148
172
|
}
|
|
149
173
|
|
|
@@ -156,7 +180,7 @@ async function printDumpInfo() {
|
|
|
156
180
|
"framework fragments",
|
|
157
181
|
asTree(
|
|
158
182
|
toTreeObject(listToTree(toTreeArray(frameworkFragmentLines))),
|
|
159
|
-
true
|
|
183
|
+
true
|
|
160
184
|
),
|
|
161
185
|
]);
|
|
162
186
|
}
|
|
@@ -166,7 +190,7 @@ async function printDumpInfo() {
|
|
|
166
190
|
"androidx fragments",
|
|
167
191
|
asTree(
|
|
168
192
|
toTreeObject(listToTree(toTreeArray(androidxFragmentLines))),
|
|
169
|
-
true
|
|
193
|
+
true
|
|
170
194
|
),
|
|
171
195
|
]);
|
|
172
196
|
}
|
|
@@ -174,11 +198,31 @@ async function printDumpInfo() {
|
|
|
174
198
|
console.log(
|
|
175
199
|
table(fragmentTable, {
|
|
176
200
|
header: { content: "fragments", alignment: "center" },
|
|
177
|
-
})
|
|
201
|
+
})
|
|
178
202
|
);
|
|
179
203
|
}
|
|
180
204
|
}
|
|
181
205
|
|
|
206
|
+
function handleFragmentLine(content: string): string {
|
|
207
|
+
if (content.length > 160) {
|
|
208
|
+
if (content.trimStart().startsWith("SupportRequestManagerFragment")) {
|
|
209
|
+
const parentIndex = content.indexOf("{parent=");
|
|
210
|
+
const parentText = content.substring(parentIndex);
|
|
211
|
+
return (
|
|
212
|
+
content.substring(0, parentIndex) + parentText.split(" ")?.at(0) + "}"
|
|
213
|
+
);
|
|
214
|
+
} else {
|
|
215
|
+
return content.substring(0, 160);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return content;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function isNullLine(content: string): boolean {
|
|
222
|
+
if (content.trim() == "null") return true;
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
|
|
182
226
|
type Tree = {
|
|
183
227
|
id: string;
|
|
184
228
|
content: string;
|
|
@@ -192,18 +236,17 @@ function toTreeArray(arr: Array<Line>): Array<Tree> {
|
|
|
192
236
|
result.push({
|
|
193
237
|
id: index.toString(),
|
|
194
238
|
content: v.content.trim(),
|
|
195
|
-
parentId: findParentIndex(
|
|
196
|
-
.
|
|
239
|
+
parentId: findParentIndex(
|
|
240
|
+
arr.map((item) => item.content),
|
|
241
|
+
v.content
|
|
242
|
+
).toString(),
|
|
197
243
|
children: null,
|
|
198
244
|
});
|
|
199
245
|
});
|
|
200
246
|
return result;
|
|
201
247
|
}
|
|
202
248
|
|
|
203
|
-
function findParentIndex(
|
|
204
|
-
arr: Array<string>,
|
|
205
|
-
target: string,
|
|
206
|
-
): number {
|
|
249
|
+
function findParentIndex(arr: Array<string>, target: string): number {
|
|
207
250
|
const targetIndex = arr.indexOf(target);
|
|
208
251
|
if (targetIndex < 0) return -1;
|
|
209
252
|
let parentIndex = -1;
|
|
@@ -267,15 +310,15 @@ function findChildren(arr: Array<string>, target: string): Array<string> {
|
|
|
267
310
|
const result = Array<string>();
|
|
268
311
|
const targetIndex = arr.indexOf(target);
|
|
269
312
|
if (targetIndex < 0 || targetIndex == arr.length - 1) return result;
|
|
270
|
-
const nextBrotherIndex = arr.findIndex(
|
|
271
|
-
spaceCount(v) == spaceCount(target) && i > targetIndex
|
|
313
|
+
const nextBrotherIndex = arr.findIndex(
|
|
314
|
+
(v, i) => spaceCount(v) == spaceCount(target) && i > targetIndex
|
|
272
315
|
);
|
|
273
316
|
if (nextBrotherIndex == targetIndex + 1) return result;
|
|
274
317
|
const firstChild = arr.at(targetIndex + 1);
|
|
275
318
|
if (firstChild) {
|
|
276
319
|
const range = arr.slice(targetIndex, nextBrotherIndex);
|
|
277
|
-
const children = range.filter(
|
|
278
|
-
spaceCount(v) == spaceCount(firstChild)
|
|
320
|
+
const children = range.filter(
|
|
321
|
+
(v) => spaceCount(v) == spaceCount(firstChild)
|
|
279
322
|
);
|
|
280
323
|
result.concat(children);
|
|
281
324
|
}
|
|
@@ -292,13 +335,10 @@ type Line = {
|
|
|
292
335
|
index: number;
|
|
293
336
|
};
|
|
294
337
|
|
|
295
|
-
function findLines(
|
|
296
|
-
lines: Array<string>,
|
|
297
|
-
target: string,
|
|
298
|
-
): Array<Line> {
|
|
338
|
+
function findLines(lines: Array<string>, target: string): Array<Line> {
|
|
299
339
|
const result = Array<Line>();
|
|
300
340
|
lines.forEach((v, i) => {
|
|
301
|
-
if (v.indexOf(target)
|
|
341
|
+
if (v.indexOf(target) >= 0) {
|
|
302
342
|
result.push({
|
|
303
343
|
content: v,
|
|
304
344
|
index: i,
|
|
@@ -310,14 +350,23 @@ function findLines(
|
|
|
310
350
|
|
|
311
351
|
function findFirstLines(
|
|
312
352
|
lines: Array<string>,
|
|
313
|
-
target: string
|
|
353
|
+
target: string
|
|
314
354
|
): string | undefined {
|
|
315
355
|
return findLines(lines, target).at(0)?.content;
|
|
316
356
|
}
|
|
317
357
|
|
|
358
|
+
function findFirstLineIndex(lines: Array<string>, target: string): number {
|
|
359
|
+
const firstLine = findLines(lines, target).at(0);
|
|
360
|
+
if (firstLine == undefined) {
|
|
361
|
+
return -1;
|
|
362
|
+
} else {
|
|
363
|
+
return firstLine.index;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
318
367
|
function findLastLines(
|
|
319
368
|
lines: Array<string>,
|
|
320
|
-
target: string
|
|
369
|
+
target: string
|
|
321
370
|
): string | undefined {
|
|
322
371
|
return findLines(lines, target).last(0)?.content;
|
|
323
372
|
}
|
|
@@ -330,7 +379,7 @@ type RangeLine = {
|
|
|
330
379
|
function findRangeLines(
|
|
331
380
|
lines: Array<string>,
|
|
332
381
|
start: string,
|
|
333
|
-
end: string
|
|
382
|
+
end: string
|
|
334
383
|
): Array<RangeLine> {
|
|
335
384
|
const startLines = findLines(lines, start);
|
|
336
385
|
const endLines = findLines(lines, end);
|
|
@@ -355,17 +404,335 @@ function findRangeLines(
|
|
|
355
404
|
}
|
|
356
405
|
|
|
357
406
|
let oldActivity = "";
|
|
358
|
-
async function
|
|
407
|
+
async function onCurrentWindowChanged(f: () => void) {
|
|
359
408
|
while (true) {
|
|
360
409
|
const currentActivity = execSync(
|
|
361
410
|
"adb shell dumpsys window displays | grep -E 'mCurrentFocus'",
|
|
362
|
-
{ encoding: "utf-8" }
|
|
411
|
+
{ encoding: "utf-8" }
|
|
363
412
|
);
|
|
364
413
|
if (oldActivity != currentActivity) {
|
|
365
|
-
|
|
414
|
+
f();
|
|
366
415
|
oldActivity = currentActivity;
|
|
367
416
|
}
|
|
368
417
|
}
|
|
369
418
|
}
|
|
370
419
|
|
|
371
|
-
|
|
420
|
+
let oldFragments = "";
|
|
421
|
+
async function onFragmentsChanged(f: () => void) {
|
|
422
|
+
while (true) {
|
|
423
|
+
const activityOutput = execSync("adb shell dumpsys activity top", {
|
|
424
|
+
encoding: "utf-8",
|
|
425
|
+
});
|
|
426
|
+
const activityLines = activityOutput.split("\n");
|
|
427
|
+
const topActivityLine = findLastLines(activityLines, "TASK");
|
|
428
|
+
let sliceStart = activityLines.indexOf(topActivityLine);
|
|
429
|
+
let sliceEnd = activityLines.length - 1;
|
|
430
|
+
const topActivityLines = activityLines.slice(sliceStart, sliceEnd);
|
|
431
|
+
const frameworkFragmentSliceStart = findFirstLineIndex(
|
|
432
|
+
topActivityLines,
|
|
433
|
+
"Local Activity"
|
|
434
|
+
);
|
|
435
|
+
const frameworkFragmentSliceEnd = findFirstLineIndex(
|
|
436
|
+
topActivityLines,
|
|
437
|
+
"ViewRoot:"
|
|
438
|
+
);
|
|
439
|
+
const androidXFragmentSliceStart = findFirstLineIndex(
|
|
440
|
+
topActivityLines,
|
|
441
|
+
"Local FragmentActivity"
|
|
442
|
+
);
|
|
443
|
+
const androidXFragmentSliceEnd = topActivityLines.length - 1;
|
|
444
|
+
let frameworkFragmentLines = "";
|
|
445
|
+
if (
|
|
446
|
+
frameworkFragmentSliceStart >= 0 &&
|
|
447
|
+
frameworkFragmentSliceEnd >= 0 &&
|
|
448
|
+
frameworkFragmentSliceStart < frameworkFragmentSliceEnd
|
|
449
|
+
) {
|
|
450
|
+
frameworkFragmentLines = topActivityLines
|
|
451
|
+
.slice(frameworkFragmentSliceStart, frameworkFragmentSliceEnd)
|
|
452
|
+
.join("\n");
|
|
453
|
+
}
|
|
454
|
+
let androidXFragmentLines = "";
|
|
455
|
+
if (
|
|
456
|
+
androidXFragmentSliceStart >= 0 &&
|
|
457
|
+
androidXFragmentSliceEnd >= 0 &&
|
|
458
|
+
androidXFragmentSliceStart < androidXFragmentSliceEnd
|
|
459
|
+
) {
|
|
460
|
+
androidXFragmentLines = topActivityLines
|
|
461
|
+
.slice(androidXFragmentSliceStart, androidXFragmentSliceEnd)
|
|
462
|
+
.join("\n");
|
|
463
|
+
}
|
|
464
|
+
const fragmentLines = frameworkFragmentLines + "\n" + androidXFragmentLines;
|
|
465
|
+
if (oldFragments != fragmentLines) {
|
|
466
|
+
f();
|
|
467
|
+
oldFragments = fragmentLines;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
async function printCurrentActivityName() {
|
|
473
|
+
const windowOutput = execSync("adb shell dumpsys window displays", {
|
|
474
|
+
encoding: "utf-8",
|
|
475
|
+
});
|
|
476
|
+
const windowLines = windowOutput.split("\n");
|
|
477
|
+
const currentFocusLine = findFirstLines(windowLines, "mCurrentFocus");
|
|
478
|
+
const currentWindow = currentFocusLine?.split(" ")?.last(0)?.removeLast(1);
|
|
479
|
+
if (currentWindow) {
|
|
480
|
+
console.clear();
|
|
481
|
+
console.log(currentWindow);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
async function printCurrentActivityStack() {
|
|
486
|
+
const windowOutput = execSync("adb shell dumpsys window displays", {
|
|
487
|
+
encoding: "utf-8",
|
|
488
|
+
});
|
|
489
|
+
const windowLines = windowOutput.split("\n");
|
|
490
|
+
|
|
491
|
+
const currentFocusAppLine = findFirstLines(windowLines, "mFocusedApp");
|
|
492
|
+
const currentActivity = currentFocusAppLine?.split(" ")?.last(1);
|
|
493
|
+
const stackId = currentFocusAppLine?.split(" ")?.last(0)?.removeLast(1);
|
|
494
|
+
|
|
495
|
+
if (stackId != undefined) {
|
|
496
|
+
const stackLines = windowLines.filter((v) => {
|
|
497
|
+
const s = v.trim();
|
|
498
|
+
return s.startsWith("*") && s.indexOf(stackId) > 0;
|
|
499
|
+
});
|
|
500
|
+
const stacks = stackLines.map((v) => v.trim().split(" ")[3]);
|
|
501
|
+
if (stacks[0] != currentActivity) {
|
|
502
|
+
stacks.shift();
|
|
503
|
+
}
|
|
504
|
+
const statckTable = Array<Array<string>>();
|
|
505
|
+
stacks.forEach((v) => statckTable.push([v]));
|
|
506
|
+
console.clear();
|
|
507
|
+
console.log(table(statckTable));
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
async function printCurrentActivityFragments() {
|
|
512
|
+
const windowOutput = execSync("adb shell dumpsys window displays", {
|
|
513
|
+
encoding: "utf-8",
|
|
514
|
+
});
|
|
515
|
+
const windowLines = windowOutput.split("\n");
|
|
516
|
+
|
|
517
|
+
const currentFocusAppLine = findFirstLines(windowLines, "mFocusedApp");
|
|
518
|
+
const currentActivity = currentFocusAppLine?.split(" ")?.last(1);
|
|
519
|
+
|
|
520
|
+
const currentApp = currentActivity?.split("/")?.at(0);
|
|
521
|
+
|
|
522
|
+
const frameworkFragmentLines = Array<Line>();
|
|
523
|
+
const androidxFragmentLines = Array<Line>();
|
|
524
|
+
if (currentApp != undefined) {
|
|
525
|
+
const activityOutput = execSync(
|
|
526
|
+
"adb shell dumpsys activity " + currentApp,
|
|
527
|
+
{ encoding: "utf-8" }
|
|
528
|
+
);
|
|
529
|
+
const activityLines = activityOutput.split("\n");
|
|
530
|
+
|
|
531
|
+
// 1. find top activity
|
|
532
|
+
const activitesLines = findLines(activityLines, "ACTIVITY ");
|
|
533
|
+
let sliceStart = 0;
|
|
534
|
+
let sliceEnd = activityLines.length - 1;
|
|
535
|
+
activitesLines.forEach((v, index) => {
|
|
536
|
+
if (currentActivity && v.content.indexOf(currentActivity) > 0) {
|
|
537
|
+
sliceStart = v.index;
|
|
538
|
+
if (index + 1 <= activitesLines.length - 1) {
|
|
539
|
+
sliceEnd = activitesLines[index + 1].index;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
// 2. cut out the top activity lines
|
|
545
|
+
const topActivityLines = activityLines.slice(sliceStart, sliceEnd);
|
|
546
|
+
// 3. split into framework fragments and androidx fragments
|
|
547
|
+
const splitLine = findLastLines(topActivityLines, "Local FragmentActivity");
|
|
548
|
+
let frameworkLines: Array<string>;
|
|
549
|
+
let androidxLines: Array<string> | undefined;
|
|
550
|
+
if (splitLine != undefined) {
|
|
551
|
+
const splitLineIndex = topActivityLines.indexOf(splitLine);
|
|
552
|
+
frameworkLines = topActivityLines.slice(0, splitLineIndex);
|
|
553
|
+
androidxLines = topActivityLines.slice(splitLineIndex);
|
|
554
|
+
} else {
|
|
555
|
+
frameworkLines = topActivityLines;
|
|
556
|
+
}
|
|
557
|
+
// 4. find all children of between "Active Fragments" and "Added Fragments" node
|
|
558
|
+
const frameworkRangeLines = findRangeLines(
|
|
559
|
+
frameworkLines,
|
|
560
|
+
"Active Fragments",
|
|
561
|
+
"Added Fragments"
|
|
562
|
+
);
|
|
563
|
+
frameworkRangeLines.sort((a, b) => a.start.index - b.start.index);
|
|
564
|
+
frameworkRangeLines.forEach((v) => {
|
|
565
|
+
const firstFragmentLine = frameworkLines?.at(v.start.index + 1);
|
|
566
|
+
if (firstFragmentLine && !isNullLine(firstFragmentLine)) {
|
|
567
|
+
frameworkFragmentLines.push({
|
|
568
|
+
content: handleFragmentLine(firstFragmentLine),
|
|
569
|
+
index: v.start.index + 1,
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
frameworkLines?.forEach((item, index) => {
|
|
573
|
+
if (
|
|
574
|
+
firstFragmentLine &&
|
|
575
|
+
!isNullLine(item) &&
|
|
576
|
+
spaceCount(item) == spaceCount(firstFragmentLine) &&
|
|
577
|
+
index > v.start.index + 1 &&
|
|
578
|
+
index < v.end.index
|
|
579
|
+
) {
|
|
580
|
+
frameworkFragmentLines.push({
|
|
581
|
+
content: handleFragmentLine(item),
|
|
582
|
+
index: index,
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
if (androidxLines) {
|
|
589
|
+
const activeFragmentsLine = findFirstLines(
|
|
590
|
+
androidxLines,
|
|
591
|
+
"Active Fragments:"
|
|
592
|
+
);
|
|
593
|
+
if (
|
|
594
|
+
activeFragmentsLine != undefined &&
|
|
595
|
+
!activeFragmentsLine.endsWith("Active Fragments:")
|
|
596
|
+
) {
|
|
597
|
+
const androidxLinesText = androidxLines.join("\n");
|
|
598
|
+
const activeFragmentsSliceIndex =
|
|
599
|
+
androidxLinesText.indexOf("Active Fragments:") +
|
|
600
|
+
"Active Fragments:".length;
|
|
601
|
+
androidxLines = (
|
|
602
|
+
androidxLinesText.slice(0, activeFragmentsSliceIndex) +
|
|
603
|
+
"\n" +
|
|
604
|
+
androidxLinesText.slice(activeFragmentsSliceIndex)
|
|
605
|
+
).split("\n");
|
|
606
|
+
}
|
|
607
|
+
const androidxRangeLines = findRangeLines(
|
|
608
|
+
androidxLines,
|
|
609
|
+
"Active Fragments",
|
|
610
|
+
"Added Fragments"
|
|
611
|
+
);
|
|
612
|
+
androidxRangeLines.sort((a, b) => a.start.index - b.start.index);
|
|
613
|
+
|
|
614
|
+
androidxRangeLines.forEach((v) => {
|
|
615
|
+
const firstFragmentLine = androidxLines?.at(v.start.index + 1);
|
|
616
|
+
if (firstFragmentLine && !isNullLine(firstFragmentLine)) {
|
|
617
|
+
androidxFragmentLines.push({
|
|
618
|
+
content: handleFragmentLine(firstFragmentLine),
|
|
619
|
+
index: v.start.index + 1,
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
androidxLines?.forEach((item, index) => {
|
|
623
|
+
if (
|
|
624
|
+
firstFragmentLine &&
|
|
625
|
+
!isNullLine(item) &&
|
|
626
|
+
spaceCount(item) == spaceCount(firstFragmentLine) &&
|
|
627
|
+
index > v.start.index + 1 &&
|
|
628
|
+
index < v.end.index
|
|
629
|
+
) {
|
|
630
|
+
androidxFragmentLines.push({
|
|
631
|
+
content: handleFragmentLine(item),
|
|
632
|
+
index: index,
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
if (frameworkFragmentLines.length > 0 || androidxFragmentLines.length > 0) {
|
|
641
|
+
const fragmentTable = Array<Array<string>>();
|
|
642
|
+
fragmentTable.push(["activity", currentActivity]);
|
|
643
|
+
if (frameworkFragmentLines.length > 0) {
|
|
644
|
+
frameworkFragmentLines.sort((a, b) => a.index - b.index);
|
|
645
|
+
fragmentTable.push([
|
|
646
|
+
"framework fragments",
|
|
647
|
+
asTree(
|
|
648
|
+
toTreeObject(listToTree(toTreeArray(frameworkFragmentLines))),
|
|
649
|
+
true
|
|
650
|
+
),
|
|
651
|
+
]);
|
|
652
|
+
}
|
|
653
|
+
if (androidxFragmentLines.length > 0) {
|
|
654
|
+
androidxFragmentLines.sort((a, b) => a.index - b.index);
|
|
655
|
+
fragmentTable.push([
|
|
656
|
+
"androidx fragments",
|
|
657
|
+
asTree(
|
|
658
|
+
toTreeObject(listToTree(toTreeArray(androidxFragmentLines))),
|
|
659
|
+
true
|
|
660
|
+
),
|
|
661
|
+
]);
|
|
662
|
+
}
|
|
663
|
+
console.clear();
|
|
664
|
+
console.log(table(fragmentTable));
|
|
665
|
+
} else {
|
|
666
|
+
console.clear();
|
|
667
|
+
const fragmentTable = Array<Array<string>>();
|
|
668
|
+
fragmentTable.push(["activity", currentActivity]);
|
|
669
|
+
console.log(table(fragmentTable));
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
const argv = yargs(process.argv.slice(2))
|
|
674
|
+
.help("help")
|
|
675
|
+
.alias("help", "h")
|
|
676
|
+
.options({
|
|
677
|
+
activity: {
|
|
678
|
+
type: "boolean",
|
|
679
|
+
default: true,
|
|
680
|
+
alias: "a",
|
|
681
|
+
description: "Show the current activity's name",
|
|
682
|
+
},
|
|
683
|
+
stack: {
|
|
684
|
+
type: "boolean",
|
|
685
|
+
default: false,
|
|
686
|
+
alias: "s",
|
|
687
|
+
description: "Show the current activity's stack",
|
|
688
|
+
},
|
|
689
|
+
fragment: {
|
|
690
|
+
type: "boolean",
|
|
691
|
+
default: false,
|
|
692
|
+
alias: "f",
|
|
693
|
+
description: "Show all fragments in the current activity",
|
|
694
|
+
},
|
|
695
|
+
watch: {
|
|
696
|
+
type: "boolean",
|
|
697
|
+
default: false,
|
|
698
|
+
alias: "w",
|
|
699
|
+
description: "Monitor activity or fragments changes in real time",
|
|
700
|
+
},
|
|
701
|
+
all: {
|
|
702
|
+
type: "boolean",
|
|
703
|
+
default: false,
|
|
704
|
+
alias: "A",
|
|
705
|
+
description:
|
|
706
|
+
"Show all information, including the current activity name, activity stack and fragments",
|
|
707
|
+
},
|
|
708
|
+
})
|
|
709
|
+
.locale("en")
|
|
710
|
+
.parseSync();
|
|
711
|
+
|
|
712
|
+
if (argv.all) {
|
|
713
|
+
if (argv.watch) {
|
|
714
|
+
onCurrentWindowChanged(() => printAll());
|
|
715
|
+
} else {
|
|
716
|
+
printAll();
|
|
717
|
+
}
|
|
718
|
+
} else if (argv.fragment) {
|
|
719
|
+
if (argv.watch) {
|
|
720
|
+
onFragmentsChanged(() => printCurrentActivityFragments());
|
|
721
|
+
} else {
|
|
722
|
+
printCurrentActivityFragments();
|
|
723
|
+
}
|
|
724
|
+
} else if (argv.activity) {
|
|
725
|
+
if (argv.stack) {
|
|
726
|
+
if (argv.watch) {
|
|
727
|
+
onCurrentWindowChanged(() => printCurrentActivityStack());
|
|
728
|
+
} else {
|
|
729
|
+
printCurrentActivityStack();
|
|
730
|
+
}
|
|
731
|
+
} else {
|
|
732
|
+
if (argv.watch) {
|
|
733
|
+
onCurrentWindowChanged(() => printCurrentActivityName());
|
|
734
|
+
} else {
|
|
735
|
+
printCurrentActivityName();
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|