要在java层打印c的log必须引入这个头文件的宏定义:
#ifndef __LOG#define __LOG#ifdef __cplusplusextern "C"{#endif#include
//宏定义类似java 层的定义,不同级别的Log LOGI, LOGD, LOGW, LOGE, LOGF。 对就Java中的 Log.i log.d
#define LOG_TAG "HelloJni" //这个是自定义的LOG的标识
//#undef LOG//取消默认的LOG
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG, __VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG, __VA_ARGS__)#ifdef __cplusplus
}#endif
#endif
分析一下:这里调用了系统的log文件 #include
#ifndef _ANDROID_LOG_H#define _ANDROID_LOG_H#include#ifdef __cplusplusextern "C"{#endif
/** Android log priority values, in ascending priority order.*/typedefenumandroid_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 simple string to the log.*/
int __android_log_write(int prio, const char *tag, const char *text);/** 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__)#ifdef __USE_MINGW_ANSI_STDIO#if __USE_MINGW_ANSI_STDIO__attribute__ ((format(gnu_printf,3, 4)))#else__attribute__ ((format(printf,3, 4)))#endif
#else__attribute__ ((format(printf,3, 4)))#endif
#endif;/** A variant of __android_log_print() that takes a va_list to list
* additional parameters.*/
int __android_log_vprint(int prio, const char *tag,const char *fmt, va_list ap);/** Log an assertion failure and abort the process to have a chance
* to inspect it if a debugger is attached. This uses the FATAL priority.*/
void __android_log_assert(const char *cond, const char *tag,const char *fmt, ...)#if defined(__GNUC__)__attribute__ ((noreturn))
#ifdef __USE_MINGW_ANSI_STDIO#if __USE_MINGW_ANSI_STDIO__attribute__ ((format(gnu_printf,3, 4)))#else__attribute__ ((format(printf,3, 4)))#endif
#else__attribute__ ((format(printf,3, 4)))#endif
#endif;
#ifdef __cplusplus
}#endif
#endif /* _ANDROID_LOG_H */
View Code
这里面定义了log的优先级,并且log最终调用的都是__android_log_print(...)函数:
int __android_log_print(int prio, const char *tag, const char *fmt, ...)
{
va_list ap;charbuf[LOG_BUF_SIZE];
va_start(ap, fmt);
vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
va_end(ap);return__android_log_write(prio, tag, buf);
}
所以自己定义一个头文件,并且定义宏指令指向__android_log_print(...)。就可以调用了。
另外在 system/core/include/cutils/log.h 也有定义,但是有些没有,而且在#include 提示找不到。估计是版本变更了。但是原理是一样的。
下面是测试函数:
JNIEXPORT jint JNICALL Java_com_example_hellojni_MainActivity_test
(JNIEnv*env, jclass clazz){
LOGD("log.d Java_Log_test()");
LOGI("Log.i Java_Log_test()");return 0;
}
安卓测试程序:
public class MainActivity extendsActivity {static{
System.loadLibrary("HelloJava");
}privateButton btn_getString;privateTextView tv_content;
@Overrideprotected voidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initUI();
setEvent();
}private voidsetEvent() {//TODO Auto-generated method stub
btn_getString.setOnClickListener(newOnClickListener() {
@Overridepublic voidonClick(View v) {//TODO Auto-generated method stub
tv_content.setText(getString());
test();
}
});
}private voidinitUI() {//TODO Auto-generated method stub
btn_getString =(Button) findViewById(R.id.btn_getString);
tv_content=(TextView) findViewById(R.id.tv_content);
}public static nativeString getString();public static native inttest();
}
测试结果: