通常、どのようにログエントリにタグを付けますか?(アンドロイド)


96

ほとんどの人がandroid.util.Logを知っていると思います。すべてのロギングメソッドは、最初の引数として「文字列タグ」を受け入れます。

そして、私の質問は、通常、アプリケーションでログにどのようにタグを付けるのですか? 次のようなハードコードを見たことがあります。

public class MyActivity extends Activity {
    private static final String TAG = "MyActivity";
    //...
    public void method () {
        //...
        Log.d(TAG, "Some logging");
    }
}

これは多くの理由により見栄えがよくありません:

  • このコードにはハードコードがありませんが、あります。
  • 私のアプリケーションでは、同じ名前の異なるパッケージに任意の数のクラスを含めることができます。したがって、ログを読み取るのは難しいでしょう。
  • 柔軟ではありません。あなたは常にプライベートフィールドTAGをクラスに入れました。

クラスのタグを取得するためのきちんとした方法はありますか?


2
TAGの使用はAndroid javadocで推奨されているため、実行時にクラス名を取得するよりも悪いとは思わない
Vladimir

GeneralConstantsのような特定のクラスを作成し、それにTAGを配置することを好むので、そのような任意のクラスにタグを到達できます。GeneralConstans.MY_TAG
cagryInside

6
クラスでTAGを定義するのが最善だと思います。クラス名をハードコーディングすることは醜いですが、proguardと連携する唯一の信頼できる方法です。proguardを使用しない場合は、MyActivity.class.getName()が最適なソリューションです。重複した名前が心配な場合は、パッケージ名を含めてください。別の場所にタグ名があると、メンテナンスの悪夢になります。
Ralph Mueller

回答:


179

タグを使用していますが、次のように初期化しています。

private static final String TAG = MyActivity.class.getName();

この方法でコードをリファクタリングすると、それに応じてタグも変更されます。


21
同じ方法でTAG定数を定義しています。ただし、コード難読化ツールがクラス名に影響し、結果としてこの定数の値にどのように影響するのでしょうか。
Gumbit

1
今回はすべて手動で貼り付けました"MyActivity.class.getName();"。「TAG」はGoogleなどの例の単なるプレースホルダーだと思っていましたが、実際のStatic変数ではありませんでした。これは、はるかに優れたソリューションです:)
ワイヤード00

4
staticを削除し、this.getClass().getName()代わりに使用してより汎用的なものにしないでください。
theblang 2014年

11
TAGの長さの制限を回避するには、this.getClass()。getSimpleName()を試してください。IllegalArgumentExceptionがスローされる場合tag.length()> 23.
マイケル・レヴィ

14
Ralph Muellerによって言及されたように、クラス名を難読化するために(ほとんどのAndroidプロジェクトと同様に)Proguardを使用する場合、この手法は機能しません。
John Patterson、

16

私は通常App、別のパッケージに配置され、有用な静的メソッドを含むクラスを作成します。メソッドの1つはメソッドですgetTag()。この方法で、どこにでもTAGを取得できます。
Appクラスは次のようになります。

編集:br mobコメントごとに改善(ありがとう:))

public class App {

    public static String getTag() {
        String tag = "";
        final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
        for (int i = 0; i < ste.length; i++) {
            if (ste[i].getMethodName().equals("getTag")) {
                tag = "("+ste[i + 1].getFileName() + ":" + ste[i + 1].getLineNumber()+")";
            }
        }
        return tag;
    }

}

そして私がそれを使いたいとき:

Log.i(App.getTag(), "Your message here");

getTagメソッドの出力は、getTagデバッグを容易にするために、(パッケージ名を含む)呼び出し元クラスの名前と、呼び出し元の行番号です。


6
私は絶対にこれをしません。そうすると、ログステートメントがパフォーマンスに大きな影響を与えます。これを行う場合は、プロダクションビルドに関する警告以外のメッセージについては、確実にログメッセージを削除する必要があります。
Matt Wolfe

1
マット、あなたは絶対的に正しいです!本番環境で
勧めします

2
タグの長さが23文字に制限されているため、これはおそらくお勧めできません
Claudio Redi

仕組みを教えてくれてありがとうgetStackTrace()。しかし、私はそれが高価であるため、使用し
ません

12

移動アンドロイドスタジオ- >好み- >ライブテンプレート- > AndroidLogは、その後、選択しLog.d(TAG、String)を

ではテンプレートのテキストを置き換えます

android.util.Log.d(TAG, "$METHOD_NAME$: $content$");

android.util.Log.d("$className$", "$METHOD_NAME$: $content$");

Androidメニューの画像

次に、[ 変数の編集 ]をクリックし、[ className Name]列の横の[ Expression ]列にclassName()と入力します。Androidメニュー2の画像

ショートカットを入力logdすると、

Log.d("CurrentClassName", "currentMethodName: ");

タグを定義する必要はもうありません。


1
これはAndroid Studioの本当にすばらしい使用法であり、問​​題への興味深いアプローチですが、同時に実際にTAG変数の代わりに文字列を入力しているため、変更する必要がある場合は少し面倒かもしれません。ただし、機能を表示するための+1、ありがとうございます!
Voy

3
私はこの方法が好きですが、既存のログエントリを変更するのではなく、新しいログエントリを作成します。将来の更新などで変更された場合に備えて、安全を確保するためです。
Alaa 2017

9

この形式のログ(filename.java:XX)xx行番号がある場合、Yanivの回答を改善したいと思います。エラーが発生した場合と同じようにショートカットをリンクできます。このようにして、問題の行に直接アクセスできます。 logcatをクリックするだけで

これを拡張アプリケーション内に配置して、他のすべてのファイルで使用できるようにします

public static String getTag() {
    String tag = "";
    final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
    for (int i = 0; i < ste.length; i++) {
        if (ste[i].getMethodName().equals("getTag")) {
            tag = "("+ste[i + 1].getFileName() + ":" + ste[i + 1].getLineNumber()+")";
        }
    }
    return tag;
}

スクリーンショット:


それを愛し、それを「盗み」、私の答えを更新する:)
Yaniv 2015年

4
タグの長さが23文字に制限されたため、これはおそらくお勧めしません
Claudio Redi

3

AndroidStudioにはlogtデフォルトでテンプレートがあります(タイプlogtしてTabキーを押すと、コードのコードに展開できます)。これを使用して、別のクラスからTAG定義をコピーして貼り付けたり、参照しているクラスを変更し忘れたりしないようにすることをお勧めします。テンプレートはデフォルトで次のように展開されます

private static final String TAG = "$CLASS_NAME$"

リファクタリング後に古いクラス名を使用しないようにするには、次のように変更します

private static final String TAG = $CLASS_NAME$.class.getSimpleName();

「変数の編集」ボタンをチェックし、CLASS_NAME変数がclassName()式を使用するように定義され、「定義されている場合はスキップする」がチェックされていることを忘れないでください。


2

という名前の静的変数、メソッド、クラスのクラスを作成しましたS

ロギング方法は次のとおりです。

public static void L(Context ctx, Object s) {
    Log.d("CCC " + ctx.getClass().getName().replace(ctx.getPackageName(), ""), s.toString());
}

次のように任意のクラスで呼び出されるも、不必要に長いタグを避けるために、したがって、パッケージ名を追加し、私はそれを削除しています。S.L(this, whaterver_object);getClass().getName()

利点:

  1. より短い Log.d(TAG,
  2. int値を文字列に変換する必要はありません。入力する必要はありませんtoString
  3. Log.dメソッドを削除するだけですべてのログの場所が赤くマークされるので、削除することを忘れないでください。
  4. クラスの名前を使用するため、アクティビティの上部でTAGを定義する必要はありません。
  5. TAGの接頭辞はCCC(短く、入力が簡単な文字列)なので、Android StudioのAndroidモニターにログのみを簡単にリストできます。ときどき、サービスや他のクラスを同時に実行しています。アクティビティ名だけで検索する必要がある場合は、サービス応答がいつ取得されたのかを正確に把握できず、アクティビティからのアクションが発生しています。CCCのような接頭辞は、それが発生したアクティビティを時系列でログに記録するので役立ちます

1
素晴らしい解決策!私はそれを使用します!しかし、私は置き換えContext ctxによってObject ctxおよびctx.getClass().getName().replace(ctx.getPackageName(), "")によってctx.getClass().getSimpleName()。そうすればS.L(Object, Object)、どこでも呼び出すことができます(instantceの場合、をFragment拡張しないsを含むContext)。
アントニオヴィニシウスメネゼスメデイ

1

を使用this.toString()して、ログに出力する特定のクラスの一意の識別子を取得できます。


これは何をするかによっては高価になる可能性がtoString()あります。
タール、2014年

1

メソッド間でコードを移動したり、メソッドの名前を変更したりするときに、これらの文字列を更新する代わりに、次のようにします。哲学的には、タグではなく、メッセージではなく「場所」または「コンテキスト」を保持する方が良いようです。

public class MyClass {

    // note this is ALWAYS private...subclasses should define their own
    private static final LOG_TAG = MyClass.class.getName();

    public void f() {
        Log.i(LOG_TAG + ".f", "Merry Christmas!");
    }

}

ここでの利点は、コンテンツが静的でない場合でも、単一のメソッドを除外できることです。たとえば、

Log.i(LOG_TAG + ".f", String.valueOf(new Random().nextInt()));

唯一の欠点は、名前を変更f()するときにg()、その文字列を覚えておく必要があることです。また、自動IDEリファクタリングはこれらをキャッチしません。

しばらくの間、私は短いクラス名を使うのが好きでしたLOG_TAG = MyClass.class.getSimpleName()。続行する項目が少なかったため、ログでのフィルタリングが困難であることがわかりました。


1

それは非常に古い質問ですが、2018年7月の更新された回答を考えても、Timberを使用する方が望ましいです。正しいログを記録するために、FirebaseやCrashlyticsなどのサードパーティのクラッシュライブラリにエラーと警告を送信できます。

Applicationを実装するクラスでは、これを追加する必要があります。

@Override
public void onCreate() {
    super.onCreate();
    if (BuildConfig.DEBUG) {
        Timber.plant(new Timber.DebugTree());
    } else {
        Timber.plant(new CrashReportingTree());
    }
}

/** A tree which logs important information for crash reporting. */
private static class CrashReportingTree extends Timber.Tree {
    @Override protected void log(int priority, String tag, String message, Throwable t) {
        if (priority == Log.VERBOSE || priority == Log.DEBUG) {
            return;
        }

        FakeCrashLibrary.log(priority, tag, message);

        if (t != null) {
            if (priority == Log.ERROR) {
                FakeCrashLibrary.logError(t);
            } else if (priority == Log.WARN) {
                FakeCrashLibrary.logWarning(t);
            }
        }
    }
}

Timber依存関係を忘れないでください。

implementation 'com.jakewharton.timber:timber:4.7.1'


0

IOschedアプリ2019にTimberを使用してデバッグ情報を表示します。

implementation 'com.jakewharton.timber:timber:4.7.1'

class ApplicationController: Application() {

override fun onCreate() {  
    super.onCreate()
    if(BuildConfig.DEBUG){
        Timber.plant(Timber.DebugTree())
    }
}   
// enables logs for every activity and service of the application
// needs to be registered in manifest like:  
 <application
    android:label="@string/app_name"
    android:name=".ApplicationController"
    ... >

使用法

  Timber.e("Error Message") 
  // will print ->  D/MainActivity: Error Message

  Timber.d("Debug Message");
  Timber.tag("new tag").e("error message");

これにより、DEBUG状態の間のみログを使用できるようになり、Google Playでの起動時にログを手動で削除するタスクが容易になります-

Playストアでアプリをリリースするときは、アプリからすべてのLogステートメントを削除する必要があります。これにより、ユーザー情報、非表示のアプリケーションデータ、auth-tokensなどのアプリケーションデータが、プレーンテキストとしてlogcatでユーザーに利用できなくなります。

この記事をチェックしてくださいhttps://medium.com/mindorks/better-logging-in-android-using-timber-72e40cc2293d


-2

私は通常タグとしてメソッド名を使用しますが、スレッドから

String TAG = Thread.currentThread().getStackTrace()[1].getMethodName();

これにより、新しい例外が回避されます。


-9
private static final String TAG = new RuntimeException().getStackTrace()[0].getClassName();

3
RuntimeException現在のクラス名を取得するためだけに新規を作成するのはなぜですか?ひどい。
asgs 2013

これは、ログエントリにタグを付ける方法です。これは、クラスをプロジェクトから別のクラスにコピーするときに適切にリファクタリングできる唯一のソリューションです。あなたがより良い、より快適なアイデアを持っているなら、私は提案を受け入れます。
2013

1
名前を変更せずにJavaクラスファイルをある場所から別の場所にコピーするだけの場合、@ gianpiが提供するソリューションが必要です。それ以外の場合はthis.getClass().getName()、静的スコープを削除する必要がありますが、実行できますTAG
asgs
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.