将标准输出重定向到 Android NDK 中的 logcat
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10531050/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Redirect stdout to logcat in Android NDK
提问by Sebastian Krysmanski
I can't get my Nexus S (running Android 4.0) to redirect native stdout message to logcat. I've read that I need to do this:
我无法让我的 Nexus S(运行 Android 4.0)将本机标准输出消息重定向到 logcat。我读过我需要这样做:
$ adb shell stop
$ adb shell setprop log.redirect-stdio true
$ adb shell start
However, this doesn't seem to work. (It does break JUnit though, as mentioned here, so it's not without effect.)
但是,这似乎不起作用。(虽然它确实破坏了 JUnit,正如这里提到的,所以它并非没有效果。)
For reference, here's my code:
作为参考,这是我的代码:
package com.mayastudios;
import android.util.Log;
public class JniTester {
public static void test() {
Log.e("---------", "Start of test");
System.err.println("This message comes from Java.");
void printCMessage();
Log.e("---------", "End of test");
}
private static native int printCMessage();
static {
System.loadLibrary("jni_test");
}
}
And the JNI .c file:
和 JNI .c 文件:
JNIEXPORT void JNICALL
Java_com_mayastudios_JniTester_printCMessage(JNIEnv *env, jclass cls) {
setvbuf(stdout, NULL, _IONBF, 0);
printf("This message comes from C (JNI).\n");
fflush(stdout);
//setvbuf(stderr, NULL, _IONBF, 0);
//fprintf(stderr, "This message comes from C (JNI).\n");
//fflush(stderr);
}
And the Android.mk:
和 Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := jni_test
LOCAL_SRC_FILES := test_jni.c
include $(BUILD_SHARED_LIBRARY)
I'm compiling this just by calling ndk-build. The native method is called correctly but I don't get any log output from it (even on verbose). I do get the log output from Java though ("This message comes from Java.").
我只是通过调用来编译它ndk-build。本机方法被正确调用,但我没有从中获得任何日志输出(即使是详细的)。不过,我确实从 Java 获得了日志输出(“此消息来自 Java。”)。
Any hints of what I might be doing wrong?
关于我可能做错了什么的任何提示?
PS: I've set up a small Mercurial repository that demonstrates the problem: https://bitbucket.org/skrysmanski/android-ndk-log-output/
PS:我已经建立了一个展示问题的小型 Mercurial 存储库:https: //bitbucket.org/skrysmanski/android-ndk-log-output/
回答by user2802811
This was not obvious to me from the previous answers. Even on rooted devices you need to run:
从以前的答案中,这对我来说并不明显。即使在有 root 权限的设备上,您也需要运行:
adb root
adb shell stop
adb shell setprop log.redirect-stdio true
adb shell start
回答by user2802811
You should also be able to wrap your logging code to detect if it's Android and if so use Android's logging. This may or may not be practical for everyone.
您还应该能够包装您的日志代码以检测它是否是 Android,如果是,则使用 Android 的日志记录。这对每个人来说可能实用,也可能不实用。
Include the logging header file:
包括日志记录头文件:
#include <android/log.h>
#include <android/log.h>
Use the built in logging functionality:
使用内置的日志记录功能:
__android_log_print(ANDROID_LOG_INFO, "foo", "Error: %s", foobar);
__android_log_print(ANDROID_LOG_INFO, "foo", "Error: %s", foobar);
回答by sqr163
setprop log.redirect-stdio trueredirects only output generated by java code, but not the native code. This fact is described on developer.android.comin following way:
setprop log.redirect-stdio true仅重定向 java 代码生成的输出,而不重定向本机代码。developer.android.com 上以下列方式描述了这一事实:
By default, the Android system sends stdout and stderr (System.out and System.err) output to /dev/null. In processes that run the Dalvik VM, you can have the system write a copy of the output to the log file.
默认情况下,Android 系统会将 stdout 和 stderr(System.out 和 System.err)输出发送到 /dev/null。在运行 Dalvik VM 的进程中,您可以让系统将输出的副本写入日志文件。
To get output from the native code, I really liked this solution
为了从本机代码中获取输出,我真的很喜欢这个解决方案
回答by fadden
stdout/stderr are redirected to /dev/nullin Android apps. The setprop workaround is a hack for rooted devices that copies stdout/stderr to the log. See Android Native Code Debugging.
stdout/stderr 被重定向到/dev/nullAndroid 应用程序中。setprop 解决方法是针对将 stdout/stderr 复制到日志的 root 设备的一种黑客攻击。请参阅Android 本机代码调试。
回答by Sergey Pekar
Here the code I use to to output stdout and stderr to android log
这里是我用来将 stdout 和 stderr 输出到 android 日志的代码
#include <android/log.h>
#include <pthread.h>
#include <unistd.h>
static int pfd[2];
static pthread_t loggingThread;
static const char *LOG_TAG = "YOU APP LOG TAG";
static void *loggingFunction(void*) {
ssize_t readSize;
char buf[128];
while((readSize = read(pfd[0], buf, sizeof buf - 1)) > 0) {
if(buf[readSize - 1] == '\n') {
--readSize;
}
buf[readSize] = 0; // add null-terminator
__android_log_write(ANDROID_LOG_DEBUG, LOG_TAG, buf); // Set any log level you want
}
return 0;
}
static int runLoggingThread() { // run this function to redirect your output to android log
setvbuf(stdout, 0, _IOLBF, 0); // make stdout line-buffered
setvbuf(stderr, 0, _IONBF, 0); // make stderr unbuffered
/* create the pipe and redirect stdout and stderr */
pipe(pfd);
dup2(pfd[1], 1);
dup2(pfd[1], 2);
/* spawn the logging thread */
if(pthread_create(&loggingThread, 0, loggingFunction, 0) == -1) {
return -1;
}
pthread_detach(loggingThread);
return 0;
}
回答by Mārti?? Mo?eiko
Try putting fflush(stdout);after your printf. Or alternatively use fprintf(stderr, "This message comes from C (JNI).\n");
试着把fflush(stdout);你的 printf放在后面。或者也可以使用fprintf(stderr, "This message comes from C (JNI).\n");
stdout by default is buffering. stderr - is not. And you are using System.err, not System.out from Java.
默认情况下,标准输出是缓冲。stderr - 不是。而且您使用的是 System.err,而不是 Java 中的 System.out。
Also you can disable stdout buffering with this: setvbuf(stdout, NULL, _IONBF, 0);Just make sure you call it before first printf call.
您也可以通过以下方式禁用标准输出缓冲:setvbuf(stdout, NULL, _IONBF, 0);只需确保在第一次 printf 调用之前调用它。

