2010年08月17日
AndroidのJavaアプリからスタックトレースをログに出す簡単な方法
AndroidのJavaアプリからログを出すには android.util.Logクラスを使います。
実はスタックトレースを出すためのメソッドもあるのですが、あまり知られていないようなのでここで紹介します。
Logクラスのstatic methodのLog.e, Log.w, Log.i, Log.d, Log.vは2つの引数(String tag, String msg)の他に3つの引数(String tag, String msg, Throwable tr)のものがあります。引数3個のほうはtrのスタックトレースを一緒にログに出してくれます。
私は別件のためにソースを見ていて見つけました。android.util.Logクラスのソースは $ANDROID_TOP/frameworks/base/core/java/android/util/Log.java です。
AndroidのAPIリファレンスにも載っています。
static int i(String tag, String msg, Throwable tr) Send a INFO log message and log the exception.
使用例
Log.i(LOG_TAG, "message", new Throwable());
catch節の中ならcatchしたThrowableオブジェクトを使えばいいし、それ以外の場合ではその場でThrowableを生成して渡せばよいだけです。
logcatの結果
I/Hello ( 829): on Start I/Hello ( 829): java.lang.Throwable I/Hello ( 829): at com.example.helloandroid.HelloAndroid.onStart(HelloAndroid.java:22) I/Hello ( 829): at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1129) I/Hello ( 829): at android.app.Activity.performStart(Activity.java:3781) I/Hello ( 829): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2636) I/Hello ( 829): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679) I/Hello ( 829): at android.app.ActivityThread.access$2300(ActivityThread.java:125) I/Hello ( 829): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033) I/Hello ( 829): at android.os.Handler.dispatchMessage(Handler.java:99) I/Hello ( 829): at android.os.Looper.loop(Looper.java:123) I/Hello ( 829): at android.app.ActivityThread.main(ActivityThread.java:4627) I/Hello ( 829): at java.lang.reflect.Method.invokeNative(Native Method) I/Hello ( 829): at java.lang.reflect.Method.invoke(Method.java:521) I/Hello ( 829): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) I/Hello ( 829): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) I/Hello ( 829): at dalvik.system.NativeStart.main(Native Method)
ログを出したメソッドがどこから呼ばれているか一目瞭然なので便利ですね。
サンプルアプリの全ソース
package com.example.helloandroid; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.widget.TextView; public class HelloAndroid extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); tv.setText("Hello, Android"); setContentView(tv); } static final String LOG_TAG = "Hello"; @Override public void onStart() { super.onStart(); Log.i(LOG_TAG, "on Start", new Throwable()); } }
2010.8.17追記
AndroidのJavaではSystem.outが/dev/nullにつながっているため、System.out.printlnではログが出ません。
以下のe.printStackTrace()も同様です。
try{ ... } catch (Exception e) { e.printStackTrace(); }
この場合、このように書きます。
try{ ... } catch (Exception e) { Log.e(LOG_TAG, "message", e); }
2010.8.17追記2
実際にやってみたらSystem.outもSystem.errもlogcatで見られるようになっていました。訂正します。
e.printStackTrace() のままで大丈夫でした。