日志
1 日志
Logcat 和ddms
1.1框架
Android 日志框架是logger的内核模块
四个日志缓冲区:
Main 应用程序的日志信息
Event 系统事件
Radio radio相关日志
System 低级系统调试信息
1.2 原生日志api
为了便于原生代码向logger发送日志信息,在头文件log.h中定义
A 需要包含头文件#include <android.h>
B 修改android.mk LOCAL_LALIBS+=-llog
日志消息
包含以下几个字段:
Priority:verbose debug info warning error fatal 表示优先级
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;
Tag:logcat 和ddms通过此标签对日志进行过虑
Message:存实际的日志信息
日志函数
_android_log_write:生成简单的日志消息
_android_log_write(ANDROID_LOG_WARN,”hello-jni”,”warning log.”);
_android_log_print:生成格式化字符串作为日志消息
_andorid_log_print(ANDROID_LOG_ERROR,”hello-jni”,
”failed with errno %d”,erron);
_android_log_vprint:可以传递参数
_android_log_vprint(ANDROID_LOG_VERBOSS,”hello-jni”,format,args);
_android_log_assert:用于记录断言失败
_android_log_assert(“0!=errno”,”hello-jni”,”there is an error.”);
1.3受控制的日志
以hello-jni为例,在jni目录下添加my_log.h头文件
示例代码如下:
#pragma once
/**
* NDK基本日志框架
*
* @author retacn
*
*/
#include <android/log.h>
/*定义日志优先级*/
#define MY_LOG_LEVEL_VERBOSE 1
#define MY_LOG_LEVEL_DEBUG 2
#define MY_LOG_LEVEL_INFO 3
#define MY_LOG_LEVEL_WARNING 4
#define MY_LOG_LEVEL_ERROR 5
#define MY_LOG_LEVEL_FATAL 6
#define MY_LOG_LEVEL_SILENT 7
#ifndef MY_LOG_TAG
#define MY_LOG_TAG __FILE__
#endif
#ifndef MY_LOG_LEVEL
#define MY_LOG_LEVEL MY_LOG_LEVEL_VERBOSE
#endif
#define MY_LOG_NOOP (void) 0
#define MY_LOG_PRINT(level,fmt,...) __android_log_print(level,MY_LOG_TAG,"(%s:%u) %s: " fmt, __FILE__, __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__)
#if MY_LOG_LEVEL_VERBOSE >= MY_LOG_LEVEL
#define MY_LOG_VERBOSE(fmt,...) MY_LOG_PRINT(ANDROID_LOG_VERBOSE,fmt,##__VA_ARGS__)
#else
#define MY_LOG_VERBOSE(...) MY_LOG_NOOP
#endif
#if MY_LOG_LEVEL_DEBUG >= MY_LOG_LEVEL
#define MY_LOG_DEBUG(fmt,...) MY_LOG_PRINT(ANDROID_LOG_DEBUG,fmt,##__VA_ARGS__)
#else
#define MY_LOG_DEBUG(...) MY_LOG_NOOP
#endif
#if MY_LOG_LEVEL_INFO >= MY_LOG_LEVEL
#define MY_LOG_INFO(fmt,...) MY_LOG_PRINT(ANDROID_LOG_INFO,fmt,##__VA_ARGS__)
#else
#define MY_LOG_INFO(...) MY_LOG_NOOP
#endif
#if MY_LOG_LEVEL_WARNING >= MY_LOG_LEVEL
#define MY_LOG_WARNING(fmt,...) MY_LOG_PRINT(ANDROID_LOG_WARN,fmt,##__VA_ARGS__)
#else
#define MY_LOG_WARNING(...) MY_LOG_NOOP
#endif
#if MY_LOG_LEVEL_ERROR >= MY_LOG_LEVEL
#define MY_LOG_ERROR(fmt,...) MY_LOG_PRINT(ANDROID_LOG_ERROR,fmt,##__VA_ARGS__)
#else
#define MY_LOG_ERROR(...) MY_LOG_NOOP
#endif
#if MY_LOG_LEVEL_FATAL >= MY_LOG_LEVEL
#define MY_LOG_FATAL(fmt,...) MY_LOG_PRINT(ANDROID_LOG_FATAL,fmt,##__VA_ARGS__)
#else
#define MY_LOG_FATAL(...) MY_LOG_NOOP
#endif
#if MY_LOG_LEVEL_FATAL >= MY_LOG_LEVEL
#define MY_LOG_ASSERT(expression,fmt,...) if(!(expression)){__android_log_assert(#expression,MY_LOG_TAG,fmt,##__VA_ARGS__);}
#else
#define MY_LOG_ASSERT(...) MY_LOG_NOOP
#endif
增加日志
A 原生代码中添加头文件
#include “my-log.h”
B 在原生代码中添加日志声明语句
示例代码如下:
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
MY_LOG_VERBOSE("The stringFormJNI is called!");
MY_LOG_DEBUG("env=%p thiz=%p",env,thiz);
MY_LOG_ASSERT(0!=env,"JniEnv cannot be NULL");
MY_LOG_INFO("Returning a new string");
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
C 更新android.mk
MY_LOG_TAG=\”hell-jni\”
Ifeq($(APP_OPTIM),release)
MY_LOG_LEVEL := MY_LOG_LEVEL_ERROR
Else
MY_LOG_LEVEL := MY_LOG_LEVEL_VERBOSE
Endif
LOCAL_CFLAGS += -DMY_LOG_TAG=$(MY_LOG_TAG)
LOCAL_CFLAGS += -DMY_LOG_LEVEL-$(MY_LOG_LEVEL)
LOCAL_LDLIBS += -llog
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
#定义日志标签
MY_LOG_TAG := \"hell-jni\"
#定义默认日志等级
ifeq ($(APP_OPTIM),release)
MY_LOG_LEVEL := MY_LOG_LEVEL_ERROR
else
MY_LOG_LEVEL := MY_LOG_LEVEL_VERBOSE
Endif
#追加编译标记
LOCAL_CFLAGS += -DMY_LOG_TAG=$(MY_LOG_TAG)
LOCAL_CFLAGS += -DMY_LOG_LEVEL=$(MY_LOG_LEVEL)
#动态链接日志库
LOCAL_LDLIBS += -llog
include $(BUILD_SHARED_LIBRARY)
注:在直接复制 return (*env)->NewStringUTF(env, "Hello from JNI !");
函数时eclips会提示报错,修正办法是将以上代码改为: