Skip to content

Commit f3745b5

Browse files
committed
修正识别日志 TAG 的正则表达式
修复在某些特殊机型上面日志没有及时更新的问题 新增支持链接自动在日志上面高亮的逻辑
1 parent e81319d commit f3745b5

File tree

6 files changed

+100
-44
lines changed

6 files changed

+100
-44
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
* 项目地址:[Github](https://github.com/getActivity/Logcat)[码云](https://gitee.com/getActivity/Logcat)
66

7-
* 可以扫码下载 Demo 进行演示或者测试,如果扫码下载不了的,[点击此处可直接下载](https://github.com/getActivity/Logcat/releases/download/10.5/Logcat.apk)
7+
* 可以扫码下载 Demo 进行演示或者测试,如果扫码下载不了的,[点击此处可直接下载](https://github.com/getActivity/Logcat/releases/download/10.6/Logcat.apk)
88

99
![](picture/demo_code.png)
1010

@@ -51,7 +51,7 @@ dependencyResolutionManagement {
5151
```groovy
5252
dependencies {
5353
// 日志调试框架:https://github.com/getActivity/Logcat
54-
debugImplementation 'com.github.getActivity:Logcat:10.5'
54+
debugImplementation 'com.github.getActivity:Logcat:10.6'
5555
}
5656
```
5757

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ android {
77
applicationId "com.hjq.logcat.demo"
88
minSdkVersion 16
99
targetSdkVersion 31
10-
versionCode 1050
11-
versionName "10.5"
10+
versionCode 1060
11+
versionName "10.6"
1212
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
1313
}
1414

library/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ android {
99

1010
defaultConfig {
1111
minSdkVersion 16
12-
versionCode 1050
13-
versionName "10.5"
12+
versionCode 1060
13+
versionName "10.6"
1414
}
1515

1616
lintOptions {

library/src/main/java/com/hjq/logcat/LogcatAdapter.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import android.text.TextUtils;
1313
import android.text.style.BackgroundColorSpan;
1414
import android.text.style.ForegroundColorSpan;
15+
import android.text.style.URLSpan;
1516
import android.text.style.UnderlineSpan;
1617
import android.util.SparseBooleanArray;
1718
import android.util.SparseIntArray;
@@ -44,6 +45,9 @@ final class LogcatAdapter extends RecyclerView.Adapter<LogcatAdapter.ViewHolder>
4445
/** 报错代码行数正则表达式 */
4546
private static final Pattern CODE_REGEX = Pattern.compile("\\(\\w+\\.\\w+:\\d+\\)");
4647

48+
/** 链接正则表达式 */
49+
private static final Pattern LINK_REGEX = Pattern.compile("https?://[^\\x{4e00}-\\x{9fa5}\\n\\r\\s]{3,}");
50+
4751
private final SparseBooleanArray mExpandSet = new SparseBooleanArray();
4852
private final SparseIntArray mScrollXSet = new SparseIntArray();
4953

@@ -236,7 +240,7 @@ public class ViewHolder extends RecyclerView.ViewHolder implements
236240
public ViewHolder(View itemView) {
237241
super(itemView);
238242

239-
mHorizontalScrollView = (HorizontalScrollView) itemView.findViewById(R.id.hcv_log_content);
243+
mHorizontalScrollView = itemView.findViewById(R.id.hcv_log_content);
240244
mContentView = itemView.findViewById(R.id.tv_log_content);
241245
mIndexView = itemView.findViewById(R.id.tv_log_index);
242246
mLineView = itemView.findViewById(R.id.v_log_line);
@@ -270,7 +274,7 @@ public boolean onLongClick(View v) {
270274
public boolean onTouch(View v, MotionEvent event) {
271275
switch (event.getAction()) {
272276
case MotionEvent.ACTION_MOVE:
273-
// 修改动作为ACTION_CANCEL
277+
// 修改动作为 ACTION_CANCEL
274278
event.setAction(MotionEvent.ACTION_CANCEL);
275279
// 将事件回传给父控件
276280
itemView.onTouchEvent(event);
@@ -310,6 +314,7 @@ private void onBindView(LogcatInfo info, int position) {
310314
}
311315
}
312316
} else {
317+
// 高亮代码行数
313318
Matcher matcher = CODE_REGEX.matcher(content);
314319
if (spannable.length() > 0) {
315320
while (matcher.find()) {
@@ -324,6 +329,20 @@ private void onBindView(LogcatInfo info, int position) {
324329
}
325330
}
326331
}
332+
333+
// 高亮 H5 链接
334+
Matcher matcher = LINK_REGEX.matcher(content);
335+
while (matcher.find()) {
336+
// 不包含左括号(
337+
int start = matcher.start();
338+
// 不包含右括号 )
339+
int end = matcher.end();
340+
URLSpan urlSpan = new URLSpan(String.valueOf(spannable.subSequence(start, end)));
341+
spannable.setSpan(urlSpan, start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
342+
// 为什么不设置点击事件,因为这样会导致外层 ScrollView 触摸事件和 itemView 点击事件无效
343+
//mContentView.setMovementMethod(LinkMovementMethod.getInstance());
344+
}
345+
327346
mContentView.setText(spannable);
328347

329348
final int resourceId;

library/src/main/java/com/hjq/logcat/LogcatInfo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ final class LogcatInfo {
2121
private static final Pattern PATTERN = Pattern.compile(
2222
//( 05-19 23:59:18.383 ) ( 3177 ) ( 3258 ) ( I ) ( XLog ) ( 我是日志内容 )
2323
//( time regex ) (pid regex) (tid regex) ( log level) ( log tag ) ( log content )
24-
"([0-9^-]+-[0-9^ ]+\\s[0-9^:]+:[0-9^:]+\\.[0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s([VDIWEF])\\s([^:&&\\s]*):\\s(.*)");
24+
"([0-9^-]+-[0-9^ ]+\\s[0-9^:]+:[0-9^:]+\\.[0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s([VDIWEF])\\s([^:]*):\\s(.*)");
2525

2626
static final ArrayList<String> IGNORED_LOG = new ArrayList<String>() {{
2727
add("--------- beginning of crash");

library/src/main/java/com/hjq/logcat/LogcatManager.java

Lines changed: 72 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.hjq.logcat;
22

33
import java.io.BufferedReader;
4+
import java.io.Closeable;
45
import java.io.IOException;
56
import java.io.InputStreamReader;
67
import java.util.ArrayList;
@@ -71,53 +72,89 @@ static void destroy() {
7172
static void clear() {
7273
try {
7374
new ProcessBuilder("logcat", "-c").start();
74-
FLAG_WORK = true;
75-
new Thread(new LogRunnable()).start();
7675
} catch (IOException ignored) {}
7776
}
7877

78+
/**
79+
* 创建 Logcat 日志缓冲区
80+
*/
81+
private static BufferedReader createLogcatBufferedReader() throws IOException {
82+
// Process process = Runtime.getRuntime().exec("/system/bin/logcat -b " + "main -P '\"/" + android.os.Process.myPid() + " 10708\"'");
83+
// Process process = Runtime.getRuntime().exec("/system/bin/logcat -b all -v uid");
84+
// Process process = Runtime.getRuntime().exec("logcat -b all -v uid");
85+
Process process = new ProcessBuilder("logcat", "-v", "threadtime").start();
86+
return new BufferedReader(new InputStreamReader(process.getInputStream()));
87+
}
88+
89+
/**
90+
* 关闭流
91+
*/
92+
private static void closeStream(Closeable closeable) {
93+
if (closeable == null) {
94+
return;
95+
}
96+
try {
97+
closeable.close();
98+
} catch (IOException e) {
99+
e.printStackTrace();
100+
}
101+
}
102+
79103
private static class LogRunnable implements Runnable {
80104

81105
@Override
82106
public void run() {
83107
BufferedReader reader = null;
84-
try {
85-
// Process process = Runtime.getRuntime().exec("/system/bin/logcat -b " + "main -P '\"/" + android.os.Process.myPid() + " 10708\"'");
86-
// Process process = Runtime.getRuntime().exec("/system/bin/logcat -b all -v uid");
87-
// Process process = Runtime.getRuntime().exec("logcat -b all -v uid");
88-
Process process = new ProcessBuilder("logcat", "-v", "threadtime").start();
89-
90-
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
91-
String line;
92-
while ((line = reader.readLine()) != null) {
93-
synchronized (LogcatManager.class) {
94-
if (LogcatInfo.IGNORED_LOG.contains(line)) {
95-
continue;
96-
}
97-
LogcatInfo info = LogcatInfo.create(line);
98-
if (info == null) {
99-
continue;
100-
}
101-
if (!FLAG_WORK) {
102-
// 这里可能会出现下标异常
103-
LOG_BACKUP.add(info);
104-
continue;
105-
}
106108

107-
final Callback callback = sCallback;
108-
if (callback != null) {
109-
callback.onReceiveLog(info);
109+
String line;
110+
while (true) {
111+
synchronized (LogcatManager.class) {
112+
if (reader == null) {
113+
try {
114+
reader = createLogcatBufferedReader();
115+
} catch (IOException e) {
116+
e.printStackTrace();
117+
break;
110118
}
111119
}
112-
}
113-
pause();
114-
} catch (IOException ignored) {
115-
pause();
116-
} finally {
117-
if (reader != null) {
118120
try {
119-
reader.close();
120-
} catch (IOException ignored) {}
121+
line = reader.readLine();
122+
} catch (IOException e) {
123+
e.printStackTrace();
124+
closeStream(reader);
125+
break;
126+
}
127+
if (line == null) {
128+
// 正常情况讲,line 是不会为空的,因为没有新的日志前提下 reader.readLine() 会阻塞读取
129+
// 但是在某些特殊机型(vivo iQOO 9 Pro Android 12)上面会出现,在没有新的日志前提下,会返回 null
130+
// 并且等待一会儿再读取还不行,无论循环等待多次,因为原先的流里面已经没有东西了,要读取新的日志必须创建新的流
131+
try {
132+
closeStream(reader);
133+
reader = null;
134+
Thread.sleep(5000);
135+
} catch (InterruptedException e) {
136+
e.printStackTrace();
137+
}
138+
continue;
139+
}
140+
141+
if (LogcatInfo.IGNORED_LOG.contains(line)) {
142+
continue;
143+
}
144+
LogcatInfo info = LogcatInfo.create(line);
145+
if (info == null) {
146+
continue;
147+
}
148+
if (!FLAG_WORK) {
149+
// 这里可能会出现下标异常
150+
LOG_BACKUP.add(info);
151+
continue;
152+
}
153+
154+
final Callback callback = sCallback;
155+
if (callback != null) {
156+
callback.onReceiveLog(info);
157+
}
121158
}
122159
}
123160
}

0 commit comments

Comments
 (0)