Ответ 1
Я использую TAG, но я инициализирую его следующим образом:
private static final String TAG = MyActivity.class.getName();
Таким образом, когда я реорганизую свой код, тег также будет соответствующим образом изменяться.
Я предполагаю, что большинство из вас знают о android.util.Log Все методы ведения журнала принимают "String tag" в качестве первого аргумента.
И мой вопрос Как вы обычно отмечаете свои журналы в своих приложениях? Я видел такой жесткий код:
public class MyActivity extends Activity {
private static final String TAG = "MyActivity";
//...
public void method () {
//...
Log.d(TAG, "Some logging");
}
}
Это не выглядит красивым из-за многих причин:
Есть ли какой-нибудь опрятный способ получить TAG для класса?
Я использую TAG, но я инициализирую его следующим образом:
private static final String TAG = MyActivity.class.getName();
Таким образом, когда я реорганизую свой код, тег также будет соответствующим образом изменяться.
Обычно я создаю класс App
, который находится в другом пакете и содержит полезные статические методы. Одним из методов является метод 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
, для легкой отладки.
Перейдите в Android Studio → предпочтение → Живые шаблоны → AndroidLog, затем выберите Log.d(TAG, String).
В текст шаблона замените
android.util.Log.d(TAG, "$METHOD_NAME$: $content$");
с
android.util.Log.d("$className$", "$METHOD_NAME$: $content$");
Затем нажмите Изменить переменные и введите className() в столбце Выражение рядом с столбцом className Имя.
Теперь, когда вы набираете ярлык logd
, он помещает
Log.d("CurrentClassName", "currentMethodName: ");
Вам больше не нужно определять TAG.
Мне нравится улучшать ответ Янива если у вас есть журнал в этом формате (filename.java:XX) номер строки xx, вы можете связать ярлык так же, как и связанный, когда есть ошибка, таким образом, я могу сразу перейти к рассматриваемой строке, просто нажав на 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;
}
Скриншот:
Я создал класс статических переменных, методов и классов с именем 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()
также добавляет имя пакета, поэтому я удаляю его, чтобы избежать ненужного тега.
<сильные > Преимущества:
Log.d(TAG,
toString
Log.d
когда-либо, так как мне просто нужно удалить этот метод, а расположение всех журналов станет красным.CCC
(короткая, простая в использовании строка), поэтому легко перечислять только ваши журналы на Android-мониторе в Android Studio. Иногда вы запускаете службы или другие классы одновременно. Если вам нужно искать только по имени активности, то вы не можете точно видеть, когда был получен ответ службы, а затем произошло действие из вашей активности. Префикс, такой как CCC, помогает, поскольку он дает вам журналы в хронологическом порядке с активностью, в которой он произошел.За счет обновления этих строк при перемещении кода между методами или переименовании мне нравится делать следующее. Философски также кажется, что лучше сохранить "местоположение" или "контекст" в теге, а не в сообщении.
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()
. Я нашел их сложнее фильтровать в журналах, потому что было меньше, чтобы продолжить.
AndroidStudio имеет шаблон logt
по умолчанию (вы можете набрать logt
и нажать вкладку, чтобы он был разворачиван до сильного кода). Я рекомендую использовать это, чтобы избежать копирования, вставляющего определение TAG из другого класса и забывая изменить класс, о котором вы говорите. Шаблон по умолчанию расширяется до
private static final String TAG = "$CLASS_NAME$"
Чтобы избежать использования старого имени класса после рефакторинга, вы можете изменить его на
private static final String TAG = $CLASS_NAME$.class.getSimpleName();
Не забудьте проверить кнопку "Изменить переменные" и убедитесь, что переменная CLASS_NAME
определена для использования выражения className()
и имеет флажок "Пропустить, если определено".
Вы можете использовать this.toString()
, чтобы получить уникальный идентификатор для определенного класса, в котором вы печатаете в журнале.
Это очень старый вопрос, но даже в обновленном ответе за июль 2018 года предпочтительнее использовать Timber. Для регистрации правильного ведения журнала ошибки и предупреждения можно отправлять сторонним библиотекам сбоев, таким как Firebase или Crashlytics.
В классе, который реализует приложение, вы должны добавить это:
@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);
}
}
}
}
Не забывайте зависимость от древесины.
implementation 'com.jakewharton.timber:timber:4.7.1'
Для тех пользователей, которые посещают этот вопрос:
private val TAG:String = this.javaClass.simpleName;
они используют Timber для приложения IOsched 2019 для отображения отладочной информации:
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 Store, нам нужно удалить все операторы Log из приложения, чтобы никакие данные приложения, такие как информация о пользователе, скрытые данные приложения, токены авторизации, не были доступны пользователю в logcat в виде простого текста
проверить эту статью https://medium.com/mindorks/better-logging-in-android-using-timber-72e40cc2293d
Я обычно использую имя метода как тег, но из Thread
String TAG = Thread.currentThread().getStackTrace()[1].getMethodName();
Это исключает новое исключение.
private static final String TAG = new RuntimeException().getStackTrace()[0].getClassName();