2012-05-10 8 views
29

Ich kann nicht mein Nexus S (mit Android 4.0), um native Stdout Nachricht an logcat umleiten. Ich habe gelesen, dass ich dies tun muss:Redirect Stdout auf Logcat in Android NDK

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

Allerdings scheint dies nicht zu funktionieren. (Es tut JUnit obwohl brechen, wie here erwähnt, es ist also nicht ohne Wirkung.)

Als Referenz hier ist mein 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"); 
    } 
} 

Und die JNI C-Datei:

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

und die Android.mk:

LOCAL_PATH := $(call my-dir) 

include $(CLEAR_VARS) 
LOCAL_MODULE := jni_test 
LOCAL_SRC_FILES := test_jni.c 
include $(BUILD_SHARED_LIBRARY) 

ich kompilieren dies nur durchAufruf. Die native Methode wird korrekt aufgerufen, aber ich erhalte keine Protokollausgabe von ihr (auch nicht im ausführlichen Modus). Ich bekomme jedoch die Log-Ausgabe von Java ("Diese Nachricht kommt von Java.").

Irgendwelche Hinweise darauf, was ich falsch machen könnte?

PS: Ich habe eine kleine Mercurial-Repository einrichten, das das Problem veranschaulicht: https://bitbucket.org/skrysmanski/android-ndk-log-output/

+0

überprüfen Sie meine Antwort in diesem questino anmelden - http : //stackoverflow.com/questions/10274920/how-to-get-printf-messgaes-written-in-ndk-application/10275209#10275209 – Shaiful

+1

Ich kenne diese Lösung (und das ist, was ich am Ende verwendet). Die ursprüngliche Frage bleibt jedoch bestehen. Vielleicht ist es nur ein Fehler. –

+0

Haben Sie versucht, den Aufruf von setvbuf zu entfernen? Ich habe printf gefolgt von fflush im log korrekt in Code angezeigt, der setvbuf nicht verwendet. –

Antwort

-1

Versuchen fflush(stdout); nach dem printf setzen. Oder alternativ fprintf(stderr, "This message comes from C (JNI).\n");

stdout puffert standardmäßig. stderr - ist nicht. Und Sie verwenden System.err, nicht System.out von Java.

Sie können auch stdout Pufferung mit diesem deaktivieren: setvbuf(stdout, NULL, _IONBF, 0); Stellen Sie sicher, dass Sie es vor dem ersten printf Anruf aufrufen.

+0

Leider haben weder "fflush()" noch "setvbuf()" irgendeinen Effekt - egal ob ich stdout oder stderr verwende. Ich habe es vorher mit "fflush()" getestet, aber ich habe vergessen, es zu meinem Beispiel hinzuzufügen. Ich habe jetzt. –

7

stdout/stderr werden zu /dev/null in Android-Apps umgeleitet. Die Setprop-Problemumgehung ist ein Hack für gerootete Geräte, der stdout/stderr in das Protokoll kopiert. Siehe Android Native Code Debugging.

15

Dies war mir aus den vorherigen Antworten nicht offensichtlich. Auch auf rooted Geräten müssen Sie laufen:

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

Das funktioniert, um die Ausgabe zu bekommen, aber es hat mich nur verrückt gemacht - neue App-Builds würden nicht korrekt installiert werden! – hooby3dfx

+1

Das hat nicht für mich funktioniert. Ich musste es wieder auf false ändern, bevor ich wieder eine App starten konnte –

+0

Funktioniert gut auf Samsung S3 –

9

Sie sollten auch in der Lage sein, Ihren Logging-Code wickeln zu erkennen, ob es Android ist und wenn ja, Android-Protokollierung. Dies kann oder kann nicht für jeden praktisch sein.

Fügen Sie die Logging-Header-Datei:

#include <android/log.h>

Verwenden Sie die in Logging-Funktionalität eingebaut:

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

+0

Das funktioniert wie ein Zauber! – Sharm

4

setprop log.redirect-stdio true nur dann ausgegeben, Umleitungen von Java-Code erzeugt, aber nicht den nativen Code. Diese Tatsache ist described on developer.android.com in folgenden Weise:

Standardmäßig sendet das System Android stdout und stderr (System.out und System.err) Ausgang zu/dev/null.In Prozessen, in denen die Dalvik-VM ausgeführt wird, können Sie eine Kopie der Ausgabe in die Protokolldatei schreiben.

Zur Ausgabe von dem nativen Code bekommen, ich mochte this solution

+1

Die hier verknüpfte Lösung sollte als Lösung markiert werden, da keine Root-Funktion oder andere spezielle Berechtigungen erforderlich sind. Rufen Sie einfach eine "Init" -Funktion an und alle Cout-Aufrufe enden in LogCat ... süß. – gnichola

0

hier wirklich der Code I zur Ausgabe von stdout und stderr verwenden, um 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; 
} 
+0

Wir brauchen einen Standardweg und keine Abhilfe. –