Перенаправить stdout для logcat в Android NDK

Я не могу заставить свой Nexus S (под управлением Android 4.0) перенаправить собственное сообщение stdout на logcat. Я читал, что мне нужно это сделать:

$ adb shell stop $ adb shell setprop log.redirect-stdio true $ adb shell start 

Однако это не работает. (Однако он разрушает JUnit, как упоминалось здесь , так что это не без эффекта.)

Для справки, вот мой код:

 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"); } } 

И файл 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); } 

И Android.mk:

 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := jni_test LOCAL_SRC_FILES := test_jni.c include $(BUILD_SHARED_LIBRARY) 

Я компилирую это, просто вызвав ndk-build . Нативный метод вызывается правильно, но я не получаю от него никакого вывода журнала (даже на подробные). Я получаю вывод журнала из Java («Это сообщение происходит от Java»).

Любые намеки на то, что я могу делать неправильно?

PS: Я создал небольшой репозиторий Mercurial, который демонстрирует проблему: https://bitbucket.org/skrysmanski/android-ndk-log-output/

Solutions Collecting From Web of "Перенаправить stdout для logcat в Android NDK"

Это не было очевидным для меня из предыдущих ответов. Даже на корневых устройствах вам нужно запустить:

 adb root adb shell stop adb shell setprop log.redirect-stdio true adb shell start 

Вы также должны иметь возможность обернуть свой код регистрации, чтобы определить, является ли это Android, и если это так, используйте регистрацию Android. Это может быть или не быть практичным для всех.

Включить заголовочный файл журнала:

#include <android/log.h>

Используйте встроенную функцию ведения журнала:

__android_log_print(ANDROID_LOG_INFO, "foo", "Error: %s", foobar);

Stdout / stderr перенаправляются в /dev/null в приложениях Android. Обходной путь setprop – это взлом для корневых устройств, который копирует stdout / stderr в журнал. См. Отладка на основе кода для Android .

setprop log.redirect-stdio true перенаправляет только вывод, сгенерированный java-кодом, но не собственный код . Этот факт описан на developer.android.com следующим образом:

По умолчанию система Android отправляет выходы stdout и stderr (System.out и System.err) в / dev / null. В процессах, которые запускают Dalvik VM, вы можете написать системе копию копии файла журнала.

Чтобы получить выход из собственного кода, мне действительно понравилось это решение

Здесь код, который я использую для вывода 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; } 

Попробуйте положить fflush(stdout); После вашего printf. Или, альтернативно, используйте fprintf(stderr, "This message comes from C (JNI).\n") ;

По умолчанию stdout является буферизацией. Stderr – нет. И вы используете System.err, а не System.out с Java.

Также вы можете отключить буферизацию stdout следующим образом: setvbuf(stdout, NULL, _IONBF, 0); Просто убедитесь, что вы вызываете его перед первым вызовом printf.