实例1
导出结果
功能实现
FileLogger.append(context," 日志导出:记录android信息"); //写日志 String s = FileLogger.readAll(context); //读日志 FileLogger.exportToUdisk(context); //导出 FileLogger.clear(context); //清理删除
FileLogger类
import android.content.Context; import android.util.Log; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; public class FileLogger { public static final String FILE_NAME = "run_log.txt"; private static final SimpleDateFormat FMT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); /** 追加一条日志 */ public static void append(Context ctx, String msg) { String line = FMT.format(new Date()) + " " + msg + "\n"; try { File file = getLogFile(ctx); FileWriter fw = new FileWriter(file, true); // true = 追加 fw.write(line); fw.close(); } catch (IOException e) { e.printStackTrace(); } } /** 日志文件对象 */ public static File getLogFile(Context ctx) { File dir = ctx.getExternalFilesDir(null); // /Android/data/包名/files if (dir != null && !dir.exists()) dir.mkdirs(); return new File(dir, FILE_NAME); } /** 读取全部内容 */ public static String readAll(Context ctx) { File file = getLogFile(ctx); if (!file.exists()) return ""; StringBuilder sb = new StringBuilder(); try { java.io.BufferedReader br = new java.io.BufferedReader(new java.io.FileReader(file)); String l; while ((l = br.readLine()) != null) sb.append(l).append('\n'); br.close(); } catch (IOException e) { e.printStackTrace(); } return sb.toString(); } public static void clear(Context ctx) { File file = getLogFile(ctx); if (file.exists()) file.delete(); } public static boolean exportToUdisk(Context context){ File sourceFile = getLogFile(context); if (!sourceFile.exists()) { Log.e("FileLogger", "exportToUdisk: 日志文件不存在!"); return false; } //-------------------------------------------------- UtilsPath.parentFolder=""; UtilsPath.creatUdiskPathAndFolder(context); File usbDir = new File(UtilsPath.parentFolder);//U盘路径:mnt/media_rw/01BC-F8F6/RX2018 if (!usbDir.exists() || !usbDir.canWrite()) { // 尝试另一个常见路径 usbDir = new File("/mnt/usbhost"); if (!usbDir.exists() || !usbDir.canWrite()) { Log.e("FileLogger", "exportToUdisk: 找不到 U 盘或没有写权限!"); return false; // 找不到 U 盘或没有写权限 } } File destFile = new File(usbDir, "run_log_export.txt"); // 2. 开始复制 try { FileInputStream in = new FileInputStream(sourceFile); FileOutputStream out = new FileOutputStream(destFile); byte[] buffer = new byte[4096]; int length; while ((length = in.read(buffer)) > 0) { out.write(buffer, 0, length); } in.close(); out.close(); Log.e("FileLogger", "exportToUdisk: 成功导出至U盘"); return true; } catch (IOException e) { e.printStackTrace(); return false; } } }获取U盘
*U盘的两个路径
方法1 通过BroadcastReceiver广播 获取
*程序识别到的U盘目录是 /storage/28BA-794A(28BA-794A 是我的U盘名字)//
方法2 自写的public static String getUdiskPath(Context context);
*系统中还有一个相同名字的U盘 那就是/mnt/media_rw/28BA-794A
*路径1:/storage/28BA-794A 读正常,写总是提示Permission denied 没有权限;(没有解决)
*路径2:/mnt/media_rw/28BA-794A 读写正常(推荐)
package com.example.x6.utils; import android.content.Context; import android.os.storage.StorageManager; import android.util.Log; import com.example.x6.com.variant.Global; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.List; public class UtilsPath { public static String parentFolder = ""; public static String wordFolder = ""; public static String excelFolder = ""; public static String otherFolder = ""; public static String projectFolder = ""; public static String ExcelSampleDocx = ""; public static String ExcelByGroupDocx = ""; public static String ExcelJTJitemDocx = ""; public static String ExcelJTJitemDocx1= ""; //检测导入文件 public static String ExcelCardDocx = ""; private static final String TAG = "UtilsPath"; //=====================================================获取U盘路径 public static String getUdiskPath(Context context){ try{ StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); Class storeManagerClazz = Class.forName("android.os.storage.StorageManager"); Method getVolumesMethod = storeManagerClazz.getMethod("getVolumes"); List<?> volumeInfos = (List<?>)getVolumesMethod.invoke(storageManager); Class volumeInfoClazz = Class.forName("android.os.storage.VolumeInfo"); Field udiskPath = volumeInfoClazz.getDeclaredField("internalPath"); Method getFsUuidMethod = volumeInfoClazz.getMethod("getFsUuid"); if(volumeInfos != null){ for(Object volumeInfo:volumeInfos){ String uuid = (String)getFsUuidMethod.invoke(volumeInfo); if(uuid != null){ String sUdiskPath = (String)udiskPath.get(volumeInfo); // 结果是 /mnt/media_rw/28BA-794A Log.e("TAG", "手动-U盘路径 = "+ sUdiskPath); return sUdiskPath; } } } }catch(Exception e){ Log.e(TAG," 确认 手动-U盘 error 100 = " + e.getMessage()); } return ""; } // ----------------------------------------/mnt/media_rw/01BC-F8F6 public static boolean creatUdiskPathAndFolder(Context context){ String path_Udisk = ""; //u盘路径错误-退出 //获取两种u盘路径的方式 String path_myself = getUdiskPath(context); //USBStatusReceiver自写程序获取 String path_auto = Global.ExternalStorageAddr; //USBStatusReceiver广播获取 if(path_auto == null ) { path_auto = "";} if(path_myself == null){ path_myself = "";} if (path_auto.contains("mnt")){ path_Udisk = path_auto; Log.e(TAG, "getpath: 获取-广播-外部设备路径 = " + path_Udisk ); } else if(path_myself.contains("mnt")){ path_Udisk = path_myself; } else{ Log.e(TAG, "creatUdiskPathAndFolder: u盘路径-错误" ); return false; } parentFolder = path_Udisk + "/RX2018"; otherFolder = path_Udisk + "/RX2018/other"; //备用 projectFolder= path_Udisk + "/RX2018/anti-chreat";//u盘+RX2018+工程名称 wordFolder = path_Udisk + "/RX2018/anti-chreat/word"; excelFolder = path_Udisk + "/RX2018/anti-chreat/excel"; ExcelSampleDocx = path_Udisk + "/RX2018/anti-chreat/ExcelSample.xlsx"; ExcelByGroupDocx = path_Udisk + "/RX2018/anti-chreat/ExcelByGroup.xlsx"; ExcelJTJitemDocx = path_Udisk + "/RX2018/anti-chreat/ExcelJTJitem.xlsx"; ExcelCardDocx = path_Udisk + "/RX2018/anti-chreat/testParamter.xlsx"; return creatFolder(); } //===================================================== public static boolean creatFolder() { try { //创建RX2022文件夹(内部包含了word1 word2 连个文件夹 ) File file = new File(parentFolder); if (!file.exists()){file.mkdir();} //新建/RX2018文件夹 file = new File(otherFolder); if (!file.exists()){file.mkdir();} //新建/RX2018/other文件夹 file = new File(projectFolder); if (!file.exists()){file.mkdir();} //新建/RX2018/anti-chreat文件夹 file = new File(wordFolder); if (!file.exists()){file.mkdir();} //新建/RX2018/anti-chreat/word文件夹 file = new File(excelFolder); if (!file.exists()){file.mkdir();} //新建/RX2018/anti-chreat/excel文件夹 Log.e(TAG, "creatFolder:路径1-成功。"); return true; } catch (Exception e) { Log.e(TAG, "creatFolder失败。"); return false; } } }补充:如果需要在日志答应出类名 包名
调用 FileLogger.append(context,Thread.currentThread().getStackTrace(),"预扫描结束"); 或者 FileLogger.append(context,"test()","预扫描结束");
在FileLogger类添加
public static void append(Context context, String location, String msg) { append(context,location + " " + msg); } public static void append(Context context, StackTraceElement[] stackTrace, String msg) { String location =""; // 1. 获取调用栈信息 // stackTrace[0] 是 getStackTrace() // stackTrace[1] 是 getCurrentLocation() // stackTrace[2] 才是真正调用这个方法的地方(也就是你目前的业务代码) //StackTraceElement[] stackTrace = thread.getStackTrace(); if (stackTrace.length > 2) { StackTraceElement caller = stackTrace[2]; // 获取包名 String packageName = caller.getClassName(); packageName = packageName.substring(0, packageName.lastIndexOf('.')); // 获取类名(去掉包名前缀) String className = caller.getClassName(); className = className.substring(className.lastIndexOf('.') + 1); // 获取方法名 String methodName = caller.getMethodName(); // 拼接返回:包名 类名.方法名() location = packageName + " " + className + "." + methodName + "()"; } location = location + " " + msg; append(context, location); }