Android Logcat very strange behavior when getting empty string

百般思念 提交于 2019-12-02 05:36:25

问题


So I came across something strange that made me loose some time. I have been trying to print the content of an ArrayList containing string elements, sometimes, an element might contain an empty string, which is fine and absolutely my intention. So I have something like this:

List<String> l = new ArrayList<String>();

//adding strings in l, sometimes it's an empty string

for (int i=0; i < l.size(); i++) {
    Log.w("element in l : ", l.get(i));
}

So here, when the loop is gonna hit the empty string, logcat is simply NOT going to print it out BUT (and here is the root of my confusion), if you have a message following the one that failed to display, suddenly the failed message is going to show up as if it contained the new logcat message. For example if you try logging an empty string like this

Log.w(TAG,  <empty string here>);

Logcat is going to output nothing at first, then, when it has a NEW message to display this is what it prints out (in this case the new message is some warning about AudioTrack):

08-21 17:06:02.265  13047-13047/company.myapp W/TAG﹕ [ 08-21 17:06:05.411   766:  937 W/AudioTrack ]
    AUDIO_OUTPUT_FLAG_FAST denied by client

I'm interested in knowing how this happens, maybe it can help someone else not getting super confused like I did. I suppose trying to log an empty string triggers some kind of buffer that sits there until it gets something to print, is this a bug?


回答1:


That is an interesting question. I just tried this in LogRabbit and am able to see the same result.

I took a quick browse through the android source and see that Log.W(...) ends up in native code and getting handled in logd_write.c

This basically writes the data to /dev/log/main (or one of the other logs)

You can get those logs like this:

adb pull /dev/log/events .
adb pull /dev/log/main .
adb pull /dev/log/radio .
adb pull /dev/log/system .

You will need to press cntl-C otherwise the copy will happen forever.

Looking in the raw log in /dev/log/main I see the message does get logged:

 <8b>F×U^_<8c>^Y^U^Emfl_MessageList^@Before Empty^@^R^@^@^@!z^@^@!z^@^@
 <8b>F×U^_<8c>^Y^U^Emfl_MessageList^@^@^]^@^@^@!z^@^@!z^@^@
 <8b>F×U^_ <8c>^Y^U^Emfl_MessageList^@After Empty^@7^@^@^@^@^E^@^@^Z^E^@^@

That gets decoded by struct found in logger.h So I think this is a problem in adb. pull the source code from here: (looks like quite a few of undocumented commands there)

This is the primary function

static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
    char* log_tags = getenv("ANDROID_LOG_TAGS");
    std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);

    std::string cmd = "shell:export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";

    if (!strcmp(argv[0], "longcat")) {
        cmd += " -v long";
    }

    --argc;
    ++argv;
    while (argc-- > 0) {
        cmd += " " + escape_arg(*argv++);
    }

    return send_shell_command(transport, serial, cmd);
}

Looking in there I see that all logcat does is basically this:

adb shell
> exec logcat

So I think the root of the problem is in logcat itself. Logcat.cpp calls into log_read.c

Based on my quick read through things what I think is happening is the message is not terminated properly. The empty message does not show up until another message is appended and the first message overruns and shows the second message because it has the appropriate termination.



来源:https://stackoverflow.com/questions/32143903/android-logcat-very-strange-behavior-when-getting-empty-string

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!