diff --git a/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt index 854c068..19822d7 100644 --- a/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt +++ b/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt @@ -45,6 +45,7 @@ import com.sw.platecabinet.socket.LanServer import com.sw.platecabinet.socket.LanServerListenerImpl import com.sw.platecabinet.socket.TcpClient import com.sw.platecabinet.utils.Debouncer +import com.sw.platecabinet.utils.FileUtil import com.sw.platecabinet.utils.PermissionHelper import com.sw.platecabinet.utils.PlateUtils import com.sw.platecabinet.utils.SoundPoolUtil @@ -286,9 +287,10 @@ class LoginByFaceActivity : BaseActivity(), */ private fun loadFaceRecognizeResult2(result: CompareResult?) { val similar = result?.similar ?: 0f - binding.tvSimilarValue.text = "$similar" + binding.tvSimilarValue.text = "$similar,${retryFailCount}次" loadLogInfo("collectFace,recognizeUserId 人脸识别配置阈值为:${faceSuccessThreshold},失败阈值为:${faceFailThreshold},相似度为:${similar},失败次数为:${retryFailCount}") if (similar > faceSuccessThreshold) { + loadLogInfo("collectFace,recognizeUserId 相似度为:${similar},识别成功时间:${DateTimeUtils.getDateTimeString()}") //大 于识别阈值,作为识别成功判断 currentUserId = result?.faceEntity?.userName Debouncer(5000).debounce { openPlate(currentUserId) } @@ -296,11 +298,14 @@ class LoginByFaceActivity : BaseActivity(), } loadLogInfo("collectFace,recognizeUserId 人脸识别相似度为:${similar},失败次数为:${retryFailCount}") if (similar < faceFailThreshold || retryFailCount >= maxFailCount) { - //小于识别错误阈值,或者识别失败次数大于等于最大失败次数,作为识别失败判断 - loadLogInfo("collectFace,recognizeUserId 未识别到人脸信息,开始采集") - isCollectFace = true - collectFace() - return + //相似度低于识别错误阈值进行采集、识别失败次数大于等于最大失败次数,作为识别失败判断 + if (isCollectFace.not()) { + //非采集中 + loadLogInfo("collectFace,recognizeUserId 未识别到人脸信息,相似度为:${similar},开始采集时间:${DateTimeUtils.getDateTimeString()}") + isCollectFace = true + collectFace() + return + } } //满足similar >= faceFailThreshold && similar <= successThreshold时进行重试 retryFailCount++ @@ -712,12 +717,17 @@ class LoginByFaceActivity : BaseActivity(), if (faceData.isNullOrBlank()) { return } - loadLogInfo("collectFace,getFaceData: ----------7,拿到人脸提取特征数据-----------") + loadLogInfo("collectFace,getFaceData: ----------7,拿到人脸提取特征数据时间:${DateTimeUtils.getDateTimeString()}-----------") block(faceData) } + /** + * 加载日志 + * @param msg 日志内容 + */ private fun loadLogInfo(msg: String) { Timber.tag(TAG).d(msg) + FileUtil.saveLog(msg) } private var facePreviewInfoList: MutableList? = null diff --git a/app/src/main/java/com/sw/platecabinet/utils/FileUtil.java b/app/src/main/java/com/sw/platecabinet/utils/FileUtil.java new file mode 100644 index 0000000..fee6eb1 --- /dev/null +++ b/app/src/main/java/com/sw/platecabinet/utils/FileUtil.java @@ -0,0 +1,697 @@ +package com.sw.platecabinet.utils; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; + +import com.sw.plate.App; +import com.sw.plate.utils.AppUtil; + +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.StringReader; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +public class FileUtil { + private static boolean isSaveLog = true; + public static final String FILE_STR_PATH = App.getContext().getExternalCacheDir().getAbsolutePath(); + + public static final int SIZETYPE_B = 1;//获取文件大小单位为B的double值 + public static final int SIZETYPE_KB = 2;//获取文件大小单位为KB的double值 + public static final int SIZETYPE_MB = 3;//获取文件大小单位为MB的double值 + public static final int SIZETYPE_GB = 4;//获取文件大小单位为GB的double值 + private static String urlNull = "原文件路径不存在"; + private static String isFile = "原文件不是文件"; + private static String canRead = "原文件不能读"; + private static String copyFalse = "备份失败!"; + private static String cFromFile = "创建原文件出错:"; + private static String ctoFile = "创建备份文件出错:"; + + + /** + * 写入文件 + * FileUtil.byteWriteFile(getExternalFilesDir("123"),"test.jpg",nv21); + * + * @param filePath + * @param fileName + * @param bytes + */ + public static void byteWriteFile(File filePath, String fileName, byte[] bytes) { + BufferedOutputStream bout = null; + try { + File file = new File(filePath, fileName); + if (file.exists() == false) { + if (file.getParentFile().exists() == false) { + file.getParentFile().mkdirs(); + } + file.createNewFile(); + } + bout = new BufferedOutputStream(new FileOutputStream(file, false)); + bout.write(bytes); + bout.flush(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (bout != null) { + try { + bout.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + /** + * 获取文件名 + * + * @param path 路径 + * @return 文件名 + */ + public static String getFileName(String path) { + int index = path.lastIndexOf("/"); + return path.substring(index + 1); + } + + /** + * 根据文件路径获取文件 + * + * @param path 路径 + * @return + */ + public static File getFileByPath(String path) { + File file = new File(path); + if (file.exists()) { + return new File(path); + } else { + return null; + } + } + + /** + * 重命名文件 + * + * @param filePath 文件路径 + * @param newName 新名称 + * @return {@code true}: 重命名成功
{@code false}: 重命名失败 + */ + public static boolean rename(String filePath, String newName) { + return rename(getFileByPath(filePath), newName); + } + + /** + * 重命名文件 + * + * @param file 文件 + * @param newName 新名称 + * @return {@code true}: 重命名成功
{@code false}: 重命名失败 + */ + public static boolean rename(File file, String newName) { + // 文件为空返回false + if (file == null) return false; + // 文件不存在返回false + if (!file.exists()) return false; + // 新的文件名为空返回false + if (AppUtil.isEmpty(newName)) return false; + // 如果文件名没有改变返回true + if (newName.equals(file.getName())) return true; + File newFile = new File(file.getParent() + File.separator + newName); + // 如果重命名的文件已存在返回false + return !newFile.exists() + && file.renameTo(newFile); + } + + + /** + * 判断文件是否存在 + * + * @param path 文件的路径,含文件后缀和文件名 + * @return 是否存在 + */ + public static boolean isFileExists(String path) { + File file = new File(path); + if (file.exists()) { + return true; + } else { + return false; + } + } + + /** + * 判断文件是否存在 + * + * @return 是否存在 + */ + public static boolean isFileExists(File file) { + if (file.exists()) { + return true; + } else { + return false; + } + } + + /** + * 删除文件夹及文件夹下所有内容 + * + * @param path 文件夹路径 + * @return 返回是否删除成功 + */ + public static boolean deleteFiles(String path) { + if (getFileByPath(path) != null) { + return deleteFiles(getFileByPath(path)); + } else { + return false; + } + } + + /** + * 删除文件夹及文件夹下所有内容 + * + * @param file 文件 + * @return 返回是否删除成功 + */ + public static boolean deleteFiles(File file) { + try { + if (file.exists()) { // 判断文件是否存在 + if (file.isFile()) { // 判断是否是文件 + file.delete(); // delete()方法 + } else if (file.isDirectory()) { // 否则如果它是一个目录 + File files[] = file.listFiles(); // 声明目录下所有的文件 files[]; + for (int i = 0; i < files.length; i++) { // 遍历目录下所有的文件 + deleteFiles(files[i].getPath()); // 把每个文件 用这个方法进行迭代 + } + file.delete();//删除目录 + } + //file.delete(); + return true; + } else { + return false; + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取文件的Uri + * + * @param path 文件的路径 + * @return 文件的Uri + */ + public static Uri getUriFromFile(String path) { + File file = new File(path); + return Uri.fromFile(file); + } + + /** + * 获取文件指定文件的指定单位的大小 + * + * @param filePath 文件路径 + * @param sizeType 获取大小的类型1为B、2为KB、3为MB、4为GB + * @return double值的大小 + */ + public static double getFileOrFilesSize(String filePath, int sizeType) { + File file = new File(filePath); + long blockSize = 0; + try { + if (file.isDirectory()) { + blockSize = getFileSizes(file); + } else { + blockSize = getFileSize(file); + } + } catch (Exception e) { + e.printStackTrace(); + L.i("获取文件大小", "获取失败!"); + } + return FormetFileSize(blockSize, sizeType); + } + + /** + * 调用此方法自动计算指定文件或指定文件夹的大小 + * + * @param filePath 文件路径 + * @return 计算好的带B、KB、MB、GB的字符串 + */ + public static String getAutoFileOrFilesSize(String filePath) { + File file = new File(filePath); + long blockSize = 0; + try { + if (file.isDirectory()) { + blockSize = getFileSizes(file); + } else { + blockSize = getFileSize(file); + } + } catch (Exception e) { + e.printStackTrace(); + L.i("获取文件大小", "获取失败!"); + } + return FormetFileSize(blockSize); + } + + /** + * 获取指定文件大小 + * + * @param file + * @return + * @throws Exception + */ + private static long getFileSize(File file) throws Exception { + long size = 0; + if (file.exists()) { + FileInputStream fis = null; + fis = new FileInputStream(file); + size = fis.available(); + } else { +// file.createNewFile(); + L.i("获取文件大小", "文件不存在!"); + } + return size; + } + + /** + * 获取目录下指定文件名的文件包括子目录 + *

大小写忽略

+ * + * @param dirPath 目录路径 + * @param fileName 文件名 + * @return 文件链表 + */ + public static List searchFileInDir(String dirPath, String fileName) { + return searchFileInDir(getFileByPath(dirPath), fileName); + } + + /** + * 获取目录下指定文件名的文件包括子目录 + *

大小写忽略

+ * + * @param dir 目录 + * @param fileName 文件名 + * @return 文件链表 + */ + public static List searchFileInDir(File dir, String fileName) { + if (dir == null || !dir.isDirectory()) return null; + List list = new ArrayList<>(); + File[] files = dir.listFiles(); + if (files != null && files.length != 0) { + for (File file : files) { + if (file.getName().toUpperCase().equals(fileName.toUpperCase())) { + list.add(file); + } + if (file.isDirectory()) { + list.addAll(searchFileInDir(file, fileName)); + } + } + } + return list; + } + + + /** + * 获取指定文件夹 + * + * @param f + * @return + * @throws Exception + */ + private static long getFileSizes(File f) throws Exception { + long size = 0; + File flist[] = f.listFiles(); + for (int i = 0; i < flist.length; i++) { + if (flist[i].isDirectory()) { + size = size + getFileSizes(flist[i]); + } else { + size = size + getFileSize(flist[i]); + } + } + return size; + } + + /** + * 转换文件大小 + * + * @param fileS + * @return + */ + private static String FormetFileSize(long fileS) { + DecimalFormat df = new DecimalFormat("#.00"); + String fileSizeString = ""; + String wrongSize = "0B"; + if (fileS == 0) { + return wrongSize; + } + if (fileS < 1024) { + fileSizeString = df.format((double) fileS) + "B"; + } else if (fileS < 1048576) { + fileSizeString = df.format((double) fileS / 1024) + "KB"; + } else if (fileS < 1073741824) { + fileSizeString = df.format((double) fileS / 1048576) + "MB"; + } else { + fileSizeString = df.format((double) fileS / 1073741824) + "GB"; + } + return fileSizeString; + } + + /** + * 转换文件大小,指定转换的类型 + * + * @param fileS + * @param sizeType + * @return + */ + private static double FormetFileSize(long fileS, int sizeType) { + DecimalFormat df = new DecimalFormat("#.00"); + double fileSizeLong = 0; + switch (sizeType) { + case SIZETYPE_B: + fileSizeLong = Double.valueOf(df.format((double) fileS)); + break; + case SIZETYPE_KB: + fileSizeLong = Double.valueOf(df.format((double) fileS / 1024)); + break; + case SIZETYPE_MB: + fileSizeLong = Double.valueOf(df.format((double) fileS / 1048576)); + break; + case SIZETYPE_GB: + fileSizeLong = Double.valueOf(df.format((double) fileS / 1073741824)); + break; + default: + break; + } + return fileSizeLong; + } + + /** + * 复制文件 + * + * @param fromFilePath 旧文件地址和名称 + * @param toFilePath 新文件地址和名称 + * @return 返回备份文件的信息,ok是成功,其它就是错误 + */ + public static File copyFile(String fromFilePath, String toFilePath) { + File fromFile = null; + File toFile = null; + try { + fromFile = new File(fromFilePath); + } catch (Exception e) { + L.i(cFromFile + e.getMessage()); + return null; + } + + try { + toFile = new File(toFilePath); + if (toFile.isDirectory()) { + toFile = new File(toFilePath.endsWith("/") ? toFilePath + fromFile.getName() : toFilePath + "/" + fromFile.getName()); + } + } catch (Exception e) { + L.i(ctoFile + e.getMessage()); + return null; + } + + if (!fromFile.exists()) { + L.i(urlNull); + return null; + } + if (!fromFile.isFile()) { + L.i(isFile); + return null; + } + if (!fromFile.canRead()) { + L.i(canRead); + return null; + } + + // 复制到的路径如果不存在就创建 + if (!toFile.getParentFile().exists()) { + toFile.getParentFile().mkdirs(); + } + + if (toFile.exists()) { + toFile.delete(); + } + + if (!toFile.canWrite()) { + //return notWrite; + } + + try { + FileInputStream fosfrom = new FileInputStream( + fromFile); + FileOutputStream fosto = new FileOutputStream(toFile); + byte bt[] = new byte[1024]; + int c; + + while ((c = fosfrom.read(bt)) > 0) { + fosto.write(bt, 0, c); // 将内容写到新文件当中 + } + //关闭数据流 + fosfrom.close(); + fosto.close(); + } catch (Exception e) { + e.printStackTrace(); + L.i(copyFalse + e.getMessage()); + return null; + } + return toFile; + } + + /** + * 创建文件 + * + * @param path 文件路径 + * @return 创建的文件 + */ + public static synchronized File createNewFile(String path) { + File file = new File(path); + String parentPath = path.substring(0, path.lastIndexOf("/") + 1); + File parentFile = new File(parentPath); + if (!parentFile.exists()) { + parentFile.mkdirs(); + } + if (!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + return file; + } + + /*** + * 根据文件后缀回去MIME类型 + ****/ + + private static String getMIMEType(File file) { + String type = "*/*"; + String fName = file.getName(); + //获取后缀名前的分隔符"."在fName中的位置。 + int dotIndex = fName.lastIndexOf("."); + if (dotIndex < 0) { + return type; + } + /* 获取文件的后缀名*/ + String end = fName.substring(dotIndex, fName.length()).toLowerCase(); + if (end == "") return type; + //在MIME和文件类型的匹配表中找到对应的MIME类型。 + for (int i = 0; i < MIME_MapTable.length; i++) { //MIME_MapTable??在这里你一定有疑问,这个MIME_MapTable是什么? + if (end.equals(MIME_MapTable[i][0])) + type = MIME_MapTable[i][1]; + } + return type; + } + + /** + * 获取全路径中的文件拓展名 + * + * @param file 文件 + * @return 文件拓展名 + */ + public static String getFileExtension(File file) { + if (file == null) return null; + return getFileExtension(file.getPath()); + } + + /** + * 获取全路径中的文件拓展名 + * + * @param filePath 文件路径 + * @return 文件拓展名 + */ + public static String getFileExtension(String filePath) { + if (AppUtil.isEmpty(filePath)) return filePath; + int lastPoi = filePath.lastIndexOf('.'); + int lastSep = filePath.lastIndexOf(File.separator); + if (lastPoi == -1 || lastSep >= lastPoi) return ""; + return filePath.substring(lastPoi + 1); + } + + /** + * 调用系统应用打开文件 + * + * @param context 上下文 + * @param file 文件 + */ + public static void openFile(Context context, File file) { + Intent intent = new Intent(); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + //设置intent的Action属性 + intent.setAction(Intent.ACTION_VIEW); + //获取文件file的MIME类型 + String type = getMIMEType(file); + //设置intent的data和Type属性。 + intent.setDataAndType(Uri.fromFile(file), type); + //跳转 + try { + context.startActivity(intent); + } catch (Exception e) { + e.printStackTrace(); + L.i("找不到打开此文件的应用!"); + } + } + + /** + * 保存文本文件 + * FileUtil.saveStrFile("测试", "log.txt", FILE_STR_PATH, true); + * + * @param res 写入内容 + * @param fileName 文件名 + * @param filePath 路径 + * @param append true新增 false替换 + * @return + */ + public static boolean saveStrFile(String res, String fileName, String filePath, boolean append) { + boolean flag = true; + BufferedReader bufferedReader = null; + BufferedWriter bufferedWriter = null; + try { + File file = new File(filePath, fileName); + + if (!file.exists()) { + file.getParentFile().mkdirs(); + file.createNewFile(); + } + bufferedReader = new BufferedReader(new StringReader(res)); + bufferedWriter = new BufferedWriter(new FileWriter(file, append)); + char buf[] = new char[1024]; //字符缓冲区 + int len; + while ((len = bufferedReader.read(buf)) != -1) { + bufferedWriter.write(buf, 0, len); + } + bufferedWriter.flush(); + bufferedReader.close(); + bufferedWriter.close(); + } catch (IOException e) { + e.printStackTrace(); + flag = false; + return flag; + } finally { + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return flag; + } + + public static void saveLog(String... logs) { + if (!isSaveLog) { + return; + } + new Thread() { + @Override + public void run() { + super.run(); + StringBuilder sb = new StringBuilder(); + for (String log : logs) { + sb.append("===") + .append((AppUtil.formatDateGetCurrentTime())) + .append("===") + .append("\n") + .append(log) + .append("\n"); + } + String fileName = "log" + AppUtil.formatDateGetDay(System.currentTimeMillis()) + ".txt"; + FileUtil.saveStrFile(sb.toString(), fileName, FILE_STR_PATH, true); + + } + }.start(); + } + + private static final String[][] MIME_MapTable = { + // {后缀名,MIME类型} + {".3gp", "video/3gpp"}, + {".apk", "application/vnd.android.package-archive"}, + {".asf", "video/x-ms-asf"}, + {".avi", "video/x-msvideo"}, + {".bin", "application/octet-stream"}, + {".bmp", "image/bmp"}, + {".c", "text/plain"}, + {".class", "application/octet-stream"}, + {".conf", "text/plain"}, + {".cpp", "text/plain"}, + {".doc", "application/msword"}, + {".docx", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, + {".xls", "application/vnd.ms-excel"}, + {".xlsx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, + {".exe", "application/octet-stream"}, + {".gif", "image/gif"}, + {".gtar", "application/x-gtar"}, + {".gz", "application/x-gzip"}, + {".h", "text/plain"}, + {".htm", "text/html"}, + {".html", "text/html"}, + {".jar", "application/java-archive"}, + {".java", "text/plain"}, + {".jpeg", "image/jpeg"}, + {".jpg", "image/jpeg"}, + {".js", "application/x-javascript"}, + {".log", "text/plain"}, + {".m3u", "audio/x-mpegurl"}, + {".m4a", "audio/mp4a-latm"}, + {".m4b", "audio/mp4a-latm"}, + {".m4p", "audio/mp4a-latm"}, + {".m4u", "video/vnd.mpegurl"}, + {".m4v", "video/x-m4v"}, + {".mov", "video/quicktime"}, + {".mp2", "audio/x-mpeg"}, + {".mp3", "audio/x-mpeg"}, + {".mp4", "video/mp4"}, + {".mpc", "application/vnd.mpohun.certificate"}, + {".mpe", "video/mpeg"}, + {".mpeg", "video/mpeg"}, + {".mpg", "video/mpeg"}, + {".mpg4", "video/mp4"}, + {".mpga", "audio/mpeg"}, + {".msg", "application/vnd.ms-outlook"}, + {".ogg", "audio/ogg"}, + {".pdf", "application/pdf"}, + {".png", "image/png"}, + {".pps", "application/vnd.ms-powerpoint"}, + {".ppt", "application/vnd.ms-powerpoint"}, + {".pptx", + "application/vnd.openxmlformats-officedocument.presentationml.presentation"}, + {".prop", "text/plain"}, {".rc", "text/plain"}, + {".rmvb", "audio/x-pn-realaudio"}, {".rtf", "application/rtf"}, + {".sh", "text/plain"}, {".tar", "application/x-tar"}, + {".tgz", "application/x-compressed"}, {".txt", "text/plain"}, + {".wav", "audio/x-wav"}, {".wma", "audio/x-ms-wma"}, + {".wmv", "audio/x-ms-wmv"}, + {".wps", "application/vnd.ms-works"}, {".xml", "text/plain"}, + {".z", "application/x-compress"}, + {".zip", "application/x-zip-compressed"}, {"", "*/*"}}; +} diff --git a/app/src/main/res/layout/activity_login_face.xml b/app/src/main/res/layout/activity_login_face.xml index 81967a0..ac9a973 100644 --- a/app/src/main/res/layout/activity_login_face.xml +++ b/app/src/main/res/layout/activity_login_face.xml @@ -68,9 +68,9 @@ android:id="@+id/tvSimilarValue" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="30sp" + android:textSize="26sp" android:layout_marginTop="80dp" - tools:text="0" + tools:text="0.618,3次" android:layout_gravity="center_horizontal" android:textColor="@color/white"/>