2013年12月10日 星期二

在 JNI 程式碼使用 Logcat

在 Android 應用的程式碼裡,可以使用 Log.v()、Log.d()、Log.i() 等函式將訊息送到 log output,然後開發者可以透過 Logcat 查看。

但,如果在 Android 應用裡使用了 JNI 及 NDK,又該如何將訊息送到 log output,才能在 Logcat 裡查看呢?

首先,查看了 NDK 的 docs/STABLE-APIS.html,找到這段說明:

Android-specific Log Support:
<android/log.h> contains various definitions that can be used to send log messages to the kernel from your native code. Please have a look at its content in (platforms/android-3/arch-arm/usr/include/android/log.h), which contain many informative comments on how to use it.
You should be able to write helpful wrapper macros for your own usage to access this facility.
If you use it, your native module should link to /system/lib/liblog.so with:
    LOCAL_LDLIBS := -llog 

然後在 android/log.h 裡找到:

/*
 * Android log priority values, in ascending priority order.
 */
typedef enum android_LogPriority {
    ANDROID_LOG_UNKNOWN = 0,
    ANDROID_LOG_DEFAULT,    /* only for SetMinPriority() */
    ANDROID_LOG_VERBOSE,
    ANDROID_LOG_DEBUG,
    ANDROID_LOG_INFO,
    ANDROID_LOG_WARN,
    ANDROID_LOG_ERROR,
    ANDROID_LOG_FATAL,
    ANDROID_LOG_SILENT,     /* only for SetMinPriority(); must be last */
} android_LogPriority;

/*
 * Send a formatted string to the log, used like printf(fmt,...)
 */
int __android_log_print(int prio, const char *tag,  const char *fmt, ...)
#if defined(__GNUC__)
    __attribute__ ((format(printf, 3, 4)))
#endif
    ; 

接著,拿 NDK samples 裡的 hello-jni 來試試。首先,修改 jni/Android.mk,加入這行:

LOCAL_LDLIBS += -llog 

再修改 jni/hello-jni.c,除了引入 android/log.h 這個標頭檔,並使用 __android_log_print 將訊息送到 log output。

#include <android/log.h>

jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
    __android_log_print(ANDROID_LOG_INFO, "HelloJNI", "Show: Hello from JNI !");
    return (*env)->NewStringUTF(env, "Hello from JNI !");
} 

如此,當這隻程式執行時,就可以在 Logcat 裡查看由 __android_log_print 送出的訊息了。

張貼留言