where is Android NDK printf output? - android

I have following code c++ code:
static void print_string(JNIEnv * env, jclass clazz, jstring str){
jboolean isCopy;
const char* utf_string;
utf_string = env->GetStringUTFChars(str, &isCopy);
env->ReleaseStringUTFChars(str, utf_string);
//LOGI("%s",utf_string);
// LOGE("JNI Out = %s", utf_string);
printf("jni out: %s",utf_string);
__android_log_print(ANDROID_LOG_INFO, "MyTag", "The value is %s", utf_string);
env->ReleaseStringUTFChars(str, utf_string);
}
I don't see any output in logcat. So where does it goes? How can I see it?

Accordint to the docs the output is lost:
By default, the Android system sends stdout and stderr (System.out and System.err) output to /dev/null.
There are methods to change that (on rooted devices), for example using setprop, taken from the docs:
$ adb shell stop
$ adb shell setprop log.redirect-stdio true
$ adb shell start

Related

what is the correct way to concat strings in c++ and execute using system

The following code is used in a native c++ library to create directory under android shell,
JNIEXPORT void JNICALL Java_com_xprea_lib_STB_mkdir(JNIEnv* env, jobject javaThis, jstring jdir) {
const char* dir = (env)->GetStringUTFChars(jdir, 0);
string d=dir;
string cmd= "su -c 'mkdir -p "+d+"'";
const char* c=cmd.c_str();
LOGE("s%s",c);
system(c);
}
it's not working because the command is built from concatenated strings.
I tested it without concatenation and it's working
What is the correct way to concat the strings all together and send them to system()
Your concatenation "su -c 'mkdir -p "+d+"'" results in the string
su -c 'mkdir -p BLA' (If the dir name is BLA)
So the command su searches for a command named mkdir -p BLA which it won't find. Better make:
"su -c mkdir -p '"+d+"'" your concatenation. This way it will search for a command named mkdir which it hopefully will find, and the directory name may even contain white space (although you would have to escape the ' and \ character with \.
Replace these 3 lines :
string d=dir;
string cmd= "su -c 'mkdir -p "+d+"'";
const char* c=cmd.c_str();
With these lines :
char cmd[1024];
sprintf(cmd,"su -c 'mkdir -p %s '",dir);

Android ADB Tool, 'fork' doesn't work

Environment
Android 5.0 # Samsung Galaxy 5
ADB # Windows (x64)
Native ADB Commandline tool
Use-case
An application that forks and immediately exit
Problem description
While fork returns a propper pid_t of the newly created process, no actual process is being created, ( 'adb -d shell ps | findstr shell' shows no new process )
Code snippet
__android_log_print(ANDROID_LOG_INFO, "ScreenCapSvc", "\n");
pid_t pid = fork();
__android_log_print(ANDROID_LOG_INFO, "ScreenCapSvc", "STARTED, pid = %d\n", pid);
if (0 != pid)
return S_OK;// Exits the parent process
HRESULT hr;
__android_log_print(ANDROID_LOG_INFO, "ScreenCapSvc", "Initializing\n");
if (FAILED(hr = Initialize(pBaseAddress, wPort, uiMaxMessageSize)))
return hr;
__android_log_print(ANDROID_LOG_INFO, "ScreenCapSvc", "Running modal loop\n");
hr = m_spIOCP->DoModal();
OnCleanup(hr);
__android_log_print(ANDROID_LOG_INFO, "ScreenCapSvc", "STOPPED, pid = %d\n", pid);
return S_OK;
Logcat output
I/ScreenCapSvc(29062):
I/ScreenCapSvc(29062): STARTED, pid = 29064
Additional info
If rather them immediately exiting the parent process I call eg. sleep(2) than the child process is properly forked, HOWEVER, While the parent process actually terminate, 'ADB -d shell' never exit ( stays hanging infinity ).
Related link: https://stackoverflow.com/questions/28277361/android-adb-tool-c11-stdthread-usage
What am I doing wrong? why does the process doesn't fork?

Redirect stdout to logcat in Android NDK

I can't get my Nexus S (running Android 4.0) to redirect native stdout message to logcat. I've read that I need to do this:
$ adb shell stop
$ adb shell setprop log.redirect-stdio true
$ adb shell start
However, this doesn't seem to work. (It does break JUnit though, as mentioned here, so it's not without effect.)
For reference, here's my 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");
}
}
And the JNI .c file:
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);
}
And the Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := jni_test
LOCAL_SRC_FILES := test_jni.c
include $(BUILD_SHARED_LIBRARY)
I'm compiling this just by calling ndk-build. The native method is called correctly but I don't get any log output from it (even on verbose). I do get the log output from Java though ("This message comes from Java.").
Any hints of what I might be doing wrong?
PS: I've set up a small Mercurial repository that demonstrates the problem: https://bitbucket.org/skrysmanski/android-ndk-log-output/
setprop log.redirect-stdio true redirects only output generated by java code, but not the native code. This fact is described on developer.android.com in following way:
By default, the Android system sends stdout and stderr (System.out and System.err) output to /dev/null. In processes that run the Dalvik VM, you can have the system write a copy of the output to the log file.
To get output from the native code, I really liked this solution
This was not obvious to me from the previous answers. Even on rooted devices you need to run:
adb root
adb shell stop
adb shell setprop log.redirect-stdio true
adb shell start
You should also be able to wrap your logging code to detect if it's Android and if so use Android's logging. This may or may not be practical for everyone.
Include the logging header file:
#include <android/log.h>
Use the built in logging functionality:
__android_log_print(ANDROID_LOG_INFO, "foo", "Error: %s", foobar);
Here the code I use to to output stdout and stderr to android log
#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;
}
stdout/stderr are redirected to /dev/null in Android apps. The setprop workaround is a hack for rooted devices that copies stdout/stderr to the log. See Android Native Code Debugging.
Try putting fflush(stdout); after your printf. Or alternatively use fprintf(stderr, "This message comes from C (JNI).\n");
stdout by default is buffering. stderr - is not. And you are using System.err, not System.out from Java.
Also you can disable stdout buffering with this: setvbuf(stdout, NULL, _IONBF, 0); Just make sure you call it before first printf call.

Run Shell Script file On Android Embedded Device using System function in Android NDK

All
Here i want to run .sh file via system call in android NDK.
I able to run cp,rm command via system call. but sh command is not working via system call.
I also installed busy-box on android.I am using below code.I set all permission on test.sh.
Code :
#include <stdlib.h>
#include <stdio.h>
#include <android/log.h>
#include <jni.h>
#define LOG_TAG "Demo"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
void Java_com_ndkdemo_NDKdemoActivity_systemcall(JNIEnv * env, jobject obj) {
int result;
result = system("cp /mnt/sdcard/test /Download");
LOGD("result is cp %d", result);
result = system("sh ./test.sh");
LOGD("result of test.sh is %d", result);
}
Output :
result is cp 0.
result of test.sh is 0.
Here i am getting 0 in system("sh ./test.sh"); but not started the test.sh script.
cant get output "Hi" on console.
test.sh contains
#!/system/bin/
echo "Hi"
If i am executing direct command on prompt than its working fine and its given output "Hi" on console.
Please Help me to figure out this issue.
Thanks
Where are you expecting to see the "echo"? By default, android sends stdout to /dev/null.
According to the documentation you can redirect stdout and stderr to the log (so it will show up in logcat) using the following commands:
$ adb shell stop
$ adb shell setprop log.redirect-stdio true
$ adb shell start
Now you may see your echo in adb logcat.
You might want to try sh -c /full/path/to/test.sh

Using Google Breakpad for Android NDK?

Is anyone using Google Breakpad for Android native code (NDK) ?
If so, could you elaborate on how to get it up and running (the client side that is).
The docs are very limited and don't mention Android at all. The build system contains android information though which make me think it shouldn't be a problem.
Sorry about that, I did the initial port but I didn't really document anything. However, one of the Chrome engineers did some work on the port and wrote a really nice README:
https://chromium.googlesource.com/breakpad/breakpad/+/master/README.ANDROID
There's also an NDK-compatible Android.mk file in there now, so if you're using the standard NDK build system it should be simple to incorporate Breakpad.
I also found a good example project for that.
As it is in the project you can set up Google Breakpad like:
extern "C" {
void Java_com_pluusystem_breakpadjavacall_MainActivity_initNative(JNIEnv* env, jobject obj, jstring filepath)
{
const char *path = env->GetStringUTFChars(filepath, 0);
google_breakpad::MinidumpDescriptor descriptor(path);
exceptionHandler = new google_breakpad::ExceptionHandler(descriptor, NULL, DumpCallback, NULL, true, -1);
}
}
in the cpp side and like:
// Save Dump Path
initNative(getExternalCacheDir().getAbsolutePath());
in the java side.
After that implementing the bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded) function you will be able to do something before the app crashes.
I have experienced and also found this issue which confirms me, that in this function you can't do java callbacks under ART just under DVM (before android 5 - Lollipop).
My example repo for Flutter Android/iOS: https://github.com/Sunbreak/flutter-breakpad.trial
Android
Build libbreakpad_client.a on Linux (e.g. https://multipass.run/)
$NDK is local path of your Android NDK directory
$CLI_BREAKPAD is local clone of https://github.com/Sunbreak/cli-breakpad.trial
cd $BREAKPAD/src/android
cp -r google_breakpad jni
$NDK/ndk-build
Install libbreakpad_client.a of all architectures
mkdir -p ./android/app/src/main/cmakeLibs
cp -r $BREAKPAD/src/android/obj/local/* ./android/app/src/main/cmakeLibs/
run on macOS/Linux
# Device/emulator connected
$ android_abi=`adb shell getprop ro.product.cpu.abi`
$ flutter run
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
I/flutter_breakpad(31631): JNI_OnLoad
D/flutter_breakpad(31631): Dump path: /data/data/com.example.flutter_breakpad/files/f5258c0e-eff3-433a-7ea47880-c756fc17.dmp
$ adb shell "run-as com.example.flutter_breakpad sh -c 'cat /data/data/com.example.flutter_breakpad/files/f5258c0e-eff3-433a-7ea47880-c756fc17.dmp'" >| libflutter-breakpad.so.dmp
run on Linux (e.g. https://multipass.run/)
$ $CLI_BREAKPAD/breakpad/linux/$(arch)/dump_syms build/app/intermediates/cmake/debug/obj/${android_abi}/libflutter-breakpad.so > libflutter-breakpad.so.sym
$ uuid=`awk 'FNR==1{print \$4}' libflutter-breakpad.so.sym`
$ mkdir -p symbols/libflutter-breakpad.so/$uuid/
$ mv ./libflutter-breakpad.so.sym symbols/libflutter-breakpad.so/$uuid/
$ $CLI_BREAKPAD/breakpad/linux/$(arch)/minidump_stackwalk libflutter-breakpad.so.dmp symbols/ > libflutter-breakpad.so.log

Categories

Resources