From 284f3dbd343b8f40e921b4b887384ebc14ba3dcb Mon Sep 17 00:00:00 2001
From: Dana <Dana_Lee1016@126.com>
Date: 星期二, 23 十二月 2025 13:57:39 +0800
Subject: [PATCH] 1.h264文件写入的时候检查tfcard剩余空间 ,并执行删除
---
app/src/main/java/com/anyun/h264/H264EncodeService.java | 3
app/src/main/java/com/anyun/h264/util/FileUtil.java | 202 ++++++++++++++++++++++++++++++++++++++++
app/src/main/java/com/anyun/h264/H264Encoder.java | 41 ++++++++
app/src/main/java/com/anyun/h264/H264EncodeService2.java | 6 +
4 files changed, 252 insertions(+), 0 deletions(-)
diff --git a/app/src/main/java/com/anyun/h264/H264EncodeService.java b/app/src/main/java/com/anyun/h264/H264EncodeService.java
index 63306ac..f65b77e 100644
--- a/app/src/main/java/com/anyun/h264/H264EncodeService.java
+++ b/app/src/main/java/com/anyun/h264/H264EncodeService.java
@@ -505,6 +505,9 @@
// 鍒涘缓缂栫爜鍣�
h264Encoder = new H264Encoder();
+ // 璁剧疆 Context锛堢敤浜庢竻鐞� TF 鍗℃枃浠讹級
+ h264Encoder.setContext(this);
+
// 璁剧疆缂栫爜鍙傛暟锛堜娇鐢ㄩ厤缃腑鐨勫弬鏁帮級
int width = config != null && config.width > 0 ? config.width : DEFAULT_WIDTH;
int height = config != null && config.height > 0 ? config.height : DEFAULT_HEIGHT;
diff --git a/app/src/main/java/com/anyun/h264/H264EncodeService2.java b/app/src/main/java/com/anyun/h264/H264EncodeService2.java
index 6f4c927..cced8b3 100644
--- a/app/src/main/java/com/anyun/h264/H264EncodeService2.java
+++ b/app/src/main/java/com/anyun/h264/H264EncodeService2.java
@@ -286,6 +286,9 @@
// 鍒涘缓缂栫爜鍣�
h264Encoder = new H264Encoder();
+ // 璁剧疆 Context锛堢敤浜庢竻鐞� TF 鍗℃枃浠讹級
+ h264Encoder.setContext(this);
+
// 璁剧疆缂栫爜鍙傛暟锛堜娇鐢ㄩ厤缃腑鐨勫弬鏁帮級
// 璁剧疆缂栫爜鍙傛暟锛堜娇鐢ㄩ厤缃腑鐨勫弬鏁帮級
int width = config != null && config.width > 0 ? config.width : DEFAULT_WIDTH;
@@ -352,6 +355,9 @@
// 鍒涘缓缂栫爜鍣�
h264Encoder = new H264Encoder();
+ // 璁剧疆 Context锛堢敤浜庢竻鐞� TF 鍗℃枃浠讹級
+ h264Encoder.setContext(this);
+
// 璁剧疆缂栫爜鍙傛暟锛堜娇鐢ㄩ厤缃腑鐨勫弬鏁帮級
int width = config != null && config.width > 0 ? config.width : DEFAULT_WIDTH;
int height = config != null && config.height > 0 ? config.height : DEFAULT_HEIGHT;
diff --git a/app/src/main/java/com/anyun/h264/H264Encoder.java b/app/src/main/java/com/anyun/h264/H264Encoder.java
index 59525d2..9be6413 100644
--- a/app/src/main/java/com/anyun/h264/H264Encoder.java
+++ b/app/src/main/java/com/anyun/h264/H264Encoder.java
@@ -1,11 +1,13 @@
package com.anyun.h264;
+import android.content.Context;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import com.anyun.libusbcamera.UsbCamera;
import com.anyun.libusbcamera.WatermarkParam;
import com.anyun.h264.model.WatermarkInfo;
+import com.anyun.h264.util.FileUtil;
import java.io.File;
import java.io.FileOutputStream;
@@ -82,6 +84,10 @@
private int cameraId = 1; // 鎽勫儚澶碔D锛岄粯璁や负1锛堢涓�涓憚鍍忓ご锛�
private long currentFileStartTime = 0; // 褰撳墠鏂囦欢鐨勫紑濮嬫椂闂达紙姣锛�
private static final long FILE_DURATION_MS = 60 * 1000; // 鏂囦欢鏃堕暱锛�1鍒嗛挓锛堟绉掞級
+
+ // Context 鍜屾竻鐞嗛厤缃�
+ private Context context; // Context 瀵硅薄锛岀敤浜庢竻鐞� TF 鍗℃枃浠�
+ private long maxH264TotalSizeGB = 5; // 鏈�澶� H264 鏂囦欢鎬诲ぇ灏忥紙GB锛夛紝榛樿 5GB
// 缃戠粶浼犺緭鎺у埗
private boolean enableNetworkTransmission = true; // 鏄惁鍚敤TCP/UDP缃戠粶浼犺緭
@@ -155,6 +161,22 @@
*/
public void setCameraId(int cameraId) {
this.cameraId = cameraId;
+ }
+
+ /**
+ * 璁剧疆 Context锛堢敤浜庢竻鐞� TF 鍗℃枃浠讹級
+ * @param context Context 瀵硅薄
+ */
+ public void setContext(Context context) {
+ this.context = context;
+ }
+
+ /**
+ * 璁剧疆鏈�澶� H264 鏂囦欢鎬诲ぇ灏忥紙GB锛�
+ * @param maxTotalSizeGB 鏈�澶ф�诲ぇ灏忥紙GB锛夛紝榛樿 5GB
+ */
+ public void setMaxH264TotalSizeGB(long maxTotalSizeGB) {
+ this.maxH264TotalSizeGB = maxTotalSizeGB;
}
/**
@@ -432,6 +454,25 @@
fileOutputStream = null;
}
+ // 妫�鏌ュ苟娓呯悊 TF 鍗′笂鐨� h264 鏂囦欢锛堝鏋滈渶瑕侊級
+ if (context != null && outputFileDirectory != null && !outputFileDirectory.isEmpty()) {
+ try {
+ // 鍒ゆ柇褰撳墠鐩綍鏄惁鍦� TF 鍗$殑 h264 鐩綍涓�
+ // 鐩綍缁撴瀯锛�/sdcard/h264/yyyyMMdd/锛宧264 鏍圭洰褰曞簲璇ユ槸鐖剁洰褰曠殑鐖剁洰褰�
+ File currentDir = new File(outputFileDirectory);
+ File parentDir = currentDir.getParentFile();
+ if (parentDir != null && "h264".equals(parentDir.getName())) {
+ // 褰撳墠鐩綍鍦� h264 鐩綍涓嬶紝鑾峰彇 h264 鏍圭洰褰�
+ String h264RootDir = parentDir.getAbsolutePath();
+ Timber.d("Checking and cleaning up h264 files in: %s", h264RootDir);
+ FileUtil.cleanupH264Files(context, h264RootDir, maxH264TotalSizeGB, 1);
+ }
+ } catch (Exception e) {
+ Timber.e(e, "Error during h264 files cleanup check");
+ // 娓呯悊澶辫触涓嶅奖鍝嶆枃浠跺垱寤猴紝缁х画鎵ц
+ }
+ }
+
// 鐢熸垚鏂版枃浠跺悕
long timeFile = System.currentTimeMillis() / 1000 * 1000;
currentFileStartTime = timeFile;
diff --git a/app/src/main/java/com/anyun/h264/util/FileUtil.java b/app/src/main/java/com/anyun/h264/util/FileUtil.java
index 9f84cd0..b41f232 100644
--- a/app/src/main/java/com/anyun/h264/util/FileUtil.java
+++ b/app/src/main/java/com/anyun/h264/util/FileUtil.java
@@ -2,10 +2,22 @@
import android.content.Context;
import android.os.storage.StorageManager;
+import android.os.StatFs;
+import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+import timber.log.Timber;
public class FileUtil {
//鑾峰彇鎻掑叆鐨凾FCard鐩綍璺緞
@@ -44,4 +56,194 @@
}
}
+
+ /**
+ * 娓呯悊 TF 鍗′笂鐨� h264 鏂囦欢
+ * 褰� h264 鏂囦欢鎬诲ぇ灏忚秴杩囨寚瀹氶槇鍊兼垨 TF 鍗″墿浣欑┖闂村皬浜庢寚瀹氬�兼椂锛屽垹闄ゆ棩鏈熸渶鏃╃殑鏂囦欢澶�
+ *
+ * @param context Context 瀵硅薄锛岀敤浜庤幏鍙� TF 鍗¤矾寰勫拰鍓╀綑绌洪棿
+ * @param h264RootDir h264 鏍圭洰褰曡矾寰勶紝渚嬪 "/sdcard/h264"
+ * @param maxTotalSizeGB 鏈�澶ф�诲ぇ灏忥紙GB锛夛紝榛樿 5GB
+ * @param minFreeSpaceGB 鏈�灏忓墿浣欑┖闂达紙GB锛夛紝榛樿 1GB
+ */
+ public static void cleanupH264Files(Context context, String h264RootDir, long maxTotalSizeGB, long minFreeSpaceGB) {
+ if (context == null || h264RootDir == null || h264RootDir.trim().isEmpty()) {
+ Timber.w("Context or h264 root directory is null, skip cleanup");
+ return;
+ }
+
+ File h264Root = new File(h264RootDir);
+ if (!h264Root.exists() || !h264Root.isDirectory()) {
+ Timber.d("H264 root directory does not exist: %s, skip cleanup", h264RootDir);
+ return;
+ }
+
+ try {
+ // 鑾峰彇 TF 鍗¤矾寰�
+ String tfCardPath = getStoragePath(context, true);
+ if (tfCardPath == null || tfCardPath.trim().isEmpty()) {
+ Timber.w("TF card path not available, skip cleanup");
+ return;
+ }
+
+ // 鑾峰彇 TF 鍗″墿浣欑┖闂达紙GB锛�
+ long freeSpaceGB = getFreeSpaceGB(tfCardPath);
+ Timber.d("TF card free space: %d GB", freeSpaceGB);
+
+ // 鎵弿鎵�鏈夋棩鏈熸枃浠跺す
+ File[] dateDirs = h264Root.listFiles(File::isDirectory);
+ if (dateDirs == null || dateDirs.length == 0) {
+ Timber.d("No date directories found in h264 root: %s", h264RootDir);
+ return;
+ }
+
+ // 鎸夋棩鏈熸帓搴忥紙鏈�鏃╃殑鍦ㄥ墠锛�
+ List<DateDirInfo> dateDirList = new ArrayList<>();
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd", Locale.CHINA);
+
+ for (File dateDir : dateDirs) {
+ String dirName = dateDir.getName();
+ // 鍙鐞嗙鍚堟棩鏈熸牸寮忕殑鏂囦欢澶癸紙yyyyMMdd锛�
+ if (dirName.length() == 8 && dirName.matches("\\d{8}")) {
+ try {
+ Date date = dateFormat.parse(dirName);
+ long totalSize = calculateH264FilesSize(dateDir);
+ dateDirList.add(new DateDirInfo(dateDir, date, totalSize));
+ } catch (ParseException e) {
+ Timber.w("Invalid date directory name: %s", dirName);
+ }
+ }
+ }
+
+ // 鎸夋棩鏈熸帓搴忥紙鏈�鏃╃殑鍦ㄥ墠锛�
+ Collections.sort(dateDirList, new Comparator<DateDirInfo>() {
+ @Override
+ public int compare(DateDirInfo o1, DateDirInfo o2) {
+ return o1.date.compareTo(o2.date);
+ }
+ });
+
+ // 璁$畻鎵�鏈� h264 鏂囦欢鐨勬�诲ぇ灏忥紙GB锛�
+ long totalSizeGB = 0;
+ for (DateDirInfo info : dateDirList) {
+ totalSizeGB += info.totalSize / (1024L * 1024L * 1024L);
+ }
+ Timber.d("Total h264 files size: %d GB, Max allowed: %d GB", totalSizeGB, maxTotalSizeGB);
+ Timber.d("TF card free space: %d GB, Min required: %d GB", freeSpaceGB, minFreeSpaceGB);
+
+ // 妫�鏌ユ槸鍚﹂渶瑕佹竻鐞�
+ boolean needCleanup = (totalSizeGB > maxTotalSizeGB) || (freeSpaceGB < minFreeSpaceGB);
+
+ if (!needCleanup) {
+ Timber.d("No cleanup needed");
+ return;
+ }
+
+ // 鍒犻櫎鏈�鏃╃殑鏃ユ湡鏂囦欢澶癸紝鐩村埌婊¤冻鏉′欢
+ int deletedCount = 0;
+ while (!dateDirList.isEmpty() && ((totalSizeGB > maxTotalSizeGB) || (freeSpaceGB < minFreeSpaceGB))) {
+ DateDirInfo oldestDir = dateDirList.remove(0);
+
+ Timber.d("Deleting oldest date directory: %s (size: %d GB, date: %s)",
+ oldestDir.dir.getName(), oldestDir.totalSize / (1024L * 1024L * 1024L),
+ dateFormat.format(oldestDir.date));
+
+ // 鍒犻櫎鏂囦欢澶瑰強鍏舵墍鏈夊唴瀹�
+ if (deleteDirectory(oldestDir.dir)) {
+ deletedCount++;
+ totalSizeGB -= oldestDir.totalSize / (1024L * 1024L * 1024L);
+
+ // 閲嶆柊鑾峰彇鍓╀綑绌洪棿
+ freeSpaceGB = getFreeSpaceGB(tfCardPath);
+ Timber.d("After deletion - Total size: %d GB, Free space: %d GB",
+ totalSizeGB, freeSpaceGB);
+ } else {
+ Timber.e("Failed to delete directory: %s", oldestDir.dir.getAbsolutePath());
+ break; // 鍒犻櫎澶辫触锛屽仠姝㈡竻鐞�
+ }
+ }
+
+ Timber.i("Cleanup completed. Deleted %d date directories. Final total size: %d GB, Free space: %d GB",
+ deletedCount, totalSizeGB, freeSpaceGB);
+
+ } catch (Exception e) {
+ Timber.e(e, "Error during h264 files cleanup");
+ }
+ }
+
+ /**
+ * 娓呯悊 TF 鍗′笂鐨� h264 鏂囦欢锛堜娇鐢ㄩ粯璁ゅ弬鏁帮細鏈�澶�5GB锛屾渶灏忓墿浣欑┖闂�1GB锛�
+ */
+ public static void cleanupH264Files(Context context, String h264RootDir) {
+ cleanupH264Files(context, h264RootDir, 5, 1);
+ }
+
+ /**
+ * 璁$畻鐩綍涓嬫墍鏈� .h264 鏂囦欢鐨勬�诲ぇ灏忥紙瀛楄妭锛�
+ */
+ private static long calculateH264FilesSize(File dir) {
+ long totalSize = 0;
+ File[] files = dir.listFiles();
+ if (files != null) {
+ for (File file : files) {
+ if (file.isFile() && file.getName().toLowerCase().endsWith(".h264")) {
+ totalSize += file.length();
+ }
+ }
+ }
+ return totalSize;
+ }
+
+ /**
+ * 鑾峰彇鎸囧畾璺緞鐨勫墿浣欑┖闂达紙GB锛�
+ */
+ private static long getFreeSpaceGB(String path) {
+ try {
+ StatFs statFs = new StatFs(path);
+ long blockSize = statFs.getBlockSizeLong();
+ long availableBlocks = statFs.getAvailableBlocksLong();
+ long freeBytes = availableBlocks * blockSize;
+ return freeBytes / (1024L * 1024L * 1024L); // 杞崲涓� GB
+ } catch (Exception e) {
+ Timber.e(e, "Error getting free space for path: %s", path);
+ return 0;
+ }
+ }
+
+ /**
+ * 閫掑綊鍒犻櫎鐩綍鍙婂叾鎵�鏈夊唴瀹�
+ */
+ private static boolean deleteDirectory(File dir) {
+ if (dir == null || !dir.exists()) {
+ return true;
+ }
+
+ if (dir.isDirectory()) {
+ File[] children = dir.listFiles();
+ if (children != null) {
+ for (File child : children) {
+ if (!deleteDirectory(child)) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return dir.delete();
+ }
+
+ /**
+ * 鏃ユ湡鏂囦欢澶逛俊鎭�
+ */
+ private static class DateDirInfo {
+ File dir;
+ Date date;
+ long totalSize; // 瀛楄妭
+
+ DateDirInfo(File dir, Date date, long totalSize) {
+ this.dir = dir;
+ this.date = date;
+ this.totalSize = totalSize;
+ }
+ }
}
--
Gitblit v1.8.0