2012-05-10 23 views
29

Nie mogę pobrać Nexusa S (z systemem Android 4.0), aby przekierować macierzystą wiadomość wyjściową do logcat. Czytałem, że muszę to zrobić:Przekieruj stdout na logcat w systemie Android NDK

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

To jednak nie działa. (Robi złamać JUnit choć, jak wspomniano here, więc to nie jest bez efektu).

Dla porównania, tutaj jest mój kod:

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

a plik .c JNI:

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

I kompilacja tego jest dostępna pod numerem.. Natywna metoda jest wywoływana poprawnie, ale nie otrzymuję z niej żadnego logu (nawet w pełnym rozmiarze). Dostaję dane wyjściowe dziennika z Javy ("Ta wiadomość pochodzi z Java.").

Jakieś wskazówki na temat tego, co robię źle?

PS: Mam założyć małą Mercurial repozytorium, który pokazuje problem: https://bitbucket.org/skrysmanski/android-ndk-log-output/

+0

Sprawdź moją odpowiedź w tym questino - http : //stackoverflow.com/questions/10274920/how-to-get-printf-messgaes-written-in-ndk-application/10275209#10275209 – Shaiful

+1

Jestem świadomy tego rozwiązania (i właśnie to wykorzystałem). Jednak pierwotne pytanie pozostaje nadal. Może to tylko błąd. –

+0

Czy próbowałeś usunąć wywołanie setvbuf? Mam printf po tym, jak fflush pokazuje się w logu poprawnie w kodzie, który nie używa setvbuf. –

Odpowiedz

-1

spróbuj umieścić fflush(stdout); po printf. Lub alternatywnie użyj fprintf(stderr, "This message comes from C (JNI).\n");

Domyślnie stdout buforuje. stderr - nie jest. Używasz System.err, a nie System.out z Java.

Można również wyłączyć buforowanie standardowe: setvbuf(stdout, NULL, _IONBF, 0); Wystarczy się upewnić, że wywołasz je przed pierwszym wywołaniem printf.

+0

Niestety, ani "fflush()", ani "setvbuf()" nie mają żadnego efektu - niezależnie od tego, czy używam stdout, czy stderr. Zrobiłem test z "fflush()" wcześniej, ale po prostu zapomniałem dodać go do mojego przykładu. Mam teraz. –

7

stdout/stderr są przekierowywane do /dev/null w Androida. Rozwiązanie zastępcze Setprop jest hack dla zrootowanych urządzeń, które kopiują stdout/stderr do dziennika. Zobacz Android Native Code Debugging.

15

To nie było dla mnie oczywiste z poprzednich odpowiedzi. Nawet na urządzeniach ukorzenionych trzeba uruchomić:

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

To działa, aby uzyskać wyniki, ale to po prostu doprowadziło mnie do szaleństwa - wszelkie nowe kompilacje aplikacji nie zostaną poprawnie zainstalowane! – hooby3dfx

+1

To nie działa dla mnie. Musiałem zmienić to z powrotem na false, zanim ponownie uruchomiłem aplikację. –

+0

Działa dobrze na Samsung S3 –

9

Należy także być w stanie owinąć kod logowania, aby wykryć, czy jest to Android, a jeśli tak korzystać rejestrowanie Androida. To może, ale nie musi być praktyczne dla wszystkich.

dołączyć plik nagłówka rejestrowania:

#include <android/log.h>

korzystać z wbudowanych funkcji rejestrowania:

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

+0

To działa jak urok! – Sharm

4

setprop log.redirect-stdio true przekierowuje tylko moc generowaną przez kod Java, ale nie natywnego kodu. Fakt ten jest described on developer.android.com w następujący sposób:

Domyślnie system Android wysyła stdout i stderr (System.out i System.err) wyjście do/dev/null.W procesach obsługujących maszynę Dalvik VM można zlecić systemowi zapisanie kopii pliku wyjściowego do pliku dziennika.

Aby uzyskać wyjście z natywnego kodu, bardzo lubiłem this solution

+1

Rozwiązanie tutaj połączone powinno zostać oznaczone jako rozwiązanie, ponieważ nie wymaga rootowania ani żadnych innych specjalnych uprawnień. Po prostu wywołaj funkcję "init" na początku, a wszystkie połączenia cout będą w LogCat ... słodkie. – gnichola

0

Oto kod Używam do stdout i stderr do Android zalogować

#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

Potrzebujemy standardowy sposób, a nie obejście tego problemu. –

Powiązane problemy