Skip to content

Commit 4122b24

Browse files
lingqiqi5211Sevtinge
authored andcommitted
adj: support rich logging api
1 parent 52988c6 commit 4122b24

6 files changed

Lines changed: 161 additions & 99 deletions

File tree

gradle/libs.versions.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ viewpager2 = "1.0.0"
1717
miuix = "1.0.10.9"
1818

1919
# Xposed & Hooks
20-
xposed-api = "100-1.0.3"
20+
xposed-api = "100-1.0.4"
21+
xposed-service = "100-1.0.3"
2122
dexkit = "2.0.7"
2223
ezxhelper = "3.1.1-rc1"
2324
hiddenapibypass = "6.1"
@@ -74,7 +75,7 @@ ezxhelper-core = { module = "io.github.kyuubiran.ezxhelper:core", version.ref =
7475
ezxhelper-xposed-api = { module = "io.github.kyuubiran.ezxhelper:xposed-api-100", version.ref = "ezxhelper" }
7576
hiddenapibypass = { module = "org.lsposed.hiddenapibypass:hiddenapibypass", version.ref = "hiddenapibypass" }
7677
libxposed-api = { module = "io.github.libxposed:api", version.ref = "xposed-api" }
77-
libxposed-service = { module = "io.github.libxposed:service", version.ref = "xposed-api" }
78+
libxposed-service = { module = "io.github.libxposed:service", version.ref = "xposed-service" }
7879

7980
# Third-party
8081
auto-service = { module = "com.google.auto.service:auto-service", version.ref = "autoService" }

library/common/src/main/java/com/fan/common/logviewer/LogAdapter.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -459,18 +459,21 @@ public void bind(LogEntry logEntry, String searchKeyword) {
459459

460460
/**
461461
* 解析 Xposed 日志消息用于显示
462-
* @return [primary, secondary],primary 可能为 null
462+
* 兼容新旧格式:
463+
* 旧版: [HyperCeiler][I][pkg][ClassName]: detail message
464+
* 新版: [pkg][ClassName]: detail message
465+
* @return [primary, secondary]
463466
*/
464467
static String[] parseXposedDisplay(String message, String level) {
465468
if (message == null) return new String[]{null, ""};
466469

467-
// Crash:去掉 [HyperCeiler][E][CrashMonitor]: 前缀
470+
// Crash:去掉所有 [...] 前缀
468471
if ("C".equals(level)) {
469472
String stripped = message.replaceFirst("^(?:\\[[^\\]]+\\])+:\\s*", "");
470473
return new String[]{null, stripped};
471474
}
472475

473-
// 普通:[HyperCeiler][D][pkg][ClassName]: detail message
476+
// 找 "]: " 分割点
474477
int idx = message.indexOf("]: ");
475478
if (idx == -1) return new String[]{null, message};
476479

library/common/src/main/java/com/fan/common/logviewer/XposedLogLoader.java

Lines changed: 76 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,21 @@ public class XposedLogLoader {
5757
private static final String LSPD_LOG_SUBDIR = "log";
5858
private static final String LSPD_LOG_OLD_SUBDIR = "log.old";
5959
private static final String FILTERED_DIR = "hyperceiler_filtered";
60-
private static final String LOG_FILE_PATTERN = "*";
6160
private static final String FILTERED_LOG_PREFIX = "hyperceiler_";
6261
private static final String ROTATION_MARKER = ".rotation_marker";
6362

64-
private static final Pattern TIME_PATTERN = Pattern.compile("\\[\\s*(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3})");
65-
private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
63+
private static final Pattern TIME_PATTERN = Pattern.compile(
64+
"\\[\\s*(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3})");
65+
private static final SimpleDateFormat TIME_FORMAT =
66+
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
6667
private static final String HYPERCEILER_TAG = "HyperCeiler";
6768

69+
private static final Pattern LINE_PREFIX_LEVEL_PATTERN = Pattern.compile(
70+
"\\[\\s*\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}\\s+\\d+:\\s*\\d+:\\s*\\d+\\s+([VDIWEC])/");
71+
72+
private static final Pattern NEW_MODULE_PATTERN = Pattern.compile(
73+
"\\[([^,\\]]+),([^\\]]+)\\]");
74+
6875
private final Context context;
6976
private final File appLogBaseDir; // files/log
7077
private final File lspdCopyBaseDir; // files/log/lspd
@@ -320,7 +327,8 @@ private void filterAndSaveLogs() {
320327
private void filterLogsInDirectory(File sourceDir, File targetDir) {
321328
if (!sourceDir.exists()) return;
322329

323-
File[] sourceFiles = sourceDir.listFiles((dir, name) -> name.startsWith("modules_") && name.endsWith(".log"));
330+
File[] sourceFiles = sourceDir.listFiles((dir, name) ->
331+
name.startsWith("modules_") && name.endsWith(".log"));
324332
if (sourceFiles == null || sourceFiles.length == 0) return;
325333

326334
for (File sourceFile : sourceFiles) {
@@ -358,20 +366,21 @@ private List<String> filterLogFile(File sourceFile, long afterTimestamp) {
358366

359367
while ((line = reader.readLine()) != null) {
360368
if (isNewLogEntry(line)) {
361-
if (isHyperCeilerEntry && includeEntry && currentEntry.length() > 0) {
369+
if (isHyperCeilerEntry && includeEntry && !currentEntry.isEmpty()) {
362370
result.add(currentEntry.toString());
363371
}
372+
// 新旧格式都包含 HyperCeiler 关键字
364373
isHyperCeilerEntry = line.contains(HYPERCEILER_TAG);
365374
long entryTimestamp = parseTimestamp(line);
366375
includeEntry = entryTimestamp > afterTimestamp;
367376
currentEntry = new StringBuilder(line);
368377
} else {
369-
if (currentEntry.length() > 0) {
378+
if (!currentEntry.isEmpty()) {
370379
currentEntry.append("\n").append(line);
371380
}
372381
}
373382
}
374-
if (isHyperCeilerEntry && includeEntry && currentEntry.length() > 0) {
383+
if (isHyperCeilerEntry && includeEntry && !currentEntry.isEmpty()) {
375384
result.add(currentEntry.toString());
376385
}
377386
} catch (IOException e) {
@@ -441,8 +450,8 @@ private List<LogEntry> loadLogsFromDirectory(File directory) {
441450
List<LogEntry> entries = new ArrayList<>();
442451
if (!directory.exists()) return entries;
443452

444-
File[] files = directory.listFiles((dir, name) ->name.startsWith(FILTERED_LOG_PREFIX) && name.endsWith(".log"));
445-
453+
File[] files = directory.listFiles((dir, name) ->
454+
name.startsWith(FILTERED_LOG_PREFIX) && name.endsWith(".log"));
446455
if (files == null || files.length == 0) return entries;
447456

448457
Arrays.sort(files, Comparator.comparing(File::getName));
@@ -522,6 +531,8 @@ public void clearLogs() {
522531
}
523532
}
524533

534+
// ==================== 解析方法 ====================
535+
525536
private boolean isNewLogEntry(String line) {
526537
return line.startsWith("[") && TIME_PATTERN.matcher(line).find();
527538
}
@@ -537,34 +548,50 @@ private long parseTimestamp(String line) {
537548
return 0;
538549
}
539550

540-
private LogEntry parseXposedLogLine(String line) {
541-
long timestamp = parseTimestamp(line);
542-
String level = parseLevel(line);
543-
String message = extractMessage(line);
544-
String tag = extractPackageName(message);
545-
546-
if (message.contains("[CrashMonitor]")) {
547-
level = "C";
548-
}
549-
550-
return new LogEntry(timestamp, level, "Xposed", message, tag, true);
551+
private boolean isNewFormat(String line) {
552+
return NEW_MODULE_PATTERN.matcher(line).find();
551553
}
552554

553555

554556
private String parseLevel(String line) {
557+
// 优先从行前缀读取
558+
Matcher prefixMatcher = LINE_PREFIX_LEVEL_PATTERN.matcher(line);
559+
if (prefixMatcher.find()) {
560+
String level = prefixMatcher.group(1);
561+
if (level != null && !level.isEmpty()) {
562+
// 新版: 行前缀级别就是真实级别
563+
if (isNewFormat(line)) {
564+
return level;
565+
}
566+
}
567+
}
568+
569+
// 旧版 / 回退: 从 message 中提取
555570
if (line.contains("[E]")) return "E";
556571
if (line.contains("[W]")) return "W";
557572
if (line.contains("[I]")) return "I";
558573
if (line.contains("[D]")) return "D";
559-
return "C";
574+
return "I";
560575
}
561576

562577
private String extractMessage(String line) {
578+
// 新版: 找 [xxx,HyperCeiler] 之后的部分
579+
Matcher moduleMatcher = NEW_MODULE_PATTERN.matcher(line);
580+
if (moduleMatcher.find()) {
581+
int afterModule = moduleMatcher.end();
582+
while (afterModule < line.length() && line.charAt(afterModule) == ' ') {
583+
afterModule++;
584+
}
585+
return afterModule < line.length() ? line.substring(afterModule) : line;
586+
}
587+
588+
// 旧版: 从 [HyperCeiler] 开始
563589
int tagIndex = line.indexOf("[" + HYPERCEILER_TAG + "]");
564590
return tagIndex != -1 ? line.substring(tagIndex) : line;
565591
}
566592

567593
private String extractPackageName(String message) {
594+
// 旧版: 找级别标记 [I]/[D] 等,其后的 [xxx] 如果是包名就取
568595
for (String level : new String[]{"[I]", "[D]", "[W]", "[E]", "[C]"}) {
569596
int levelIndex = message.indexOf(level);
570597
if (levelIndex != -1) {
@@ -578,9 +605,21 @@ private String extractPackageName(String message) {
578605
}
579606
}
580607
}
608+
// 旧版匹配到级别标记但后面不是包名,跳出
581609
break;
582610
}
583611
}
612+
613+
if (message.startsWith("[")) {
614+
int endIndex = message.indexOf("]");
615+
if (endIndex != -1) {
616+
String first = message.substring(1, endIndex);
617+
if (isValidPackageName(first)) {
618+
return first;
619+
}
620+
}
621+
}
622+
584623
return "Other";
585624
}
586625

@@ -597,6 +636,22 @@ private boolean isValidPackageName(String name) {
597636
return true;
598637
}
599638

639+
/**
640+
* 解析 Xposed 日志行
641+
*/
642+
private LogEntry parseXposedLogLine(String line) {
643+
long timestamp = parseTimestamp(line);
644+
String level = parseLevel(line);
645+
String message = extractMessage(line);
646+
String tag = extractPackageName(message);
647+
648+
if (message.contains("[CrashMonitor]")) {
649+
level = "C";
650+
}
651+
652+
return new LogEntry(timestamp, level, "Xposed", message, tag, true);
653+
}
654+
600655
private LogEntry buildLogEntry(LogEntry template, String message) {
601656
return new LogEntry(
602657
template.getTimestamp(),

library/libhook/src/main/java/com/sevtinge/hyperceiler/libhook/utils/log/AndroidLog.kt

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -42,145 +42,138 @@ object AndroidLog {
4242
}
4343

4444
private fun notifyListener(level: String, tag: String, message: String) {
45-
try {
45+
runCatching {
4646
sLogListener?.onLog(level, tag, message)
47-
} catch (_: Throwable) {
4847
}
4948
}
5049

5150
// ============ Debug: 4 ============
5251
@JvmStatic
5352
fun d(msg: String) {
5453
if (!LoggerUtils.shouldLog(logLevel, 4)) return
55-
Log.d(TAG, LoggerUtils.formatMessage(TAG, "D", msg))
54+
Log.d(TAG, msg)
5655
notifyListener("D", TAG, msg)
5756
}
5857

5958
@JvmStatic
6059
fun d(tag: String, msg: String) {
6160
if (!LoggerUtils.shouldLog(logLevel, 4)) return
62-
Log.d(tag, LoggerUtils.formatMessageWithTag(TAG, "D", tag, msg))
61+
Log.d(tag, "[$tag]: $msg")
6362
notifyListener("D", tag, msg)
6463
}
6564

6665
@JvmStatic
6766
fun d(tag: String, msg: String, t: Throwable?) {
6867
if (!LoggerUtils.shouldLog(logLevel, 4)) return
69-
Log.d(tag, LoggerUtils.formatMessageWithTag(TAG, "D", tag, msg), t)
68+
Log.d(tag, "[$tag]: $msg", t)
7069
notifyListener("D", tag, msg + if (t != null) "\n$t" else "")
7170
}
7271

7372
@JvmStatic
7473
fun d(tag: String, pkg: String?, msg: String) {
7574
if (!LoggerUtils.shouldLog(logLevel, 4)) return
76-
Log.d(tag, LoggerUtils.formatMessageWithPkg(TAG, "D", pkg, tag, msg))
75+
Log.d(tag, LoggerUtils.formatBrackets(pkg, tag, msg))
7776
notifyListener("D", tag, msg)
7877
}
7978

8079
// ============ Info: 3 ============
8180
@JvmStatic
8281
fun i(msg: String) {
8382
if (!LoggerUtils.shouldLog(logLevel, 3)) return
84-
Log.i(TAG, LoggerUtils.formatMessage(TAG, "I", msg))
83+
Log.i(TAG, msg)
8584
notifyListener("I", TAG, msg)
8685
}
8786

8887
@JvmStatic
8988
fun i(tag: String, msg: String) {
9089
if (!LoggerUtils.shouldLog(logLevel, 3)) return
91-
Log.i(tag, LoggerUtils.formatMessageWithTag(TAG, "I", tag, msg))
90+
Log.i(tag, "[$tag]: $msg")
9291
notifyListener("I", tag, msg)
9392
}
9493

9594
@JvmStatic
9695
fun i(tag: String, pkg: String?, msg: String) {
9796
if (!LoggerUtils.shouldLog(logLevel, 3)) return
98-
Log.i(tag, LoggerUtils.formatMessageWithPkg(TAG, "I", pkg, tag, msg))
97+
Log.i(tag, LoggerUtils.formatBrackets(pkg, tag, msg))
9998
notifyListener("I", tag, msg)
10099
}
101100

102101
// ============ Warn: 2 ============
103102
@JvmStatic
104103
fun w(msg: String) {
105104
if (!LoggerUtils.shouldLog(logLevel, 2)) return
106-
Log.w(TAG, LoggerUtils.formatMessage(TAG, "W", msg))
105+
Log.w(TAG, msg)
107106
notifyListener("W", TAG, msg)
108107
}
109108

110109
@JvmStatic
111110
fun w(tag: String, msg: String) {
112111
if (!LoggerUtils.shouldLog(logLevel, 2)) return
113-
Log.w(tag, LoggerUtils.formatMessageWithTag(TAG, "W", tag, msg))
112+
Log.w(tag, "[$tag]: $msg")
114113
notifyListener("W", tag, msg)
115114
}
116115

117116
@JvmStatic
118117
fun w(tag: String, msg: String, t: Throwable?) {
119118
if (!LoggerUtils.shouldLog(logLevel, 2)) return
120-
Log.w(tag, LoggerUtils.formatMessageWithTag(TAG, "W", tag, msg), t)
119+
Log.w(tag, "[$tag]: $msg", t)
121120
notifyListener("W", tag, msg + if (t != null) "\n$t" else "")
122121
}
123122

124123
@JvmStatic
125124
fun w(tag: String, pkg: String?, msg: String) {
126125
if (!LoggerUtils.shouldLog(logLevel, 2)) return
127-
Log.w(tag, LoggerUtils.formatMessageWithPkg(TAG, "W", pkg, tag, msg))
126+
Log.w(tag, LoggerUtils.formatBrackets(pkg, tag, msg))
128127
notifyListener("W", tag, msg)
129128
}
130129

131130
@JvmStatic
132131
fun w(tag: String, pkg: String?, msg: String, t: Throwable?) {
133132
if (!LoggerUtils.shouldLog(logLevel, 2)) return
134-
Log.w(tag, LoggerUtils.formatMessageWithPkg(TAG, "W", pkg, tag, msg), t)
133+
Log.w(tag, LoggerUtils.formatBrackets(pkg, tag, msg), t)
135134
notifyListener("W", tag, msg + if (t != null) "\n$t" else "")
136135
}
137136

138137
// ============ Error: 1 ============
139138
@JvmStatic
140139
fun e(msg: String) {
141140
if (!LoggerUtils.shouldLog(logLevel, 1)) return
142-
Log.e(TAG, LoggerUtils.formatMessage(TAG, "E", msg))
141+
Log.e(TAG, msg)
143142
notifyListener("E", TAG, msg)
144143
}
145144

146145
@JvmStatic
147146
fun e(tag: String, msg: String) {
148147
if (!LoggerUtils.shouldLog(logLevel, 1)) return
149-
Log.e(tag, LoggerUtils.formatMessageWithTag(TAG, "E", tag, msg))
148+
Log.e(tag, "[$tag]: $msg")
150149
notifyListener("E", tag, msg)
151150
}
152151

153152
@JvmStatic
154153
fun e(tag: String, t: Throwable) {
155154
if (!LoggerUtils.shouldLog(logLevel, 1)) return
156-
Log.e(tag, LoggerUtils.formatMessageWithTag(TAG, "E", tag, t.message ?: t.toString()), t)
155+
Log.e(tag, "[$tag]: ${t.message ?: t.toString()}", t)
157156
notifyListener("E", tag, t.message ?: t.toString())
158157
}
159158

160159
@JvmStatic
161160
fun e(tag: String, msg: String, t: Throwable?) {
162161
if (!LoggerUtils.shouldLog(logLevel, 1)) return
163-
Log.e(tag, LoggerUtils.formatMessageWithTag(TAG, "E", tag, msg), t)
162+
Log.e(tag, "[$tag]: $msg", t)
164163
notifyListener("E", tag, msg + if (t != null) "\n$t" else "")
165164
}
166165

167166
@JvmStatic
168167
fun e(tag: String, pkg: String?, msg: String) {
169168
if (!LoggerUtils.shouldLog(logLevel, 1)) return
170-
Log.e(tag, LoggerUtils.formatMessageWithPkg(TAG, "E", pkg, tag, msg))
169+
Log.e(tag, LoggerUtils.formatBrackets(pkg, tag, msg))
171170
notifyListener("E", tag, msg)
172171
}
173172

174173
@JvmStatic
175174
fun e(tag: String, pkg: String?, msg: String, t: Throwable?) {
176175
if (!LoggerUtils.shouldLog(logLevel, 1)) return
177-
Log.e(tag, LoggerUtils.formatMessageWithPkg(TAG, "E", pkg, tag, msg), t)
176+
Log.e(tag, LoggerUtils.formatBrackets(pkg, tag, msg), t)
178177
notifyListener("E", tag, msg + if (t != null) "\n$t" else "")
179178
}
180-
181-
@JvmStatic
182-
fun logLevelDesc(): String {
183-
return LoggerUtils.logLevelDesc(logLevel)
184-
}
185179
}
186-

0 commit comments

Comments
 (0)