在Android中, Java 代码通过 android.util.Log 输出Log信息,同样的本地 c/c++ 代码也提供了相对应而且是更多的接口。Android直接在头文件( system/core/include/cutils/log.h )里定义了一些日志输出的宏,这些宏比 android.util.Log 提供了更多的日志输出接口。因此,使用这些宏,就可以进行和java代码中一样的日志输出。宏 LOGD() , LOGE() , LOGI() , LOGV() , LOGW() , LOGD() 分别对应 android.util.Log 中的 Log.d() , Log.e() , Log.i() , Log.v() , Log.w() 。

注意: 这里的都是把日志输出到Main缓冲区。


另外,关于此文最好对照着《 Android LOG机制流程图 》一起来看。


log.h 中对日志输出还提供一些更细的宏,比如对于 LOGD() ,还提供了 LOGD_IF() , IF_LOGD(),SLOGD(),SLOGD_IF() 。其中 LOGD_IF() 表示条件输出, IF_LOGD() 用于测试是否需要输出, SLOGD() 表示把日志输出到 System 日志缓冲, SLOGD_IF() 表示条件成立的情况下,把日志输出到 System 日志缓冲。



注意: IF_LOGD() 现在总是返回1.



因为,LOG分了VERBOSE/DEBUG/INFO/WARN/ERROR/ASSERT等类别,简单起见,以DEBUG为例的实现来说明。



system\core\include\cutils)
  
 
  
#ifndef LOGD
 
  
#define 
   LOGD(...) 
   LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
 
  
#endif
 
  

 
  
#ifndef LOGD_IF
 
  
#define
    LOGD_IF(cond, ...)
    \
 
  
    ( (CONDITION(cond)) \
 
  
    ? LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__) \
 
  
    : (void)0 )
 
  
#endif
 
  

 
  
#ifndef IF_LOGD
 
  
 #define
    IF_LOGD()
    IF_LOG(LOG_DEBUG, LOG_TAG)
 
  
#endif
 
  

 
  
#ifndef SLOGD
 
  
 #define 
   SLOGD(...)
    ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
 
  
#endif
 
  
#ifndef SLOGD_IF
 
  
 #define 
   SLOGD_IF
   (cond, ...) \
 
  
     ( (CONDITION(cond)) \
 
  
     ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
 
  
     : (void)0 )
 
  
 #endif



 对于 宏 LOGD(),LOGE(),LOGI(),LOGV(),LOGW(),LOGD(), 其实最好使用以下的宏。


Log.h 文件中(
   system\core\include\cutils
   )
 
  
#ifndef LOG
 
  
#define LOG(priority, tag, ...) \
 
  
   
    LOG_PRI
   (ANDROID_##priority, tag, __VA_ARGS__)
 
  
#endif
 
  
#ifndef LOG_PRI
 
  
#define 
   LOG_PRI(priority, tag, ...) 
                                       \
 
  
    ({                                                                  \
 
  
       if (((priority == ANDROID_LOG_VERBOSE) && (LOG_NDEBUG == 0)) ||  \
 
  
           ((priority == ANDROID_LOG_DEBUG) && (LOG_NDDEBUG == 0))  ||  \
 
  
           ((priority == ANDROID_LOG_INFO) && (LOG_NIDEBUG == 0))   ||  \
 
  
            (priority == ANDROID_LOG_WARN)                          ||  \
 
  
            (priority == ANDROID_LOG_ERROR)                         ||  \
 
  
            (priority == ANDROID_LOG_FATAL))                            \
 
  
                
   (void)android_printLog(priority, tag, __VA_ARGS__)
   ;     \
 
  
    })
 
  
#endif
 
  
 
 
  
#define 
   android_printLog
   (prio, tag, fmt...) \
 
  
__android_log_print(prio, tag, fmt)



而这一系列宏,最后还是调用了 system/core/liblog/logd_write.c 中的__android_log_print()



int
     __android_log_print(int prio, const char *tag, const char *fmt, ...)
 
   
{
 
   
    va_list ap;
 
   
    char buf[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_write() 。 __android_log_write() 组织了参数,又调用了 write_to_log 这个函数指针。



关于 write_to_log 这个函数指针的调用详情请参考《 Android中LOG机制详解






要在 c/c++ 中使用Log,很简单。通常的做法是:



定义自己的 TAG_LOG 宏;包含头文件 log.h ;然后在需要记录Log的地方直接用 LOGV/LOGD/LOGI/LOGW/LOGE 等即可。



比如,文件 lights.c 中就在开头这样写,



#define LOG_TAG "lights"
 
   
#include <cutils/log.h>



然后在该文件的后续部分,直接用 LOGV/LOGE 等来输出日志就可以。