赞
踩
android中的log有很多级别,合理的控制log可以提高的解决问题的效率,减少工作量
1. log输出级别
android中的log级别如下
- ANDROID_LOG_UNKNOWN,
- ANDROID_LOG_DEFAULT,
- ANDROID_LOG_VERBOSE,
- ANDROID_LOG_DEBUG,
- ANDROID_LOG_INFO,
- ANDROID_LOG_WARN,
- ANDROID_LOG_ERROR,
- ANDROID_LOG_FATAL,
- ANDROID_LOG_SILENT,
-
2. log所在的文件
java中Log.java所对应的源码路径
使用时只需导入该Log类,如:
import android.util.Log;
native中log文件对应的源码路径
以上三个头文件依次include(包含)关系,使用时#include
3. log的级别说明
Info、Warn、Error这三个等级的Log的警示作用依次提高,需要一直保留。这些信息在系统异常时能提供有价值的分析线索。
VERBOSE DEBUG信息应当只存在于开发中,INFO,WARN,ERROR这三种log将出现在发布版本中。
4. native中打印控制
在system/core/include/log/log.h文件中有如下代码
- #ifndef LOG_NDEBUG
- #ifdef NDEBUG
- #define LOG_NDEBUG 1
- #else
- #define LOG_NDEBUG 0
- #endif
- #endif
以上宏定义的意思不解析,不明白可以baidu
通常在使用之前要在文件头加上如下代码来在打印中输入对就模块
- #ifndef LOG_TAG
- #define LOG_TAG ""
- #endif
Android的编译参数中,加入了-DNDEBUG,也就是默认是no debug的,
当然还需要LOG_NDEBUG LOG_NIDEBUG LOG_NDDEBUG这三个宏设置。
当-DNDEBUG被打上后,默认ALOGV会被禁止。
LOG_NDEBUG
LOG_NIDEBUG
LOG_NDDEBUG
这三个宏控制 LOG_PRI(priority, tag, ...)
NDEBUG 是总开关,默认在编译参数中加入,如果要控制打印级别,如下:
打开ALOGV: #define LOG_NDEBUG 0 //允许Verbose级别打印
打开ALOGI: #define LOG_NIDEBUG 0 //允许Info级别打印
打开ALOGD:#define LOG_NDDEBUG 0 //允许Debug级别打印
打开全部LOG:#undef NDEBUG //允许所有级别打印
5. 在native中自定义log函数
第一步:在对应的mk文件中加入:LOCAL_LDLIBS := -llog
第二步:在要使用LOG的cpp文件中加入:
#include //
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, fmt, __VA_ARGS__)
第三步:这样就可以使用了:LOGD("调试信息^_^"); 这样,在logcat端看到的输出是:D/keymatch( 32):我要看到的调试信息^_^ 如果想改变输出中的各项内容,可以参考相应颜色的标示,比如,如果想定义LOGE,就可以把上面的ANDROID_LOG_DEBUG改成ANDROID_LOG_ERROR,同理,LOGI神马的也都以此类推:
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "ProjectName", __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , "ProjectName", __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , "ProjectName", __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN , "ProjectName", __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , "ProjectName", __VA_ARGS__)
fmt:格式化字符串可以指定log格式
6. c++中的预定义宏
__LINE__: 当前源文件的行号,整数
__FILE__: 当前源文件名,char 字符串,使用 /FC 选项产生全路径
__DATE__: 当前编译日期,char 字符串,格式 Aug 28 2011
__TIME__: 当前编译时间,char 字符串,格式 06:43:59
__STDC__: 整数 1,表示兼容 ANSI/ISO C 标准,配合 #if 使用
__TIMESTAMP__: 最后一次修改当前文件的时间戳,char 字符串,格式 Sun Aug 28 06:43:57 2011
__cplusplus: 以 C++ 方式而非 C 语言方式编译时定义,VC 2005 中定义为 199711L,配合 #ifdef 使用
__VA_ARGS__: 在函数式宏中,代表变长部分参数 (...),参考 MSDN: Variadic Macros
__COUNTER__: include 展开编译单元后,编译时第一次遇到 __COUNTER__ 替换为 0,以后在这个编译每遇到一次 __COUNTER__ 自增一。不同的编译单元之间 __COUNTER__ 不互相积累叠加,均从 0 开始计数,但预编译头 .pch 文件会记录 __COUNTER__ 的历史值,则每个编译单元均从历史值 + 1 开始计数。__COUNTER__ 支持宏的嵌套展开
__FUNCTION__, __FUNCDNAME__, __FUNCSIG__: 表示所在函数的函数名的 char 字符串。例如,对于 void test_funcname_macro() 函数原型,它们的值如下:
(1). __FUNCTION__ = test_funcname_macro: 函数的原始名/非修饰名 (undecorated)
(2). __FUNCDNAME__ = ?test_funcname_macro@@YAXXZ: 函数的修饰名 (decorated),可用工具 undname "decorated_name" 得出函数原型和调用规范,即 __FUNCSIG__ 所表示的
(3). __FUNCSIG__ = void __cdecl test_funcname_macro(void): 函数的 signature 名,即调用约定、返回值类型、参数类型
7. 以下是我自定义log函数
#define LOGD(...) \
__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "[%s,%s,%d]:%s", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。