From ccf7a1f19b5c6276178c72609c88d057214c8239 Mon Sep 17 00:00:00 2001
From: Dana <Dana_Lee1016@126.com>
Date: 星期一, 01 十二月 2025 09:51:50 +0800
Subject: [PATCH] 1.添加timber日志库
---
app/src/main/java/com/anyun/h264/H264EncodeService.java | 115 ++++++++--------
app/src/main/java/com/anyun/h264/H264Application.java | 27 +++
app/src/main/java/com/anyun/h264/MainActivity.kt | 16 +-
app/src/main/AndroidManifest.xml | 5
app/src/main/java/com/anyun/h264/JT1076ProtocolHelper.java | 33 ++--
app/src/main/java/com/anyun/h264/H264FileTransmitter.java | 36 ++--
gradle/libs.versions.toml | 2
app/build.gradle | 1
app/src/main/java/com/anyun/h264/FileLoggingTree.java | 146 ++++++++++++++++++++
9 files changed, 281 insertions(+), 100 deletions(-)
diff --git a/app/build.gradle b/app/build.gradle
index b971839..9fa237e 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -68,6 +68,7 @@
implementation libs.androidx.ui.tooling.preview
implementation libs.androidx.material3
implementation libs.netty.all
+ implementation libs.timber
testImplementation libs.junit
androidTestImplementation libs.androidx.junit
androidTestImplementation libs.androidx.espresso.core
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9254442..58a629f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -7,10 +7,15 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <!-- 瀛樺偍鏉冮檺锛堢敤浜庢棩蹇楁枃浠讹級 -->
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+
<!-- USB鎽勫儚澶存潈闄� -->
<uses-feature android:name="android.hardware.usb.host" />
<application
+ android:name=".H264Application"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
diff --git a/app/src/main/java/com/anyun/h264/FileLoggingTree.java b/app/src/main/java/com/anyun/h264/FileLoggingTree.java
new file mode 100644
index 0000000..d133697
--- /dev/null
+++ b/app/src/main/java/com/anyun/h264/FileLoggingTree.java
@@ -0,0 +1,146 @@
+package com.anyun.h264;
+
+import android.os.Environment;
+import android.util.Log;
+import timber.log.Timber;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * Timber Tree implementation that logs to files.
+ * Logs are saved to sdcard/nvlog/h264_yyyyMMdd.log format.
+ */
+public class FileLoggingTree extends Timber.DebugTree {
+ private static final String LOG_DIR = "nvlog";
+ private static final String LOG_PREFIX = "h264_";
+ private static final String LOG_SUFFIX = ".log";
+ private static final String DATE_FORMAT = "yyyyMMdd";
+ private static final String TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";
+
+ private String currentLogFile = null;
+ private SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.CHINA);
+ private SimpleDateFormat timestampFormat = new SimpleDateFormat(TIMESTAMP_FORMAT, Locale.CHINA);
+
+ @Override
+ protected void log(int priority, String tag, String message, Throwable t) {
+ try {
+ // Get today's log file path
+ String today = dateFormat.format(new Date());
+ String logFileName = LOG_PREFIX + today + LOG_SUFFIX;
+
+ // Check if we need to update the log file (new day)
+ if (!logFileName.equals(currentLogFile)) {
+ currentLogFile = logFileName;
+ }
+
+ File logFile = getLogFile(logFileName);
+ if (logFile == null) {
+ return;
+ }
+
+ // Format log entry
+ String logEntry = formatLogEntry(priority, tag, message, t);
+
+ // Write to file (append mode)
+ synchronized (this) {
+ try (FileWriter writer = new FileWriter(logFile, true)) {
+ writer.append(logEntry);
+ writer.append("\n");
+ writer.flush();
+ } catch (IOException e) {
+ // If file writing fails, log to system log as fallback
+ Log.e("FileLoggingTree", "Failed to write log to file", e);
+ }
+ }
+ } catch (Exception e) {
+ // If anything goes wrong, log to system log
+ Log.e("FileLoggingTree", "Error in FileLoggingTree", e);
+ }
+ }
+
+ /**
+ * Get the log file. Creates directory if needed.
+ */
+ private File getLogFile(String fileName) {
+ try {
+ File logDir = new File(Environment.getExternalStorageDirectory(), LOG_DIR);
+ if (!logDir.exists()) {
+ if (!logDir.mkdirs()) {
+ Log.e("FileLoggingTree", "Failed to create log directory: " + logDir.getAbsolutePath());
+ return null;
+ }
+ }
+
+ File logFile = new File(logDir, fileName);
+ if (!logFile.exists()) {
+ if (!logFile.createNewFile()) {
+ Log.e("FileLoggingTree", "Failed to create log file: " + logFile.getAbsolutePath());
+ return null;
+ }
+ }
+
+ return logFile;
+ } catch (IOException e) {
+ Log.e("FileLoggingTree", "Error getting log file", e);
+ return null;
+ }
+ }
+
+ /**
+ * Format a log entry with timestamp, priority, tag, and message.
+ */
+ private String formatLogEntry(int priority, String tag, String message, Throwable t) {
+ StringBuilder sb = new StringBuilder();
+
+ // Timestamp
+ sb.append(timestampFormat.format(new Date()));
+ sb.append(" ");
+
+ // Priority level
+ sb.append(getPriorityString(priority));
+ sb.append("/");
+
+ // Tag
+ sb.append(tag);
+ sb.append(": ");
+
+ // Message
+ sb.append(message);
+
+ // Throwable stack trace
+ if (t != null) {
+ sb.append("\n");
+ sb.append(Log.getStackTraceString(t));
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Get priority string representation.
+ */
+ private String getPriorityString(int priority) {
+ switch (priority) {
+ case Log.VERBOSE:
+ return "V";
+ case Log.DEBUG:
+ return "D";
+ case Log.INFO:
+ return "I";
+ case Log.WARN:
+ return "W";
+ case Log.ERROR:
+ return "E";
+ case Log.ASSERT:
+ return "A";
+ default:
+ return "?";
+ }
+ }
+}
+
diff --git a/app/src/main/java/com/anyun/h264/H264Application.java b/app/src/main/java/com/anyun/h264/H264Application.java
new file mode 100644
index 0000000..6c1ba4b
--- /dev/null
+++ b/app/src/main/java/com/anyun/h264/H264Application.java
@@ -0,0 +1,27 @@
+package com.anyun.h264;
+
+import android.app.Application;
+import timber.log.Timber;
+
+/**
+ * Application class for initializing Timber logging.
+ */
+public class H264Application extends Application {
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ // Initialize Timber
+// if (BuildConfig.DEBUG) {
+ // In debug mode, use both console and file logging
+ Timber.plant(new Timber.DebugTree());
+ Timber.plant(new FileLoggingTree());
+// } else {
+// // In release mode, only use file logging
+// Timber.plant(new FileLoggingTree());
+// }
+
+ Timber.d("H264Application onCreate - Timber initialized");
+ }
+}
+
diff --git a/app/src/main/java/com/anyun/h264/H264EncodeService.java b/app/src/main/java/com/anyun/h264/H264EncodeService.java
index a2ec246..e1f5ad0 100644
--- a/app/src/main/java/com/anyun/h264/H264EncodeService.java
+++ b/app/src/main/java/com/anyun/h264/H264EncodeService.java
@@ -4,7 +4,7 @@
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
-import android.util.Log;
+import timber.log.Timber;
import com.anyun.h264.model.ResourceInfo;
@@ -56,22 +56,22 @@
@Override
public void onCreate() {
super.onCreate();
- Log.d(TAG, "H264EncodeService created");
+ Timber.d("H264EncodeService created");
// 鍒濆鍖栬緭鍑烘枃浠剁洰褰曪紙浣跨敤搴旂敤澶栭儴瀛樺偍鐩綍锛�
outputFileDirectory = getExternalFilesDir(null).getAbsolutePath();
- Log.d(TAG, "Output file directory: " + outputFileDirectory);
+ Timber.d("Output file directory: %s", outputFileDirectory);
}
@Override
public IBinder onBind(Intent intent) {
- Log.d(TAG, "Service bound");
+ Timber.d("Service bound");
return binder;
}
@Override
public boolean onUnbind(Intent intent) {
- Log.d(TAG, "Service unbound");
+ Timber.d("Service unbound");
// 涓嶈嚜鍔ㄥ仠姝㈢紪鐮佸櫒锛岃瀹冨湪鏈嶅姟涓繚鎸佽繍琛�
return super.onUnbind(intent);
}
@@ -79,7 +79,7 @@
@Override
public void onDestroy() {
super.onDestroy();
- Log.d(TAG, "Service destroyed");
+ Timber.d("Service destroyed");
// 鍋滄骞堕噴鏀剧紪鐮佸櫒鍜屾枃浠朵紶杈撳櫒
stopEncoder();
@@ -170,7 +170,7 @@
* @return 0-鎴愬姛锛�1-澶辫触
*/
private synchronized int controlEncode(int action, String jsonConfig) {
- Log.d(TAG, "controlEncode called with action: " + action + ", jsonConfig: " + jsonConfig);
+ Timber.d("controlEncode called with action: %d, jsonConfig: %s", action, jsonConfig);
try {
switch (action) {
@@ -179,7 +179,7 @@
EncodeConfig config0 = EncodeConfig.fromJson(jsonConfig);
return startFileEncode(config0);
} catch (JSONException e) {
- Log.e(TAG, "Failed to parse JSON config: " + jsonConfig, e);
+ Timber.e(e, "Failed to parse JSON config: %s", jsonConfig);
return 1;
}
@@ -191,7 +191,7 @@
EncodeConfig config2 = EncodeConfig.fromJson(jsonConfig);
return startNetworkEncode(config2);
} catch (JSONException e) {
- Log.e(TAG, "Failed to parse JSON config: " + jsonConfig, e);
+ Timber.e(e, "Failed to parse JSON config: %s", jsonConfig);
return 1;
}
@@ -203,7 +203,7 @@
FileTransmitConfig config4 = FileTransmitConfig.fromJson(jsonConfig);
return startFileTransmit(config4);
} catch (JSONException e) {
- Log.e(TAG, "Failed to parse JSON config: " + jsonConfig, e);
+ Timber.e(e, "Failed to parse JSON config: %s", jsonConfig);
return 1;
}
@@ -211,11 +211,11 @@
return stopFileTransmitter();
default:
- Log.e(TAG, "Unknown action: " + action);
+ Timber.e("Unknown action: %d", action);
return 1; // 澶辫触
}
} catch (Exception e) {
- Log.e(TAG, "Error in controlEncode", e);
+ Timber.e(e, "Error in controlEncode");
return 1; // 澶辫触
}
}
@@ -224,11 +224,11 @@
* 鍚姩鏂囦欢缂栫爜妯″紡锛堝彧鍐欏叆鏂囦欢锛屼笉杩涜缃戠粶鎺ㄩ�侊級
*/
private int startFileEncode(EncodeConfig config) {
- Log.d(TAG, "Starting file encode mode");
+ Timber.d("Starting file encode mode");
// 濡傛灉缂栫爜鍣ㄥ凡缁忓湪杩愯锛屽厛鍋滄
if (h264Encoder != null) {
- Log.w(TAG, "Encoder is already running, stopping it first");
+ Timber.w("Encoder is already running, stopping it first");
stopEncoder();
}
@@ -245,7 +245,7 @@
long timeFile = System.currentTimeMillis();
SimpleDateFormat bcdFormat = new SimpleDateFormat("yyMMddHHmmss");
String str = bcdFormat.format(timeFile);
- Log.i(TAG,"鏂囦欢鍚嶏細"+str);
+ Timber.i("鏂囦欢鍚嶏細%s", str);
// 璁剧疆杈撳嚭鏂囦欢
String fileName = "h264_" + timeFile+ ".h264";
File outputFile = new File(outputFileDirectory, fileName);
@@ -259,16 +259,16 @@
int[] resolution = {width, height};
if (h264Encoder.initialize(DEFAULT_CAMERA_ID_RANGE, null, resolution, false)) {
h264Encoder.start();
- Log.d(TAG, "File encode started successfully, output file: " + outputFile.getAbsolutePath() +
- ", resolution: " + width + "x" + height + ", framerate: " + framerate);
+ Timber.d("File encode started successfully, output file: %s, resolution: %dx%d, framerate: %d",
+ outputFile.getAbsolutePath(), width, height, framerate);
return 0; // 鎴愬姛
} else {
- Log.e(TAG, "Failed to initialize encoder");
+ Timber.e("Failed to initialize encoder");
h264Encoder = null;
return 1; // 澶辫触
}
} catch (Exception e) {
- Log.e(TAG, "Failed to start file encode", e);
+ Timber.e(e, "Failed to start file encode");
h264Encoder = null;
return 1; // 澶辫触
}
@@ -278,17 +278,17 @@
* 鍚姩缃戠粶鎺ㄩ�佹ā寮忥紙鍙繘琛岀綉缁滄帹閫侊紝涓嶅啓鍏ユ枃浠讹級
*/
private int startNetworkEncode(EncodeConfig config) {
- Log.d(TAG, "Starting network encode mode");
+ Timber.d("Starting network encode mode");
// 濡傛灉缂栫爜鍣ㄥ凡缁忓湪杩愯锛屽厛鍋滄
if (h264Encoder != null) {
- Log.w(TAG, "Encoder is already running, stopping it first");
+ Timber.w("Encoder is already running, stopping it first");
stopEncoder();
}
// 妫�鏌ュ繀闇�鐨勯厤缃弬鏁�
if (config == null || config.ip == null || config.ip.trim().isEmpty() || config.port <= 0) {
- Log.e(TAG, "Network encode requires valid ip and port in config");
+ Timber.e("Network encode requires valid ip and port in config");
return 1; // 澶辫触
}
@@ -321,16 +321,16 @@
int[] resolution = {width, height};
if (h264Encoder.initialize(DEFAULT_CAMERA_ID_RANGE, null, resolution, false)) {
h264Encoder.start();
- Log.d(TAG, "Network encode started successfully, server: " + config.ip + ":" + config.port +
- ", resolution: " + width + "x" + height + ", framerate: " + framerate);
+ Timber.d("Network encode started successfully, server: %s:%d, resolution: %dx%d, framerate: %d",
+ config.ip, config.port, width, height, framerate);
return 0; // 鎴愬姛
} else {
- Log.e(TAG, "Failed to initialize encoder");
+ Timber.e("Failed to initialize encoder");
h264Encoder = null;
return 1; // 澶辫触
}
} catch (Exception e) {
- Log.e(TAG, "Failed to start network encode", e);
+ Timber.e(e, "Failed to start network encode");
h264Encoder = null;
return 1; // 澶辫触
}
@@ -340,22 +340,22 @@
* 鍋滄缂栫爜鍣�
*/
private int stopEncoder() {
- Log.d(TAG, "Stopping encoder");
+ Timber.d("Stopping encoder");
if (h264Encoder != null) {
try {
h264Encoder.stop();
h264Encoder.release();
h264Encoder = null;
- Log.d(TAG, "Encoder stopped successfully");
+ Timber.d("Encoder stopped successfully");
return 0; // 鎴愬姛
} catch (Exception e) {
- Log.e(TAG, "Error stopping encoder", e);
+ Timber.e(e, "Error stopping encoder");
h264Encoder = null;
return 1; // 澶辫触
}
} else {
- Log.w(TAG, "Encoder is not running");
+ Timber.w("Encoder is not running");
return 0; // 鎴愬姛锛堟病鏈夎繍琛岀殑缂栫爜鍣紝瑙嗕负鎴愬姛锛�
}
}
@@ -364,22 +364,22 @@
* 鍚姩鏂囦欢浼犺緭妯″紡锛堜粠H264鏂囦欢璇诲彇骞剁綉缁滄帹閫侊級
*/
private int startFileTransmit(FileTransmitConfig config) {
- Log.d(TAG, "Starting file transmit mode");
+ Timber.d("Starting file transmit mode");
// 濡傛灉鏂囦欢浼犺緭鍣ㄥ凡缁忓湪杩愯锛屽厛鍋滄
if (h264FileTransmitter != null) {
- Log.w(TAG, "File transmitter is already running, stopping it first");
+ Timber.w("File transmitter is already running, stopping it first");
stopFileTransmitter();
}
// 妫�鏌ュ繀闇�鐨勯厤缃弬鏁�
if (config == null || config.ip == null || config.ip.trim().isEmpty() || config.port <= 0) {
- Log.e(TAG, "File transmit requires valid ip and port in config");
+ Timber.e("File transmit requires valid ip and port in config");
return 1; // 澶辫触
}
if (config.filePath == null || config.filePath.trim().isEmpty()) {
- Log.e(TAG, "File transmit requires valid filePath in config");
+ Timber.e("File transmit requires valid filePath in config");
return 1; // 澶辫触
}
@@ -387,7 +387,7 @@
// 妫�鏌ユ枃浠舵槸鍚﹀瓨鍦�
File file = new File(config.filePath);
if (!file.exists() || !file.isFile()) {
- Log.e(TAG, "File does not exist: " + config.filePath);
+ Timber.e("File does not exist: %s", config.filePath);
return 1; // 澶辫触
}
@@ -413,24 +413,24 @@
h264FileTransmitter.setOnTransmitProgressCallback(new H264FileTransmitter.OnTransmitProgressCallback() {
@Override
public void onProgress(int currentFrame, int totalFrames) {
- Log.d(TAG, "File transmit progress: frame " + currentFrame +
- (totalFrames > 0 ? " of " + totalFrames : ""));
+ Timber.d("File transmit progress: frame %d%s", currentFrame,
+ totalFrames > 0 ? " of " + totalFrames : "");
}
@Override
public void onComplete() {
- Log.d(TAG, "File transmit completed");
+ Timber.d("File transmit completed");
}
@Override
public void onError(String error) {
- Log.e(TAG, "File transmit error: " + error);
+ Timber.e("File transmit error: %s", error);
}
});
// 鍒濆鍖朣ocket杩炴帴
if (!h264FileTransmitter.initialize()) {
- Log.e(TAG, "Failed to initialize file transmitter socket");
+ Timber.e("Failed to initialize file transmitter socket");
h264FileTransmitter = null;
return 1; // 澶辫触
}
@@ -438,19 +438,18 @@
// 寮�濮嬩紶杈撴枃浠�
h264FileTransmitter.transmitFile(config.filePath);
- Log.d(TAG, "File transmit started successfully, file: " + config.filePath +
- ", server: " + config.ip + ":" + config.port +
- ", protocol: " + (config.protocolType == JT1076ProtocolHelper.PROTOCOL_TYPE_UDP ? "UDP" : "TCP") +
- ", framerate: " + framerate);
+ Timber.d("File transmit started successfully, file: %s, server: %s:%d, protocol: %s, framerate: %d",
+ config.filePath, config.ip, config.port,
+ config.protocolType == JT1076ProtocolHelper.PROTOCOL_TYPE_UDP ? "UDP" : "TCP", framerate);
return 0; // 鎴愬姛
} catch (Exception e) {
- Log.e(TAG, "Failed to start file transmit", e);
+ Timber.e(e, "Failed to start file transmit");
if (h264FileTransmitter != null) {
try {
h264FileTransmitter.stop();
} catch (Exception ex) {
- Log.e(TAG, "Error stopping file transmitter after failure", ex);
+ Timber.e(ex, "Error stopping file transmitter after failure");
}
h264FileTransmitter = null;
}
@@ -462,21 +461,21 @@
* 鍋滄鏂囦欢浼犺緭鍣�
*/
private int stopFileTransmitter() {
- Log.d(TAG, "Stopping file transmitter");
+ Timber.d("Stopping file transmitter");
if (h264FileTransmitter != null) {
try {
h264FileTransmitter.stop();
h264FileTransmitter = null;
- Log.d(TAG, "File transmitter stopped successfully");
+ Timber.d("File transmitter stopped successfully");
return 0; // 鎴愬姛
} catch (Exception e) {
- Log.e(TAG, "Error stopping file transmitter", e);
+ Timber.e(e, "Error stopping file transmitter");
h264FileTransmitter = null;
return 1; // 澶辫触
}
} else {
- Log.w(TAG, "File transmitter is not running");
+ Timber.w("File transmitter is not running");
return 0; // 鎴愬姛锛堟病鏈夎繍琛岀殑鏂囦欢浼犺緭鍣紝瑙嗕负鎴愬姛锛�
}
}
@@ -488,7 +487,7 @@
* @return 璧勬簮鍒楄〃
*/
private List<ResourceInfo> getResourceList(String startTime, String endTime) {
- Log.d(TAG, "getResourceList called, startTime: " + startTime + ", endTime: " + endTime);
+ Timber.d("getResourceList called, startTime: %s, endTime: %s", startTime, endTime);
List<ResourceInfo> resourceList = new ArrayList<>();
@@ -496,13 +495,13 @@
// 鎵弿杈撳嚭鐩綍涓殑H264鏂囦欢
File dir = new File(outputFileDirectory);
if (!dir.exists() || !dir.isDirectory()) {
- Log.w(TAG, "Output directory does not exist: " + outputFileDirectory);
+ Timber.w("Output directory does not exist: %s", outputFileDirectory);
return resourceList;
}
File[] files = dir.listFiles((dir1, name) -> name.toLowerCase().endsWith(".h264"));
if (files == null || files.length == 0) {
- Log.d(TAG, "No H264 files found in directory");
+ Timber.d("No H264 files found in directory");
return resourceList;
}
@@ -511,7 +510,7 @@
Date endDate = parseTime(endTime);
if (startDate == null || endDate == null) {
- Log.e(TAG, "Invalid time format, startTime: " + startTime + ", endTime: " + endTime);
+ Timber.e("Invalid time format, startTime: %s, endTime: %s", startTime, endTime);
return resourceList;
}
@@ -523,11 +522,11 @@
}
}
- Log.d(TAG, "Found " + resourceList.size() + " resources in time range");
+ Timber.d("Found %d resources in time range", resourceList.size());
return resourceList;
} catch (Exception e) {
- Log.e(TAG, "Error getting resource list", e);
+ Timber.e(e, "Error getting resource list");
return resourceList;
}
}
@@ -578,7 +577,7 @@
return resourceInfo;
} catch (Exception e) {
- Log.e(TAG, "Error creating resource info from file: " + file.getName(), e);
+ Timber.e(e, "Error creating resource info from file: %s", file.getName());
return null;
}
}
@@ -597,7 +596,7 @@
SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmss", Locale.CHINA);
return format.parse(timeStr);
} catch (ParseException e) {
- Log.e(TAG, "Failed to parse time: " + timeStr, e);
+ Timber.e(e, "Failed to parse time: %s", timeStr);
return null;
}
}
diff --git a/app/src/main/java/com/anyun/h264/H264FileTransmitter.java b/app/src/main/java/com/anyun/h264/H264FileTransmitter.java
index 51299d0..af9919f 100644
--- a/app/src/main/java/com/anyun/h264/H264FileTransmitter.java
+++ b/app/src/main/java/com/anyun/h264/H264FileTransmitter.java
@@ -1,6 +1,6 @@
package com.anyun.h264;
-import android.util.Log;
+import timber.log.Timber;
import java.io.File;
import java.io.FileInputStream;
@@ -119,7 +119,7 @@
public void setFrameRate(int frameRate) {
this.frameRate = frameRate > 0 ? frameRate : 25;
this.frameInterval = 1000 / this.frameRate;
- Log.d(TAG, "Frame rate set to: " + this.frameRate + " fps, interval: " + this.frameInterval + " ms");
+ Timber.d("Frame rate set to: %d fps, interval: %d ms", this.frameRate, this.frameInterval);
}
/**
@@ -135,12 +135,12 @@
*/
public boolean initialize() {
if (isRunning.get()) {
- Log.w(TAG, "Transmitter is already running");
+ Timber.w("Transmitter is already running");
return false;
}
if (!protocolHelper.initializeSocket()) {
- Log.e(TAG, "Failed to initialize socket");
+ Timber.e("Failed to initialize socket");
return false;
}
@@ -152,7 +152,7 @@
lastIFrameTime = 0;
lastFrameTime = 0;
- Log.d(TAG, "Socket initialized successfully");
+ Timber.d("Socket initialized successfully");
return true;
}
@@ -162,13 +162,13 @@
*/
public void transmitFile(String filePath) {
if (isRunning.get()) {
- Log.w(TAG, "Transmitter is already running");
+ Timber.w("Transmitter is already running");
return;
}
File file = new File(filePath);
if (!file.exists() || !file.isFile()) {
- Log.e(TAG, "File does not exist: " + filePath);
+ Timber.e("File does not exist: %s", filePath);
if (progressCallback != null) {
progressCallback.onError("File does not exist: " + filePath);
}
@@ -186,7 +186,7 @@
});
transmitThread.start();
- Log.d(TAG, "Started transmitting file: " + filePath);
+ Timber.d("Started transmitting file: %s", filePath);
}
/**
@@ -214,10 +214,10 @@
}
if (totalRead != fileData.length) {
- Log.w(TAG, "File read incomplete, expected: " + fileData.length + ", actual: " + totalRead);
+ Timber.w("File read incomplete, expected: %d, actual: %d", fileData.length, totalRead);
}
- Log.d(TAG, "File read complete, size: " + fileData.length + " bytes");
+ Timber.d("File read complete, size: %d bytes", fileData.length);
// 鎸夊抚瑙f瀽骞朵紶杈擄紙涓�涓抚鍖呭惈浠庝竴涓捣濮嬬爜鍒颁笅涓�涓捣濮嬬爜涔嬮棿鐨勬墍鏈夋暟鎹紝鍖呮嫭璧峰鐮侊級
int offset = 0;
@@ -255,19 +255,19 @@
offset = nextFrameStart;
}
- Log.d(TAG, "Transmission complete, total frames: " + frameCount);
+ Timber.d("Transmission complete, total frames: %d", frameCount);
if (progressCallback != null) {
progressCallback.onComplete();
}
} catch (IOException e) {
- Log.e(TAG, "Error transmitting file", e);
+ Timber.e(e, "Error transmitting file");
if (progressCallback != null) {
progressCallback.onError("IO Error: " + e.getMessage());
}
} catch (Exception e) {
- Log.e(TAG, "Unexpected error during transmission", e);
+ Timber.e(e, "Unexpected error during transmission");
if (progressCallback != null) {
progressCallback.onError("Error: " + e.getMessage());
}
@@ -276,7 +276,7 @@
try {
fis.close();
} catch (IOException e) {
- Log.e(TAG, "Error closing file", e);
+ Timber.e(e, "Error closing file");
}
}
isRunning.set(false);
@@ -464,13 +464,13 @@
Thread.sleep(frameInterval);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
- Log.d(TAG, "Transmission interrupted");
+ Timber.d("Transmission interrupted");
return;
}
}
} catch (Exception e) {
- Log.e(TAG, "Error transmitting frame", e);
+ Timber.e(e, "Error transmitting frame");
}
}
@@ -489,7 +489,7 @@
try {
transmitThread.join(2000);
} catch (InterruptedException e) {
- Log.e(TAG, "Wait transmit thread error", e);
+ Timber.e(e, "Wait transmit thread error");
}
}
@@ -498,7 +498,7 @@
protocolHelper.closeSocket();
}
- Log.d(TAG, "H264 file transmitter stopped");
+ Timber.d("H264 file transmitter stopped");
}
/**
diff --git a/app/src/main/java/com/anyun/h264/JT1076ProtocolHelper.java b/app/src/main/java/com/anyun/h264/JT1076ProtocolHelper.java
index 1489907..71af779 100644
--- a/app/src/main/java/com/anyun/h264/JT1076ProtocolHelper.java
+++ b/app/src/main/java/com/anyun/h264/JT1076ProtocolHelper.java
@@ -1,12 +1,13 @@
package com.anyun.h264;
-import android.util.Log;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.ByteBuffer;
+
+import timber.log.Timber;
/**
* JT/T 1076-2016 鍗忚宸ュ叿绫�
@@ -78,7 +79,7 @@
*/
public void setProtocolType(int protocolType) {
if (protocolType != PROTOCOL_TYPE_UDP && protocolType != PROTOCOL_TYPE_TCP) {
- Log.w(TAG, "Invalid protocol type: " + protocolType + ", using UDP");
+ Timber.w("Invalid protocol type: " + protocolType + ", using UDP");
protocolType = PROTOCOL_TYPE_UDP;
}
@@ -92,7 +93,7 @@
}
this.protocolType = protocolType;
- Log.d(TAG, "Protocol type set to: " + (protocolType == PROTOCOL_TYPE_UDP ? "UDP" : "TCP"));
+ Timber.d("Protocol type set to: " + (protocolType == PROTOCOL_TYPE_UDP ? "UDP" : "TCP"));
}
/**
@@ -127,16 +128,16 @@
public boolean initializeUdpSocket() {
try {
if (serverIp == null || serverIp.isEmpty()) {
- Log.e(TAG, "Server IP not set");
+ Timber.e("Server IP not set");
return false;
}
udpSocket = new DatagramSocket();
serverAddress = InetAddress.getByName(serverIp);
- Log.d(TAG, "UDP socket initialized, target: " + serverIp + ":" + serverPort);
+ Timber.d("UDP socket initialized, target: " + serverIp + ":" + serverPort);
return true;
} catch (Exception e) {
- Log.e(TAG, "Initialize UDP socket failed", e);
+ Timber.e(e,"Initialize UDP socket failed");
return false;
}
}
@@ -147,7 +148,7 @@
public boolean initializeTcpSocket() {
try {
if (serverIp == null || serverIp.isEmpty()) {
- Log.e(TAG, "Server IP not set");
+ Timber.e("Server IP not set");
return false;
}
@@ -159,26 +160,26 @@
tcpClient.setConnectionListener(new JT1076TcpClient.ConnectionListener() {
@Override
public void onConnected() {
- Log.d(TAG, "TCP connection established");
+ Timber.d("TCP connection established");
}
@Override
public void onDisconnected() {
- Log.d(TAG, "TCP connection disconnected");
+ Timber.d( "TCP connection disconnected");
}
@Override
public void onError(Throwable cause) {
- Log.e(TAG, "TCP connection error", cause);
+ Timber.e(cause, "TCP connection error");
}
});
}
tcpClient.connect();
- Log.d(TAG, "TCP socket initializing, target: " + serverIp + ":" + serverPort);
+ Timber.d("TCP socket initializing, target: " + serverIp + ":" + serverPort);
return true;
} catch (Exception e) {
- Log.e(TAG, "Initialize TCP socket failed", e);
+ Timber.e(e,"Initialize TCP socket failed");
return false;
}
}
@@ -202,7 +203,7 @@
try {
udpSocket.close();
} catch (Exception e) {
- Log.e(TAG, "Close UDP socket error", e);
+ Timber.e( e,"Close UDP socket error");
}
udpSocket = null;
}
@@ -240,10 +241,10 @@
packet, packet.length, serverAddress, serverPort);
udpSocket.send(datagramPacket);
} else {
- Log.w(TAG, "UDP socket not initialized");
+ Timber.w("UDP socket not initialized");
}
} catch (Exception e) {
- Log.e(TAG, "Send UDP packet error", e);
+ Timber.e(e,"Send UDP packet error");
}
}
@@ -254,7 +255,7 @@
if (tcpClient != null && tcpClient.isConnected()) {
tcpClient.sendPacket(packet);
} else {
- Log.w(TAG, "TCP socket not connected");
+ Timber.w("TCP socket not connected");
}
}
diff --git a/app/src/main/java/com/anyun/h264/MainActivity.kt b/app/src/main/java/com/anyun/h264/MainActivity.kt
index f70360f..4fc1e0d 100644
--- a/app/src/main/java/com/anyun/h264/MainActivity.kt
+++ b/app/src/main/java/com/anyun/h264/MainActivity.kt
@@ -1,7 +1,7 @@
package com.anyun.h264
import android.os.Bundle
-import android.util.Log
+import timber.log.Timber
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
@@ -52,7 +52,7 @@
private fun startH264Encoder(): Boolean {
if (h264Encoder != null) {
- Log.w("MainActivity", "H264Encoder is already running")
+ Timber.w("H264Encoder is already running")
return false
}
@@ -80,16 +80,16 @@
if (h264Encoder?.initialize(cameraIdRange, null, resolution, false) == true) {
h264Encoder?.start()
- Log.d("MainActivity", "H264Encoder started successfully")
- Log.d("MainActivity", "Output file: ${outputFile.absolutePath}")
+ Timber.d("H264Encoder started successfully")
+ Timber.d("Output file: %s", outputFile.absolutePath)
return true
} else {
- Log.e("MainActivity", "Failed to initialize H264Encoder")
+ Timber.e("Failed to initialize H264Encoder")
h264Encoder = null
return false
}
} catch (e: Exception) {
- Log.e("MainActivity", "Failed to start H264Encoder", e)
+ Timber.e(e, "Failed to start H264Encoder")
h264Encoder = null
return false
}
@@ -99,9 +99,9 @@
h264Encoder?.let { encoder ->
try {
encoder.stop()
- Log.d("MainActivity", "H264Encoder stopped")
+ Timber.d("H264Encoder stopped")
} catch (e: Exception) {
- Log.e("MainActivity", "Failed to stop H264Encoder", e)
+ Timber.e(e, "Failed to stop H264Encoder")
}
h264Encoder = null
}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index ed71bad..07b697f 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -9,6 +9,7 @@
activityCompose = "1.8.0"
composeBom = "2024.04.01"
netty = "4.1.48.Final"
+timber = "4.7.1"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@@ -26,6 +27,7 @@
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
netty-all = { group = "io.netty", name = "netty-all", version.ref = "netty" }
+timber = { group = "com.jakewharton.timber", name = "timber", version.ref = "timber" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
--
Gitblit v1.8.0