この記事はJava言語をつかったAndroidアプリ開発に関する記事です。
デバッグをちょっと楽にする小ネタとしてログ出力に関する提案です。
おまけもあるので見てください。(おまけが本番です)
こんなものつくってみました。
public class LogUtil {
private static final int MAX_TAG_SIZE = 23;
// Objのクラス名をMAX_TAG_SIZEの文字数以内で出力してくれる。
public static String TAG(Object obj) {
String objName = obj.getClass().getSimpleName();
return objName.length() > MAX_TAG_SIZE ? objName.substring(0, MAX_TAG_SIZE) : objName;
}
}
TAG()
LogUtilのようなクラスに定義しておいて、import static
で使うといい感じに使えます。
AndroidStudio(IntellijIDE)の機能でimport文補完を使います。TAG()と打ち込んだ時点でstatic import
しちゃう?って提案してくれるので便利です。
つまり
LogUtilのTAG()の定義+AndroidStudioのコード入力サポート機能(自動import)
を使えばfinal static String TAG = MyClass.class.getSimpleName();
をクラス毎に定義しなくてよくなります。
これでLogデバッグするときのジミーで冗長的な作業がほとんどなくなって、集中力が保てていい感じです。
使い方
public class MainActivity extends ExtensionActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// TAGの引数は出したいクラス名のインスタンスを入れる。この場合はMainActivity
Log.d(TAG(this), " onCreate()");
}
}
注意:定数とは違い動的に価を決定するので、定数を使った時よりもごく微小ですが遅くなります。パフォーマンスを気にされるデバッグでは使わないほうがいいかもしれません。(そもそもstatic finalにしているのはパフォーマンスを阻害しないの理由なので、両者の違いを考えた上でつかってください)
おまけ
-
CLASS_LINE() :
[クラス.メソッド名(行番号)]
-
METHOD_INFO() :
[パッケージ名.クラス名.メソッド名(ファイル名:行数)]
AndroidStudioのLogCat上からファイルの対象行にマウスクリックで飛べる -
CALLED_BY() : CALLED_BYが呼ばれているメソッドを呼び出した
[クラス名.メソッド名(行数)]
が出力される
を紹介します。
これらはLogで実行クラスファイルの行番号やどこから呼ばれているかを出力したいときに使えます。
Stringで返すのでそのままログ出力にいれていただければ結構です。
メソッド名が大文字のスネークケースなのは、利用頻度と見やすさを重視したためです。
public static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID;
// [クラス.メソッド名(行番号)]
public static String CLASS_LINE() {
try {
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
for (StackTraceElement ste: elements) {
String cls = ste.getClassName();
if (cls.startsWith(PACKAGE_NAME)) {
cls = cls.replace(PACKAGE_NAME, "");
return cls + "." + ste.getMethodName() + "(" + ste.getLineNumber() + ")";
}
}
} catch (Exception e) {
return "null";
}
return "null";
}
// [パッケージ名.クラス名.メソッド名(ファイル名:行数)] AndroidStudioのLogCat上からファイルの対象行に飛べる
public static String METHOD_INFO() {
try {
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
for (StackTraceElement ste: elements) {
// 最後の改行がないとリンクされない
if (ste.getClassName().startsWith(PACKAGE_NAME)) return ste.toString() + "\n";
}
} catch (Exception e) {
return "null";
}
return "null";
}
// CALLED_BYが呼ばれているメソッドを呼び出した[クラス名.メソッド名(行数)]が出力される
public static String CALLED_BY() {
try {
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
boolean breakFlg = false;
for (StackTraceElement ste: elements) {
String cls = ste.getClassName();
if (breakFlg) {
cls = cls.replace(PACKAGE_NAME, "");
return cls + "." + ste.getMethodName() + "(" + ste.getLineNumber() + ")";
}
if (cls.startsWith(PACKAGE_NAME)) breakFlg = true;
}
} catch (Exception e) {
return "null";
}
return "null";
}
Logデバッグではこれを使ってみて!
お勧めの使い方は
個人的には**METHOD_INFO()**をつかったデバッグがお勧めです。ログでデバッグが必要なときで、どこで問題が起きているか突き止めにくい時に、関係ありそうなところの各処理ごとにLog.d(TAG(this), METHOD_INFO());
をコピペで配置しておけば。
アプリの落ちる前の最後のMETHOD_INFO()を使ったログを使って、AndroidStudioのLogCatから瞬時にマウスクリックで移動してソースを確認するのに役に立ちます。
注意を読んでいただいた上でコレをつかって、ログによるデバッグをもっと楽にしてみたらいかがでしょうか?
ここまで読んでくださった方ありがとうございました。
なおこのコードはGitHub上に公開してあります。