2012-05-10 17 views
29

No puedo obtener mi Nexus S (con Android 4.0) para redirigir el mensaje nativo stdout a logcat. He leído que necesito hacer esto:redireccionar stdout a logcat en Android NDK

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

Sin embargo, esto no parece funcionar. (Lo hace romper JUnit embargo, como se mencionó here, así que no es sin efecto).

Como referencia, aquí está mi código:

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

y el archivo .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); 
} 

y el Android.mk:

LOCAL_PATH := $(call my-dir) 

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

estoy compilando esto simplemente llamando ndk-build. El método nativo se llama correctamente pero no obtengo ningún resultado de registro (incluso en verbose). Sin embargo, obtengo el resultado de registro de Java ("Este mensaje proviene de Java").

¿Algún indicio de lo que podría estar haciendo mal?

PS: He creado un pequeño repositorio de Mercurial que demuestra el problema: https://bitbucket.org/skrysmanski/android-ndk-log-output/

+0

comprobar mi respuesta en este questino - http : //stackoverflow.com/questions/10274920/how-to-get-printf-messgaes-written-in-ndk-application/10275209#10275209 – Shaiful

+1

Conozco esta solución (y eso es lo que terminé usando). Sin embargo, la pregunta original aún permanece. Tal vez es solo un error. –

+0

¿Has intentado eliminar la llamada setvbuf? Tengo printf seguido por fflush que aparece en el registro correctamente en el código que no usa setvbuf. –

Respuesta

-1

trate de poner fflush(stdout); después de su printf. O alternativamente use fprintf(stderr, "This message comes from C (JNI).\n");

stdout por defecto es el almacenamiento en búfer. stderr - no es. Y está utilizando System.err, no System.out desde Java.

También puede deshabilitar el almacenamiento en búfer estándar con esto: setvbuf(stdout, NULL, _IONBF, 0); Solo asegúrese de llamar antes de la primera llamada printf.

+0

Desafortunadamente, ni "fflush()" ni "setvbuf()" tienen ningún efecto, independientemente de si uso stdout o stderr. Lo probé con "fflush()" anteriormente, pero me olvidé de agregarlo a mi ejemplo. Ahora tengo. –

7

stdout/stderr se redirigen a /dev/null en las aplicaciones de Android. La solución setprop es un truco para dispositivos rooteados que copia stdout/stderr al registro. Ver Android Native Code Debugging.

15

Esto no era obvio para mí de las respuestas anteriores. Incluso en dispositivos con lo que necesita para funcionar:

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

Esto funciona para obtener el resultado, pero me volvió loco: ¡cualquier nueva compilación de aplicaciones no se instalaría correctamente! – hooby3dfx

+1

Esto no funcionó para mí. Tuve que volver a cambiarlo a falso antes de poder iniciar una aplicación nuevamente –

+0

Funciona bien en Samsung S3 –

9

También debe ser capaz de envolver su código de registro para detectar si se trata de Android y si a fin de utilizar el registro de Android. Esto puede o no ser práctico para todos.

Incluya el archivo de cabecera de registro:

#include <android/log.h>

utilizar el construido en la funcionalidad de registro:

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

+0

Esto funciona como un encanto! – Sharm

4

setprop log.redirect-stdio true redirige única salida generada por el código de Java, pero no el código nativo. Este hecho es described on developer.android.com en siguiente manera:

Por defecto, el sistema Android envía la salida stdout y stderr (System.out y System.err) a/dev/null.En los procesos que ejecutan la VM Dalvik, puede hacer que el sistema escriba una copia de la salida en el archivo de registro.

Para obtener una salida desde el código nativo, me gustó mucho this solution

+1

La solución vinculada aquí debe marcarse como la solución, ya que no requiere enrutamiento ni ningún otro privilegio especial. Simplemente llame a una función "init" desde el principio y todas las llamadas finales terminan en LogCat ... dulce. – gnichola

0

Aquí el código que utilizo para la salida estándar de salida y stderr a Android ingrese

#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

Necesitamos una forma estándar, no una solución alternativa. –