Android 本地日志保存
下面介绍一个本地日志保存的工具类,当然需要先获取到文件存储权限
没啥说的,直接上代码吧
import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by Administrator on 2018\12\12 0012.
*/
public class WriteLogSDCard {
private static final String FOLDER_NAME="日志文件夹名称";
private static final String FILE_NAME="日志文件名称";
private static volatile Context sContext;
private static String packageName = "";
static HnLogLinkedBlockingDeque<String> logDeque = new HnLogLinkedBlockingDeque<String>(15000);
private static final int[] INTERVAL_RETRY_INIT = new int[]{1, 2, 4, 8, 16, 29}; //重试时间
private static AtomicInteger retryInitTimes = new AtomicInteger(0);
public static final SimpleDateFormat timeFormatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
private static String logTime = "";
private static String logPath = "";
public static String nowUsedFile = "";
static final ReentrantLock lock = new ReentrantLock();
protected static Object formatterLock = new Object();
private static long nextDayTime;
private static long nextSecondMinuteTime;
static long lastWriterErrorTime = 0;
private static boolean bActive = true;
private static FileWriter writer;
private static Handler retryInitHandler = new Handler(Looper.getMainLooper());
/**
* 初始化日志
*/
public static void init(Context context) {
sContext = context;
initRunnable.run();
}
/**
* 将日志写到文件
*/
private static void writeLogToFile(String log) {
try {
// 如果SD卡不可用,则不写日志,以免每次都抛出异常,影响性能
if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
System.out.println("writeLogToFile not ready");
return;
}
if (null == writer) {
System.out.println("can not write SxbLog.");
long now = System.currentTimeMillis();
if (lastWriterErrorTime == 0) {
lastWriterErrorTime = now;
} else if (now - lastWriterErrorTime > 60 * 1000) {
try {
initLogFile(System.currentTimeMillis());
} catch (IOException e1) {
e1.printStackTrace();
}
lastWriterErrorTime = now;
}
} else {
long now = System.currentTimeMillis();
if (now > nextDayTime) {
initLogFile(now);
}
//加入消息的时候记录时间
if (lock.tryLock()) {
try {
writer.write(log);
writer.flush();
} finally {
lock.unlock();
}
} else {
if (!insertLogToCacheHead(log)) {
System.out.println("insertLogToCacheHead failed!");
}
}
}
} catch (Throwable e) {
if (e instanceof IOException && e.getMessage().contains("ENOSPC")) {
e.printStackTrace();
} else {
try {
initLogFile(System.currentTimeMillis());
} catch (Throwable e1) {
e1.printStackTrace();
}
}
}
}
/**
* 写日志线程
*/
static Thread takeThread = new Thread() {
public void run() {
while (bActive) {
synchronized (this) {
try {
String log;
log = logDeque.take();
if (null != log) {
writeLogToFile(log);
}
} catch (Exception e) {
System.out.println("write log file error: " + e.toString());
} catch (AssertionError ignore) {
System.out.println("--------------");
}
}
}
}
};
private static String getDateStr(long nowCurrentMillis) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(nowCurrentMillis);
SimpleDateFormat logFileFormatter = new SimpleDateFormat("yyyyMMdd");
SimpleDateFormat timeFormatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
logTime = timeFormatter.format(nowCurrentMillis);
String thisLogName = logFileFormatter.format(calendar.getTime());
setNextSecond(calendar);
setNextHour(calendar);
return thisLogName;
}
private static void setNextHour(Calendar setSecondedCalendar) {
setSecondedCalendar.add(Calendar.DAY_OF_MONTH, 1);
nextDayTime = setSecondedCalendar.getTimeInMillis();
}
private static void setNextSecond(Calendar calendar) {
calendar.set(Calendar.MILLISECOND, 0);
nextSecondMinuteTime = calendar.getTimeInMillis() + 1000;
}
public static String getLogFileName(String dataStr) {
return FILE_NAME + dataStr + ".log";
}
private static synchronized void checkNextMinuteTime(long currentTimeMillis) {
if (currentTimeMillis > nextSecondMinuteTime) {
synchronized (formatterLock) {
logTime = timeFormatter.format(currentTimeMillis);
nextSecondMinuteTime = nextSecondMinuteTime + 1000;
}
}
}
/**
* 初始化日志文件
*/
static synchronized void initLogFile(long nowCurrentTimeMillis) throws IOException {
logPath = Environment.getExternalStorageDirectory().getPath() + "/"+FOLDER_NAME+"/" + packageName.replace(".", "/") + "/";
File tmpeFile = new File(logPath);
if (!tmpeFile.exists()) {
tmpeFile.mkdirs();
}
nowUsedFile = logPath + getLogFileName(getDateStr(nowCurrentTimeMillis));
try {
tmpeFile = new File(nowUsedFile);
if (!tmpeFile.exists()) {
boolean b = tmpeFile.createNewFile();
if (null != writer) {
writer.write(logTime + "|" + "|D|" + android.os.Build.MODEL + " " + android.os.Build.VERSION.RELEASE + " create newLogFile " + tmpeFile.getName() + " " + b + "\n");
writer.flush();
}
} else {
if (null != writer) {
writer.write(logTime + "|" + "|E|" + android.os.Build.MODEL + " " + android.os.Build.VERSION.RELEASE + "|newLogFile " + tmpeFile.getName() + " is existed.\n");
writer.flush();
}
}
} catch (Throwable e) {
e.printStackTrace();
}
writer = new FileWriter(tmpeFile, true);
}
static void delete7DaysBeforeFiles(long today) {
logPath = Environment.getExternalStorageDirectory().getPath() + "/"+FOLDER_NAME+"/" + packageName.replace(".", "/");
long day = (long) 1 * 24 * 60 * 60 * 1000;
File tmpeFile;
//删除前一个月的
for (long i = (today - 7 * day); i > today - 37 * day; i = i - day) {
String date = getDateStr(i);
nowUsedFile = logPath + getLogFileName(date);
try {
// Log.i("logtest", "find file: " + getLogFileName(date));
tmpeFile = new File(nowUsedFile);
if (tmpeFile.exists()) {
// Log.e("logtest", date + " tmpFile exists" + " delete ");
tmpeFile.delete();
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}
/**
* 日志初始化Runnable
*/
public static Runnable initRunnable = new Runnable() {
@Override
public void run() {
if (null == sContext) {
return;
}
new Thread("LVBLogInitThread") {
@Override
public void run() {
try {
try {
packageName = sContext.getPackageName();
} catch (Exception e) {
packageName = "unknown";
}
delete7DaysBeforeFiles(System.currentTimeMillis());
initLogFile(System.currentTimeMillis());
if (!takeThread.isAlive()) {
takeThread.setName("logWriteThread");
takeThread.start();
}
retryInitHandler.removeCallbacks(initRunnable);
} catch (Exception e) {
int times = retryInitTimes.get();
System.out.println("ILVBLog init post retry " + times + " times, interval " + INTERVAL_RETRY_INIT[times]);
retryInitHandler.removeCallbacks(initRunnable);
retryInitHandler.postDelayed(initRunnable, INTERVAL_RETRY_INIT[times] * 60000);
times++;
if (times >= INTERVAL_RETRY_INIT.length) {
times = 0;
}
retryInitTimes.set(times);
}
}
}.start();
}
};
public static void writeLog(String TAG, String msg, Throwable tr) {
long now = System.currentTimeMillis();
if (now >= nextSecondMinuteTime) {
checkNextMinuteTime(now);
}
String message = "[" + logTime + "]" + TAG + ":" + msg + "\n";
if (null != tr) {
message = "[" + logTime + "]" + TAG + ":" + msg + "\n" + android.util.Log.getStackTraceString(tr) + "\n";
}
addLogToCache(message);
}
/**
* 添加日志到缓存
*/
private static boolean addLogToCache(String log) {
try {
logDeque.add(log);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 添加缓冲头部
*/
private static boolean insertLogToCacheHead(String log) {
try {
logDeque.addFirst(log);
return true;
} catch (Exception e) {
return false;
}
}
public static void pauseLogThread() {
bActive = false;
writeLog("pauseLogThread", "pauseLogThread->enter", null);
}
public static void resumeLogThread() {
bActive = true;
retryInitHandler.postDelayed(initRunnable, 0);
}
}
当然还是免不了要初始化的
WriteLogSDCard.init(HnApplication.getContext());
初始化之后只需要很简单的调用就好了
WriteLogSDCard.writeLog("房间定时器--Activity", "关闭", Throwable);
网友评论