我假设大多数人都知道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?
答案 0 :(得分:157)
我使用TAG,但我将其初始化为:
private static final String TAG = MyActivity.class.getName();
这样,当我重构我的代码时,标记也会相应地改变。
答案 1 :(得分:12)
我通常创建一个App
类,它位于不同的包中并包含有用的静态方法。其中一种方法是getTag()
方法,这样我就可以到处获取TAG。
App
类看起来像这样:
编辑:改进每个暴徒评论(谢谢:))
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
的行号,以便轻松进行调试。
答案 2 :(得分:11)
转到 Android Studio - &gt;偏好 - &gt;实时模板 - &gt; 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。
答案 3 :(得分:7)
我喜欢改善Yaniv的答案 如果您有这种格式的日志(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;
}
截图:
答案 4 :(得分:3)
我创建了一类名为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 Studio的Android监视器中仅列出您的日志。有时您同时运行服务或其他类。如果您必须单独按活动名称搜索,则无法确切地查看何时获得服务响应,然后发生了您的活动中的操作。像CCC这样的前缀会有所帮助,因为它会按时间顺序为您提供日志记录及其发生的活动答案 5 :(得分:2)
当我在方法之间移动代码或重命名方法时,以更新这些字符串为代价,我喜欢执行以下操作。从哲学角度来看,在标签中保留“位置”或“上下文”似乎更好,而不是消息。
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()
。我发现在日志中过滤更难,因为没有更少的东西可以继续。
答案 6 :(得分:2)
默认情况下,AndroidStudio有一个logt
模板(您可以输入logt
并按Tab键将其扩展为代码片段)。我建议使用它来避免从另一个类复制粘贴TAG定义而忘记更改您所指的类。模板默认扩展为
private static final String TAG = "$CLASS_NAME$"
为避免在重构后使用旧的类名,您可以将其更改为
private static final String TAG = $CLASS_NAME$.class.getSimpleName();
请记得检查&#34;编辑变量&#34;按钮并确保CLASS_NAME
变量已定义为使用className()
表达式,并且如果已定义&#34;则跳过#34}。检查。
答案 7 :(得分:1)
您可以使用this.toString()
获取您在其中打印到日志的特定类的唯一标识符。
答案 8 :(得分: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'
答案 9 :(得分:1)
如果您使用的是 Kotlin,Any
上的扩展属性对此很有用:
val Any.TAG: String
get() = this::class.java.simpleName
这使得 TAG
可用于任何类或对象,只需要导入即可。
答案 10 :(得分:0)
对于那些访问此问题的用户:
private val TAG:String = this.javaClass.simpleName;
答案 11 :(得分:0)
他们将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商店中发布应用程序时,我们需要从应用程序中删除所有Log语句,以便用户在logcat中无法像普通用户一样使用任何应用程序数据(例如用户信息,隐藏的应用程序数据,身份验证令牌)文字
查看这篇文章https://medium.com/mindorks/better-logging-in-android-using-timber-72e40cc2293d
答案 12 :(得分:-2)
我通常使用方法名作为标记但是来自Thread
String TAG = Thread.currentThread().getStackTrace()[1].getMethodName();
这可以避免新的异常。
答案 13 :(得分:-9)
private static final String TAG = new RuntimeException().getStackTrace()[0].getClassName();