`
yanfaguanli
  • 浏览: 658582 次
文章分类
社区版块
存档分类
最新评论

Android中关于JNI 的学习(五)在C文件中使用LogCat

 
阅读更多

Log是开发过程中,对于我们调试程序非常重要的一个工具,有很多时候,我们正是通过Log才能够看清楚程序是不是真的按照我们想像中的模式在跑,从而定位到问题所在的地方。而在Android开发中,毫无疑问,要是没有了logcat,我们调试程序的时候,就会痛苦死。

在NDK的开发中,尽管我们是利用C/C++来开发程序的,然后通过加载共享库的方法来调用C/C++程序,Android也提供了一套方法,可以让我们在LogCat中看到在C/C++代码中的数据流向,帮我们定位问题。

这一篇文章就简单地来说一下,如何在JNI层使用log工具。

回到我们之前的demo中,我们在程序中为了查看在JNI层某个数的值是否被改变了,我们特意添加了以下的log:

	LOGI("before change testval = %d", val);
	val = val + 1;
	LOGI("after change testval = %d", val);

当程序在手机上运行的时候,我们就可以在LogCat中看到以下的记录:


这说明了,在C/C++中同样是可以利用log工具来调试的(其实这是废话,因为Android中Log的实现本来就是通过JNI层,由C++实现的。)

下面我们就来说一下,如何在C/C++文件中添加log吧。

1)在C/C++文件中,要添加log的引用文件,如下面第2行:

#include "com_lms_jni_ParamTransferTest.h"
#include <android/log.h>
#include <jni.h>

在这里,我们会引用android/log.h头文件,而log.h头文件定义了几个log函数,如下:

/*
 * 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__)
    __attribute__ ((format(printf, 3, 4)))
#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);

2)引入log.h头文件之后,我们可以在C/C++中直接使用__android_log_print方法,不过老这样使用,就太麻烦了,所以我们可以重新定义一下,如下:

#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
在这里,我们定义了LOGD和LOGI 可变参数宏,分别对应不同级别的__andoid_log_print函数,这样我们在代码中,就可以直接通过LOGD和LOGI来写入log信息了。

在log.h头文件中,我们可以查到LOG对应的级别信息,如下:

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;

3)接下来,就是如何使用LOGI或者LOGD了,如下,在程序中需要写入log的地方,调用函数:

JNIEXPORT void JNICALL Java_com_lms_jni_ParamTransferTest_changeTestVal
  (JNIEnv * env, jobject obj){
	jclass clazz = (*env)->GetObjectClass(env,obj);
	jint val = (*env)->GetStaticIntField(env, clazz,
						(*env)->GetStaticFieldID(env, clazz,"testval","I"));
	LOGI("before change testval = %d", val);
	val = val + 1;
	LOGI("after change testval = %d", val);
	(*env)->SetStaticIntField(env, clazz,(*env)->GetStaticFieldID(env, clazz,"testval","I"),val);
}

4)到这一步,在C/C++中的使用就结束了,但是JNI的使用一般都是通过编译成共享库的形式,所以我们还需要在Android.mk文件中指定对应的库文件,如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := com_lms_jni_HwDemo

LOCAL_SRC_FILES := \
HwDemo.c \
JniTest.c \
ParamTransferTest.c

LOCAL_LDLIBS += -llog

include $(BUILD_SHARED_LIBRARY)

其中,我们可以看到 LOCAL_LDLIBS += -llog,在这里,LOCAL_LDLIBS 是告诉编译器,在编译这个共享库的时候,我们要去链接系统库中某一个库,而-llog,其实就是代表

liblog库的意思,-l是表明lib,而log则是表明前缀是lib的liblog的库,跟LOCAL_MODULE一样,编译器和链接器会自动处理前缀lib跟后缀.so,而liblog.so这个库就是在ndk提供的系统库中,如下:


5)通过这几步,我们就可以像在Android调试一样,在C/C++中去调试我们的程序了。

结束。


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics