SD Logger
ログを取って後でじっくり分析したいとき、logcat では溢れてしまったり、
抜き出しが面倒だったりします。そこで、sd カードに出すツールを作ってみました。
特徴
- ログは一定サイズまで溜めてから書き出します。
- シングルトンで、好きな場所からその context の logger のインスタンスを取得できます
SDLogger のソース
package com.funini.sdlogger;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;
/**
* Simple logger for Android
* Export app logs to sdcard
*
* Usage:
* sdLogger = SDLogger.getInstance();
* sdLogger.writeln("TAG", "message");
*
*/
@SuppressLint("SimpleDateFormat")
public class SDLogger {
public final static String TAG = "SDLogger";
final static String SEPARATOR = ",";
static SDLogger mLogger = null;
final File mLogDir, mLogFile;
StringBuffer mBuffer = new StringBuffer();
final static int BUFFER_THRES = 4096;
Context mContext;
static DateFormat mStringDateFormat = new SimpleDateFormat("yyyy-MM-dd_hhmm");
private SDLogger(Context context) {
mContext = context;
mLogDir = Environment.getExternalStoragePublicDirectory("PonLog");
String dateExpr = mStringDateFormat.format(new Date());
mLogFile = new File(Environment.getExternalStoragePublicDirectory("PonLog"), dateExpr + ".csv");
showMsg("Starting logging to " + mLogFile.toString());
Log.w("SDLogger", "Starting logging to " + mLogFile);
}
public void flush() {
Log.w("SDLogger", "Stopping logging");
dump();
}
void showMsg(String msg) {
Log.i(TAG, msg);
Toast.makeText(mContext, msg, Toast.LENGTH_LONG).show();
}
public static SDLogger getLoger(Context context) {
if(mLogger == null) {
mLogger = new SDLogger(context);
}
return mLogger;
}
void appendTime() {
Date now = new Date();
String dateExpr = mStringDateFormat.format(now);
mBuffer.append(dateExpr);
mBuffer.append(SEPARATOR);
mBuffer.append(now.getTime());
mBuffer.append(SEPARATOR);
}
/**
* Write log with tag
* @param tag Log tag
* @param log Log message
*/
public void writeln(final String tag, final String log) {
writeln(tag + SEPARATOR + log);
}
public void writeln(final String log) {
appendTime();
mBuffer.append(log);
mBuffer.append("\n");
if(mBuffer.length() > BUFFER_THRES) {
dump();
}
}
public void dump() {
if(!mLogDir.exists()) {
showMsg(mLogDir + " does not exists");
if(!mLogDir.mkdirs()) {
showMsg("Failed to mkdir(" + mLogDir + "). Check if WRITE_EXTERNAL_STORAGE permission is set.");
return;
}
}
boolean appendMode = mLogFile.exists();
try {
FileWriter writer = new FileWriter(mLogFile, appendMode);
writer.write(mBuffer.toString());
writer.close();
mBuffer.setLength(0);
showMsg("Logs are successfully written to " + mLogFile);
} catch (FileNotFoundException e) {
showMsg("Log file " + mLogFile.toString() + " not found ");
return;
} catch (IOException e) {
showMsg("Failed to write log to " + mLogFile + "\n" + e.toString());
}
}
}
使うサンプル
タッチされた点が 10 個まで画面に表示されます。
タッチされた点の座標をログします。
SDLoggerSample.tgz
package com.funini.sdlogger;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
public class MainActivity extends Activity {
SDLogger mSDLogger;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
mSDLogger = SDLogger.getLoger(this);
}
@Override
protected void onPause() {
super.onPause();
mSDLogger.flush();
}
class MyView extends View {
final static int DIAM = 40;
final static int N_POINTS = 10;
Paint mPaint = new Paint();
List mPoints = new ArrayList();
int[] mColors = new int[N_POINTS];
public MyView(Context context){
super(context);
for(int i = 0; i < N_POINTS; i++) {
int r = (int)(127.0 * i / N_POINTS + 128);
int g = (int)(63.0 * i / N_POINTS + 192);
mColors[i] = Color.rgb(r, g, 255);
}
}
void addPoint(int x, int y){
mPoints.add(0, new Point(x, y));
if(mPoints.size() > N_POINTS){
mPoints.remove(mPoints.size() - 1);
}
mSDLogger.writeln(x + "," + y);
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for(int i = mPoints.size() - 1; i >= 0; i--) {
Point p = mPoints.get(i);
mPaint.setColor(mColors[i]);
canvas.drawCircle(p.x, p.y, DIAM, mPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
addPoint(x, y);
return super.onTouchEvent(event);
}
}
}