SDカードにログを出力する方法

GPSを使用するアプリケーションを開発して、外に出て実機でテストすると、どうしてもその場でログが確認できない状況が発生します。
そんな時にはSDカードにログを出力するようにしておくと便利です。
以下はSDカードにログを出力する例です。

package jp.bs.util;

import java.io.File;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.Date;

import android.os.Environment;
import android.util.Log;

public class SdLog {
	private final static String LOGDIR = Environment.getExternalStorageDirectory().getPath() + "/hoge/";
	private final static String SDFILE = LOGDIR+"log.txt";
	private static boolean enable = true;
	static public void put(String text) {
		if (!enable) return;
		Date now = new Date();
		BufferedWriter bw = null;
		StackTraceElement[] ste = (new Throwable()).getStackTrace();
		text = ste[1].getMethodName()
			   + "("
			 	+ ste[1].getFileName() + ":" + ste[1].getLineNumber()
			   + ") " + text;
		try {
			try {
				mkdir_p(LOGDIR);
			} catch (IOException e) {
				e.printStackTrace();
				return;
			}
			FileOutputStream file = new FileOutputStream(SDFILE, true);
			bw = new BufferedWriter(new OutputStreamWriter(
					file, "UTF-8"));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		try {
			bw.append((now.getYear()+1900)+"/"+(now.getMonth()+1)+"/"+now.getDate()
					+" "+now.getHours()+":"+now.getMinutes()+":"+now.getSeconds()+"\t"+text+"\n");
			Log.e("log",(now.getYear()+1900)+"/"+(now.getMonth()+1)+"/"+now.getDate()
					+" "+now.getHours()+":"+now.getMinutes()+":"+now.getSeconds()+"\t"+text);
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			bw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		bw = null;
	}

	public static boolean mkdir_p(File dir) throws IOException {
		if (!dir.exists()) {
			if (!dir.mkdirs()) {
				throw new IOException("File.mkdirs() failed.");
			}
			return true;
		} else if (!dir.isDirectory()) {
			throw new IOException("Cannot create path. " + dir.toString() + " already exists and is not a directory.");
		} else {
			return false;
		}
	}

	public static boolean mkdir_p(String dir) throws IOException {
		return mkdir_p(new File(dir));
	}
}

Throwableからスタックトレースを取得してファイル名とメソッド名、行番号を取ってきているのがポイントです。

SdLog.put("hogehoge");

として使うとLogCatの画面に

10-01 22:59:32.149: ERROR/log(9532): 2009/10/1 22:59:31    onCreate(HogeActivity.java:113) hogehoge

のように出力されるのと同時にLOGDIRに設定しているディレクトリにファイル出力されます。
#この場合は「/sdcard/hoge/log.txt」

全てのログ出力をこの方法にしておけば、SdLogのenableをfalseにしておけばログ出力を一括で止める事も出来ます。

SDカード内のファイルを閲覧できるアプリを入れて置くと、Androidの実機本体だけでログを確認することができ、非常に便利です。

是非ご活用ください。

なお、SDK1.6よりSDカード書き込みのパーミッションが必要になりましたが、1.6にアップデートしたGDDPhoneではパーミッションの記述をしなくても書き込みできるようです。
今後変更されたり、HT-03Aや他の機種では挙動が異なるかもしれませんので、1.6以降を使う場合は以下のパーミッションマニフェストファイルに記述しておいた方がよいでしょう。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>