3

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

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())。这是日志猫:

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日志,通常是被监控的。
4

2 回答 2

4

logcat在开始搜索源代码之前,我应该阅读文档。根据logcat的文档:

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

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

adb logcat -b radio

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


现在,对于那些对代码探索感兴趣的人,以下是我的原始答案:

类中的方法都是JNI 方法的Log包装器。对其参数执行一些验证,然后调用.println_native
println_native__android_log_buf_write

现在,后一种方法将标签参数(来自原始Log.d调用)与几个硬编码字符串(标签SMS是此列表之一)进行比较,如果找到匹配项,则最终将日志消息写入不同的文件!

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

相关来源可以阅读

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

于 2013-04-17T20:27:36.680 回答
0

编辑忽略这一点,根据这个,我显然很偏离基础。

所以我觉得这很有趣,在挖掘了源代码之后,我最终发现了Log.isLoggable()

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

参数
tag 要检查的标签。
level 要检查的级别。

返回
是否允许记录。

显然,某些日志级别不允许某些标签,似乎定义在 中/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

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

于 2013-04-17T19:16:50.757 回答