Short: What is the best way to invoke a process from Java and have its output be consumed by a C++ function invoked via JNI.
Long: I am experimenting with a log reader application for Android. For that, I have to run the logcat command and parse its output. I have attempted this from Java, but the amount of memory allocations performed are such that not only makes the process utterly slow but it also clutters the very same log with lots of GC related entries.
For that reason, I have implemented all parsing related operations in C++. However, I can’t use the usual fork/exec idiom to invoke logcat from the C++ side as its not really supported by the NDK. Instead, I need to start the process from Java and somehow make its output accessible to the C++ code. Ideally I would use a pipe for this, but the redirectOutput methods from ProcessBuilder are not available on Android either.
The best solution I have come up with so far is to start the process redirecting its output to a temporary file (using logcat > tempfile), and have the C++ code read from that file. However, this is far from ideal. Is there a better way to have native code access the output of a process started from Java?
Your premise is a bit mistaken: fork/exec() is no more “proper” on Android when accomplished from Java than when accomplished via the NDK – in both cases it works today, but is considered to be outside of the way Android apps are supposed to work.
Reading the logs is another borderline case: as of JellyBean, you can only read your own (process or userid, not sure which) messages. There is an ADB command which can be used to enable a given app to read all logs as in previous releases, but that has to be issued from the ADB – it cannot be set up by an app.
If you want to do literally what you have stated, regardless of the lack of necessity and impending limitation of utility, the thing to do would be to get knowledge of the file descriptors connecting to the child process into the native code. You may be able to pass it, or the native code may be able to discover it for itself, since all file descriptors are listed in /proc.