Zakładam, że większość z Was wie o android.util.Log Wszystkie metody logowania akceptują „String tag” jako pierwszy argument.
Moje pytanie brzmi: Jak zwykle tagujesz swoje dzienniki w swoich aplikacjach? Widziałem taki kod:
public class MyActivity extends Activity {
private static final String TAG = "MyActivity";
//...
public void method () {
//...
Log.d(TAG, "Some logging");
}
}
To nie wygląda ładnie z wielu powodów:
- Możesz mi powiedzieć, że ten kod nie ma twardego kodu, ale ma.
- Moja aplikacja może mieć dowolną liczbę klas w różnych pakietach o tej samej nazwie. Trudno byłoby więc przeczytać dziennik.
- To nie jest elastyczne. W swojej klasie zawsze umieszczałeś TAG pola prywatnego.
Czy jest jakiś fajny sposób na uzyskanie TAG-a na zajęcia?
Odpowiedzi:
Używam TAG-a, ale inicjalizuję go w ten sposób:
private static final String TAG = MyActivity.class.getName();
W ten sposób, gdy refaktoryzuję swój kod, tag również się odpowiednio zmieni.
źródło
"MyActivity.class.getName();"
. Zawsze myślałem, że „TAG” to tylko symbol zastępczy w przykładach z Google itp ... a nie rzeczywistaStatic
zmienna! To znacznie lepsze rozwiązanie dzięki :)this.getClass().getName()
zamiast tego, aby był bardziej ogólny?Zwykle tworzę
App
klasę, która znajduje się w innym pakiecie i zawiera przydatne metody statyczne. Jedną z metod jestgetTag()
metoda, w ten sposób mogę uzyskać TAG wszędzie.App
klasa wygląda następująco:EDYCJA : Ulepszone za komentarz br mob (dzięki :))
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; } }
A kiedy chcę go użyć:
Log.i(App.getTag(), "Your message here");
Wyjście
getTag
metody jest nazwa klasy rozmówcy (z nazwą pakietu), a numer linii, gdziegetTag
nazywany jest od, do łatwego debuging.źródło
getStackTrace()
działa. Ale niePrzejdź do Android Studio -> preferencje -> Live Templates -> AndroidLog, a następnie wybierz Log.d (TAG, String) .
W szablonie zastąp tekst
android.util.Log.d(TAG, "$METHOD_NAME$: $content$");
z
android.util.Log.d("$className$", "$METHOD_NAME$: $content$");
Następnie kliknij Edytuj zmienne i wpisz className () w kolumnie Wyrażenie obok kolumny Nazwa klasy .
Teraz, kiedy wpiszesz skrót
logd
, zostanie on umieszczonyLog.d("CurrentClassName", "currentMethodName: ");
Nie musisz już definiować TAG-a.
źródło
Lubię poprawić odpowiedź Yaniv, jeśli masz dziennik w tym formacie (nazwa_pliku.java:XX). Xx numer linii możesz połączyć skrót w ten sam sposób, gdy pojawia się błąd, w ten sposób mogę uzyskać bezpośredni dostęp do danej linii wystarczy kliknąć logcat
Umieściłem to w mojej rozszerzonej aplikacji, aby móc używać go w każdym innym pliku
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; }
Zrzut ekranu:
źródło
AndroidStudio ma
logt
domyślnie szablon (możesz wpisaćlogt
i nacisnąć klawisz Tab, aby rozwinąć go do pojedynczego fragmentu kodu). Zalecam użycie tego, aby uniknąć kopiowania wklejania definicji TAG z innej klasy i zapomnienia o zmianie klasy, do której się odnosisz. Szablon domyślnie rozwija się doprivate static final String TAG = "$CLASS_NAME$"
Aby uniknąć używania starej nazwy klasy po refaktoryzacji, możesz ją zmienić na
private static final String TAG = $CLASS_NAME$.class.getSimpleName();
Pamiętaj, aby zaznaczyć przycisk „Edytuj zmienne” i upewnić się, że
CLASS_NAME
zmienna jest zdefiniowana do używaniaclassName()
wyrażenia i ma zaznaczone pole „Pomiń, jeśli zdefiniowano”.źródło
Stworzyłem klasę zmiennych statycznych, metod i klas o nazwie as
S
.Poniżej przedstawiono metodę logowania:
public static void L(Context ctx, Object s) { Log.d("CCC " + ctx.getClass().getName().replace(ctx.getPackageName(), ""), s.toString()); }
Jest wywoływany w dowolnej klasie, ponieważ
S.L(this, whaterver_object);
ThegetClass().getName()
dołącza również nazwę pakietu, dlatego usuwam go, aby uniknąć niepotrzebnego wydłużania tagu.Zalety:
Log.d(TAG,
toString
Log.d
Nigdy , ponieważ muszę tylko usunąć metodę, a lokalizacje wszystkich dzienników zostaną zaznaczone na czerwono.CCC
(krótki, łatwy do wpisania ciąg), dzięki czemu łatwo jest wyświetlić listę tylko dzienników na monitorze Android w Android Studio. Czasami jednocześnie prowadzisz usługi lub inne zajęcia. Jeśli musisz wyszukiwać według samej nazwy działania, nie możesz dokładnie zobaczyć, kiedy otrzymano odpowiedź usługi, a następnie nastąpiło działanie z Twojego działania. Prefiks taki jak CCC pomaga, ponieważ zapewnia chronologicznie dzienniki czynności, w których miało miejsceźródło
Context ctx
przezObject ctx
ictx.getClass().getName().replace(ctx.getPackageName(), "")
przezctx.getClass().getSimpleName()
. W ten sposób mogę zadzwonićS.L(Object, Object)
wszędzie (w tym do tych,Fragment
które nie rozszerzająContext
, na przykład).Możesz użyć,
this.toString()
aby uzyskać unikalny identyfikator dla określonej klasy, w której drukujesz do dziennika.źródło
toString()
robi.Kosztem aktualizowania tych ciągów, gdy przenoszę kod między metodami lub zmieniam nazwy metod, lubię robić następujące rzeczy. Z filozoficznego punktu widzenia wydaje się również, że lepiej jest umieścić w tagu słowo „lokalizacja” lub „kontekst”, a nie wiadomość.
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!"); } }
Zaletą jest to, że możesz odfiltrować pojedynczą metodę, nawet jeśli treść nie jest statyczna, np
Log.i(LOG_TAG + ".f", String.valueOf(new Random().nextInt()));
Jedyną wadą jest to, że kiedy zmieniam nazwę
f()
nag()
, muszę pamiętać o tym ciągu. Ponadto automatyczna refaktoryzacja IDE ich nie złapie.To znaczy przez jakiś czas byłem fanem używania krótkiej nazwy klasy
LOG_TAG = MyClass.class.getSimpleName()
. Trudniej było je filtrować w dziennikach, ponieważ było mniej do zrobienia.źródło
Jest to bardzo stare pytanie, ale nawet pomyśleć, że zaktualizowana odpowiedź na lipiec 2018 r., Lepiej jest użyć drewna. W celu zarejestrowania prawidłowego logowania błędy i ostrzeżenia mogą być wysyłane do bibliotek awarii innych firm, takich jak Firebase lub Crashlytics.
W klasie implementującej Application należy dodać:
@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); } } } }
Nie zapomnij o zależności od drewna.
implementation 'com.jakewharton.timber:timber:4.7.1'
źródło
Dla użytkowników, którzy odwiedzili to pytanie:
private val TAG:String = this.javaClass.simpleName;
źródło
używają Timber dla aplikacji IOsched 2019, aby wyświetlić informacje o debugowaniu:
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" ... >
stosowanie
Timber.e("Error Message") // will print -> D/MainActivity: Error Message Timber.d("Debug Message"); Timber.tag("new tag").e("error message");
pamiętaj, że dzięki temu dzienniki są dostępne tylko w stanie DEBUG i ułatwia zadanie ich ręcznego usuwania w celu uruchomienia w Google Play -
sprawdź ten artykuł https://medium.com/mindorks/better-logging-in-android-using-timber-72e40cc2293d
źródło
Zwykle używam nazwy metody jako tagu, ale z Thread
String TAG = Thread.currentThread().getStackTrace()[1].getMethodName();
Pozwala to uniknąć nowego wyjątku.
źródło
private static final String TAG = new RuntimeException().getStackTrace()[0].getClassName();
źródło
RuntimeException
tylko po to, aby uzyskać aktualną nazwę klasy? Bardzo źle.this.getClass().getName()
chociaż musiałbyś usunąć statyczny zakresTAG