package me.xiaopan.sketchsample;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import me.xiaopan.sketch.SLogTracker;
import me.xiaopan.sketch.util.ObjectPool;
import me.xiaopan.sketch.util.SketchUtils;
public class SampleLogTracker implements SLogTracker {
private Context context;
private OutLog2SDCard outLog2SDCard;
private ObjectPool<LogEntry> logEntryObjectPool;
private SimpleDateFormat logTimeDateFormat;
private boolean closed;
public SampleLogTracker(Context context) {
this.context = context.getApplicationContext();
}
private void install() {
if (outLog2SDCard == null) {
synchronized (this) {
if (outLog2SDCard == null) {
outLog2SDCard = new OutLog2SDCard(context);
}
}
}
if (logEntryObjectPool == null) {
synchronized (this) {
if (logEntryObjectPool == null) {
logEntryObjectPool = new ObjectPool<LogEntry>(new ObjectPool.ObjectFactory<LogEntry>() {
@Override
public LogEntry newObject() {
return new LogEntry(logEntryObjectPool);
}
});
}
}
}
if (logTimeDateFormat == null) {
synchronized (this) {
if (logTimeDateFormat == null) {
logTimeDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS", Locale.US);
}
}
}
}
public void close() {
closed = true;
if (outLog2SDCard != null) {
outLog2SDCard.close();
outLog2SDCard = null;
}
if (logEntryObjectPool != null) {
logEntryObjectPool.clear();
logEntryObjectPool = null;
}
}
@Override
public boolean isClosed() {
return closed;
}
@Override
public void v(String tag, String msg) {
if (closed) {
return;
}
install();
String time = logTimeDateFormat.format(new Date());
LogEntry logEntry = logEntryObjectPool.get();
logEntry.set(time, "V", tag, msg);
outLog2SDCard.outLog(logEntry);
}
@Override
public void i(String tag, String msg) {
if (closed) {
return;
}
install();
String time = logTimeDateFormat.format(new Date());
LogEntry logEntry = logEntryObjectPool.get();
logEntry.set(time, "I", tag, msg);
outLog2SDCard.outLog(logEntry);
}
@Override
public void d(String tag, String msg) {
if (closed) {
return;
}
install();
String time = logTimeDateFormat.format(new Date());
LogEntry logEntry = logEntryObjectPool.get();
logEntry.set(time, "D", tag, msg);
outLog2SDCard.outLog(logEntry);
}
@Override
public void w(String tag, String msg) {
if (closed) {
return;
}
install();
String time = logTimeDateFormat.format(new Date());
LogEntry logEntry = logEntryObjectPool.get();
logEntry.set(time, "W", tag, msg);
outLog2SDCard.outLog(logEntry);
}
@Override
public void e(String tag, String msg) {
if (closed) {
return;
}
install();
String time = logTimeDateFormat.format(new Date());
LogEntry logEntry = logEntryObjectPool.get();
logEntry.set(time, "E", tag, msg);
outLog2SDCard.outLog(logEntry);
}
private static class OutLog2SDCard {
private Context context;
private Handler handler;
private HandlerThread handlerThread;
private SimpleDateFormat fileNameDateFormat;
private String logFileName;
private FileWriter fileWriter;
private boolean closed;
public OutLog2SDCard(Context context) {
this.context = context.getApplicationContext();
}
private void close() {
closed = true;
if (handlerThread != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
handlerThread.quitSafely();
} else {
handlerThread.quit();
}
handlerThread = null;
}
if (fileWriter != null) {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
fileWriter = null;
}
}
public void outLog(LogEntry entry) {
if (closed) {
return;
}
if (handler == null) {
synchronized (this) {
if (handler == null) {
handlerThread = new HandlerThread("OutLogThread");
handlerThread.start();
handler = new Handler(handlerThread.getLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg.obj instanceof LogEntry) {
writeLog((LogEntry) msg.obj);
return true;
}
return false;
}
});
}
}
}
handler.obtainMessage(0, entry).sendToTarget();
}
private File makeLogFile(String newLogFileName) {
File dir = context.getExternalCacheDir();
if (dir == null) {
return null;
}
return new File(dir, "sketch_log" + File.separator + newLogFileName);
}
private void writeLog(LogEntry entry) {
if (closed) {
return;
}
if (fileNameDateFormat == null) {
fileNameDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
}
Date date = new Date();
String newLogFileName = fileNameDateFormat.format(date) + ".log";
if (!newLogFileName.equals(logFileName) || fileWriter == null) {
if (fileWriter != null) {
SketchUtils.close(fileWriter);
}
File logFile = makeLogFile(newLogFileName);
if (logFile == null) {
new IllegalStateException("Not found sdcard").printStackTrace();
return;
}
if (!logFile.exists()) {
logFile.getParentFile().mkdirs();
try {
logFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
if (!logFile.exists()) {
new IllegalStateException("Create file failed. " + logFile.getPath()).printStackTrace();
return;
}
}
try {
fileWriter = new FileWriter(logFile, true);
} catch (IOException e) {
e.printStackTrace();
return;
}
logFileName = newLogFileName;
}
try {
fileWriter.write(entry.time);
fileWriter.write(" ");
fileWriter.write(entry.level);
fileWriter.write(" ");
fileWriter.write(entry.tag);
fileWriter.write(" ");
fileWriter.write(entry.message);
} catch (IOException e) {
e.printStackTrace();
}
try {
fileWriter.write("\n");
} catch (IOException e) {
e.printStackTrace();
}
if (closed) {
if (fileWriter != null) {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
fileWriter = null;
}
} else {
entry.recycle();
}
}
}
private static class LogEntry {
public String time;
public String level;
public String tag;
public String message;
private ObjectPool<LogEntry> logEntryObjectPool;
public LogEntry(ObjectPool<LogEntry> logEntryObjectPool) {
this.logEntryObjectPool = logEntryObjectPool;
}
public void set(String time, String level, String tag, String message) {
this.time = time;
this.level = level;
this.tag = tag;
this.message = message;
}
public void recycle() {
set(null, null, null, null);
logEntryObjectPool.put(this);
}
}
}