相反奇怪的Log行为

时间:2013-04-14 16:43:24

标签: android android-logcat

我写了一个非常简单的Android活动:

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Log.d("TAG", "onCreate() Log call 1");
        Log.d("SMS", "onCreate() Log call 2");
        Log.d("TEST", "onCreate() Log call 3");

        finish();
    }

    @Override
    protected void onDestroy() {
        Log.d("TAG", "onDestroy() Log call 1");
        Log.d("SMS", "onDestroy() Log call 2");
        Log.d("TEST", "onDestroy() Log call 3");

        super.onDestroy();
    }
}

我希望这会生成6条日志消息(3条来自onCreate(),3条来自onDestroy())。这是logcat:

04-14 17:31:58.363: D/TAG(18084): onCreate() Log call 1
04-14 17:31:58.363: D/TEST(18084): onCreate() Log call 3
04-14 17:31:59.905: D/TAG(18084): onDestroy() Log call 1
04-14 17:31:59.905: D/TEST(18084): onDestroy() Log call 3

可以看出,带有“SMS”标签的行无法通过。这不是,据我所知,有记录的事情。问题是,为什么?

编辑:答案的更多细节。

Matthew Burke在下面给出了一个相当好的答案。简而言之,根据logd_write.c的源代码,似乎:

    具有以下标记的
  • Log个请求会自动重定向到radio日志:
    • HTC_RIL
    • RIL
    • 开头的代码
    • AT
    • GSM
    • STK
    • CDMA
    • PHONE
    • SMS
  • 没有Log次请求被重定向到events日志(或system日志,另请参阅http://elinux.org/Android_Logging_System
  • 所有其他Log个请求都会转到main日志,即通常受监控的日志。

2 个答案:

答案 0 :(得分:4)

在开始寻找源代码之前,我应该阅读logcat的文档。根据{{​​1}}的文档:

  

Android日志记录系统为日志消息保留多个循环缓冲区,并非所有日志消息都发送到默认循环缓冲区。

标签为logcat的消息将发送到无线缓冲区,而不是主缓冲区。因此,除非你不愿意这样做,否则你不会看到它们。如果您运行命令:

  

SMS

您应该会看到丢失的日志消息。以上信息可在https://developer.android.com/tools/debugging/debugging-log.html

中找到

现在,对于那些对代码搜寻感兴趣的人,下面是我的原始答案:

adb logcat -b radio类中的方法都是Log的包装器,它是JNI方法。
println_native对其参数执行一些验证,然后调用println_native

现在后一种方法将标记参数(来自原始__android_log_buf_write调用)与几个硬编码字符串(标记 SMS 是此列表之一)进行比较,如果找到匹配,结束将日志消息写入另一个文件!

顺便说一下,其他重新路由的标签是GSM,STK,PHONE,CDMA和其他一些标签。

可以在

中读取相关来源

这些不是官方链接,可能会在某些时候消失。我会尝试追踪官方链接并在今晚稍后进行编辑。

答案 1 :(得分:0)

编辑忽略这一点,根据this,我显然非常偏离基地。

所以我认为这很有意思,在深入了解源代码后,我最终发现了Log.isLoggable()

  

检查指定标记的日志是否可记录   在指定的级别。任何标记的默认级别都设置为INFO。   这意味着将记录任何级别以上且包括INFO。   在对日志记录方法进行任何调用之前,您应该查看   如果你的标签应该被记录。您可以更改默认级别   设置系统属性:' setprop log.tag。 '   级别是VERBOSE,DEBUG,INFO,WARN,ERROR,ASSERT或   压制。 SUPPRESS将关闭标签的所有日志记录。您可以   还创建一个local.prop文件,其中包含以下内容:   ' log.tag ='并将其放在/data/local.prop。

中      

参数
  标签   要检查的标签。
水平要检查的水平。

返回
  是否允许记录此内容。

显然某些日志级别不允许使用某些标记,似乎在/data/local.prop中定义,但必须有一些我尚未找到的系统级属性文件。你可以使用类似的东西来检查它,但是:

boolean isLoggableV = Log.isLoggable("SMS", Log.VERBOSE);
boolean isLoggableD = Log.isLoggable("SMS", Log.DEBUG);
boolean isLoggableI = Log.isLoggable("SMS", Log.INFO);
boolean isLoggableW = Log.isLoggable("SMS", Log.WARN);
boolean isLoggableE = Log.isLoggable("SMS", Log.ERROR);
boolean isLoggableA = Log.isLoggable("SMS", Log.ASSERT);

Log.v("LogTest", String.format("Verbose: %b Debug: %b Info: %b Warn: %b Error: %b Assert: %b", isLoggableV, isLoggableD, isLoggableI, isLoggableW, isLoggableE, isLoggableA));

对我来说,返回以下内容:

Verbose: false Debug: false Info: true Warn: true Error: true Assert: true

因此,您可以将标记SMS记录在INFO及更高级别的日志级别,而不是VERBOSEDEBUG

我必须假设这是为了防止应用程序意外地记录个人信息,但这似乎是一种相当粗暴的方式。