Capturing stdout / stderr using NDK

I am porting some existing C code to run on Android. This C code writes a lot of output to stdout / stderr. I need to write this output either to the memory buffer or to a file, so I can send it by e-mail or otherwise share it.

How can I achieve this, ideally without modifying the existing C code?

Note: this question is NOT about redirecting output to adb or logcat; I need to buffer the output locally on the device. I know the following questions that do not seem to affect my request:

  • Why does redirecting stdout / stderr on android not work?
  • Android NDK Native LIB what to do with existing stdio?
+12
c android stdout android-ndk stdio
Feb 08 2018-12-12T00:
source share
3 answers

stdout is path 1 and stderr is path 2. Knowing this, you can set new paths that you want to be the output destination, and then force them into stdout and / or stderr. There is an example demonstrating how to do this with practical examples using dup or dup2 .

+1
Feb 08 2018-12-12T00:
source share
— -

Use something like this to redirect stderr to the pipe. Ask the reader on the other side of the pipe to write logcat:

extern "C" void Java_com_test_yourApp_yourJavaClass_nativePipeSTDERRToLogcat(JNIEnv* env, jclass cls, jobject obj) { int pipes[2]; pipe(pipes); dup2(pipes[1], STDERR_FILENO); FILE *inputFile = fdopen(pipes[0], "r"); char readBuffer[256]; while (1) { fgets(readBuffer, sizeof(readBuffer), inputFile); __android_log_write(2, "stderr", readBuffer); } } 

You want to run this in your thread. I deploy the thread in Java and then the Java thread calls this NDK code as follows:

 new Thread() { public void run() { nativePipeSTDERRToLogcat(); } }.start(); 
+17
Jun 13 2018-12-12T00:
source share

I used the answer provided by James Moore, but I wanted to be able to turn logging on and off. With this, I can set mKeepRunning to false and it will shut down. I also needed to add the O_NONBLOCK flag to the file so that it was no longer a blocking call.

  int lWriteFD = dup(STDERR_FILENO); if ( lWriteFD < 0 ) { // WE failed to get our file descriptor LOGE("Unable to get STDERR file descriptor."); return; } int pipes[2]; pipe(pipes); dup2(pipes[1], STDERR_FILENO); FILE *inputFile = fdopen(pipes[0], "r"); close(pipes[1]); int fd = fileno(inputFile); int flags = fcntl(fd, F_GETFL, 0); flags |= O_NONBLOCK; fcntl(fd, F_SETFL, flags); if ( nullptr == inputFile ) { LOGE("Unable to get read pipe for STDERR"); return; } char readBuffer[256]; while (true == mKeepRunning) { fgets(readBuffer, sizeof(readBuffer), inputFile); if ( strlen(readBuffer) == 0 ) { sleep(1); continue; } __android_log_write(ANDROID_LOG_ERROR, "stderr", readBuffer); } close(pipes[0]); fclose(inputFile); 
+1
Mar 30 '15 at 12:52
source share



All Articles