Android记录文件日志工具类



import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.util.Log;

import com.bitvf.bitcoinWallet.base.JJApplication;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class FileLogger {
	private static final String TAG = "FileLogger";
	private static final long MB = 1024 * 1024;
	private static final long LOG_LIMIT = 1 * 1024 * 1024;
	private static final long FREE_SPACE_LIMIT = 5 * 1024 * 1024;
	private static final long FREE_SPACE_TIMER = 20 * 60 * 1000;
	private static final int DAY_LIMIT = 3;	//日志保存的天数
	private static final String INFO_COLOR = "green";
	private static final String ERROR_COLOR = "red";
	private static final String WARN_COLOR = "orange";
	private static final String DEBUG_COLOR = "blue";
	private ExecutorService singleThreadService = Executors.newSingleThreadExecutor();
	private Timer timer = null;
	private boolean spaceAvailable = true;

	void d(String tag, String msg) {
		startThreadService(DEBUG_COLOR, "[" + tag + "]" + msg);
	}

	void e(String tag, String msg) {
		startThreadService(ERROR_COLOR, "[" + tag + "]" + "[ERROR]" + msg);
	}

	void i(String tag, String msg) {
		startThreadService(INFO_COLOR, "[" + tag + "]" + msg);
	}

	void w(String tag, String msg) {
		startThreadService(WARN_COLOR, "[" + tag + "]" + "[WARN]" + msg);
	}

	void v(String tag, String msg) {
		startThreadService(INFO_COLOR, "[" + tag + "]" + msg);
	}

	private void startThreadService(String tag, String msg) {
		File file = getLogRoot();
		if ((file == null) || (!file.exists())) {
			return;
		}
		singleThreadService.execute(getWriterRunnable(tag, msg));
	}

	private Runnable getWriterRunnable(final String tag, final String msg) {
		Runnable runnable = new Runnable() {
			public void run() {
				try {
					File file = getLogRoot();
					if ((file == null) || (!file.exists())) {
						return;
					}
					if ((timer == null) && (!freeSpace())) {
						return;
					}
					FileLogger.this.startCleanUpTimer();
					File availableFile = FileLogger.this.getAvailableFile();
					if (availableFile == null) {
						return;
					}
					boolean available = false;
					if (!availableFile.exists()) {
						try {
							availableFile.createNewFile();
							available = true;
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
					if (!availableFile.exists()) {
						return;
					}
					FileOutputStream fileOutputStream = null;
					try {
						fileOutputStream = new FileOutputStream(availableFile, true);
						if (available) {
							String header = "<header>"
									+ "<meta http-equiv=" + "\""
									+ "Content-Type" + "\"" + " content="
									+ "\"" + "text/html; charset=UTF-8" + "\">"
									+ "</header>";
							fileOutputStream.write(header.getBytes());
						}
						SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
						String strDate = simpleDateFormat.format(new Date());
						String body = "<p><font color =\"" + tag + "\">" + strDate + " " + msg.replaceAll(">", ">").replaceAll("<", "<") + "</p>";
						fileOutputStream.write(body.getBytes());
					} catch (FileNotFoundException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					} finally {
						try {
							if (fileOutputStream != null) {
								fileOutputStream.close();
							}
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
					return;
				} catch (NullPointerException e) {
					e.printStackTrace();
					if(null != e) {
						Log.e(TAG, e.getMessage());
					}
				} catch (Exception e) {
					e.printStackTrace();
					if(null != e) {
						Log.e(TAG, e.getMessage());
					}
				}
			}
		};
		return runnable;
	}

	private File getAvailableFile() {
		File rootFile = getLogRoot();
		if ((rootFile == null) || (!rootFile.exists())) {
			return null;
		}
		removeOldFolders();
		File file = getLogFolder();
		int index = 0;
		List<File> fileList = null;
		File[] files = file.listFiles();
		if ((files != null) && (files.length > 0)) {
			fileList = Arrays.asList(files);
			if (fileList.size() > 1) {
				getSortedFileListByName(fileList);
				files = (File[]) fileList.toArray();
			}
			String name = files[0].getName();
			String cntName = name.substring(0, name.indexOf("."));
			try {
				index = Integer.parseInt(cntName);
			} catch (Exception e) {
				e.printStackTrace();
				Log.e(TAG, "Wrong cntName! : " + cntName);
			}
			if (files[0].length() >= MB / 2) {
				index++;
			}
		}
		String fileName = getLogFileName(index);
		return new File(file, fileName);
	}

	private static String getLogFileName(int index) {
		return String.format("%03d", index) + ".html";
	}

	private File getLogFolder() {
		File rootFile = getLogRoot();
		File file = new File(rootFile, getCurrentDate());
		if (!file.exists()) {
			file.mkdirs();
		}
		return file;
	}

	private void removeFolderBeforeDay(String strDate, int offset) {
		String strBeforeDate = getSpecifiedDayBefore(strDate, offset);
		File rootFile = getLogRoot();
		File file = new File(rootFile, strBeforeDate);
		if (file.exists()) {
			deleteFile(file);
		}
	}

	private void removeOldFolders() {
		File file = getLogRoot();
		if ((file == null) || (!file.exists())) {
			return;
		}
		String strDate = getCurrentDate();
		String strYesterdayDate = getSpecifiedDayBefore(strDate, -1);
		String strBeforeYesterdayDate = getSpecifiedDayBefore(strDate, -2);
		File[] files = file.listFiles();
		if (files == null) {
			return;
		}
		for (File subFile : files) {
			if (subFile.isDirectory()) {
				String fileName = subFile.getName();
				if (!fileName.contains(strDate) && !fileName.contains(strYesterdayDate) && !fileName.contains(strBeforeYesterdayDate)) {
					deleteFile(subFile);
				}
			} else {
				subFile.delete();
			}
		}
	}

	private static void deleteFile(File file) {
		if (file == null) {
			return;
		}
		if (file.exists()) {
			if (file.isDirectory()) {
				File[] files = file.listFiles();
				if (files != null) {
					for (File subFile : files) {
						deleteFile(subFile);
					}
				}
				file.delete();
			} else {
				file.delete();
			}
		}
	}

	private static long getDirSize(File floder) {
		if (floder == null) {
			return 0L;
		}
		if (floder.isDirectory()) {
			long size = 0L;
			File[] files = floder.listFiles();
			if (files != null) {
				for (File subFile : files) {
					size += getDirSize(subFile);
				}
			}
			return size;
		}
		return floder.length();
	}

	private static String getSpecifiedDayBefore(String strDate, int offset) {
		Calendar calendar = Calendar.getInstance();
		Date date = null;
		try {
			date = new SimpleDateFormat("yyyyMMdd").parse(strDate);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		calendar.setTime(date);
		calendar.add(Calendar.DATE, offset);
		String dateTime = new SimpleDateFormat("yyyyMMdd").format(calendar.getTime());
		return dateTime;
	}

	private static File getStorageDir() {
		if (Environment.getExternalStorageState().equals("mounted")) {
			return Environment.getExternalStorageDirectory();
		}
		return Environment.getDataDirectory();
	}

	private static void getSortedFileListByName(List<File> fileList) {
		Collections.sort(fileList, new Comparator<File>() {
			public int compare(File lhs, File rhs) {
				return lhs.getName().compareTo(rhs.getName());
			}
		});
	}

	private boolean spaceIsAlearting() {
		return getCurrentAvailabeSpace() < FREE_SPACE_LIMIT;
	}

	private boolean logSizeAlearting() {
		return getDirSize(getLogRoot()) > LOG_LIMIT;
	}

	boolean freeSpace() {
		File file = getLogRoot();
		if ((file == null) || (!file.exists())) {
			return false;
		}
		if (spaceIsAlearting()) {
			Log.w(TAG, "there is no availabe free space and try to free space");
			freeLogFolder();
			return !spaceIsAlearting();
		}
		checkAndFreeLogFiles();
		return true;
	}

	private void freeLogFolder() {
		deleteFile(getLogRoot());
	}

	private void freeOldFolders() {
		File[] files = getLogRoot().listFiles();
		for (File file : files) {
			if ((file.isDirectory()) && (!file.getName().contains(getCurrentDate()))) {
				deleteFile(file);
			} else {
				file.delete();
			}
		}
	}
	
	private String getCurrentDate() {
		return new SimpleDateFormat("yyyyMMdd").format(new Date());
	}

	private void freeOldFiles() {
		File[] files = getLogFolder().listFiles();
		if (files != null) {
			List<File> fileList = Arrays.asList(files);
			getSortedFileListByName(fileList);
			if (fileList.size() > 5) {
				int i = fileList.size();
				for (int j = 5; j < i; j++) {
					Log.w(TAG, "try to delete file : " + fileList.get(j).getAbsoluteFile());
					fileList.get(j).delete();
				}
			}
		}
	}

	@TargetApi(18)
	private static long getCurrentAvailabeSpace() {
		StatFs statFs = new StatFs(getStorageDir().getPath());
		if (Build.VERSION.SDK_INT >= 18) {
			return statFs.getAvailableBytes();
		}
		long availableBlocks = statFs.getAvailableBlocks();
		long blockSize = statFs.getBlockSize();
		return availableBlocks * blockSize;
	}

	File getLogRoot() {
		try {
			Context context = JJApplication.getInstance();
			String filePath = "/Android/data/" + context.getPackageName() + "/log/";
			File file = new File(getStorageDir(), filePath);
			synchronized (this) {
				if (!file.exists()) {
					file.mkdirs();
				}
			}
			return file;
		} catch (Throwable e) {
			return null;
		}
	}

	void checkAndFreeLogFiles() {
		if (logSizeAlearting()) {
			Log.w(TAG, "the log size is > 8M, try to free log files");
			freeOldFolders();
			Log.w(TAG, "old folders are deleted");
			if (logSizeAlearting()) {
				Log.w(TAG, "try to delete old log files");
				freeOldFiles();
			}
		}
	}

	private void startCleanUpTimer() {
		synchronized (this) {
			if (timer == null) {
				timer = new Timer();
				TimerTask task = new TimerTask() {
					public void run() {
						singleThreadService.execute(new Runnable() {
							public void run() {
								try {
									File file = getLogRoot();
									if ((file == null) || (!getLogRoot().exists())) {
										return;
									}
									spaceAvailable = freeSpace();
								} catch (NullPointerException e) {
									e.printStackTrace();
									Log.e(TAG, e.getMessage());
								} catch (Exception e) {
									e.printStackTrace();
									Log.e(TAG, e.getMessage());
								}
							}
						});
					}
				};
				timer.schedule(task, FREE_SPACE_TIMER, FREE_SPACE_TIMER);
			}
		}
	}
}

关注公众号“大模型全栈程序员”回复“小程序”获取1000个小程序打包源码。更多免费资源在http://www.gitweixin.com/?p=2627

发表评论

邮箱地址不会被公开。 必填项已用*标注