此程序的功能为对android 提供的log功能进行封装,提供统一的接口函数

droid_log(LOG_DEBUG,,,,,);

可以根据开关决定log的打印级别(修改logger.h 中的LOGLEVEL 宏),从低到高为五个:

LOG_VERBOSE, LOG_DEBUG,LOG_NOTICE, LOG_WARNING, LOG_ERROR,  LOG_ERROR.

 

通过logcat可以看到打印级别,时间戳,函数名,文件名,以及根据不同级别的语法高亮显示。

使用例子:

 droid_log(LOG_DEBUG, "test debug\n");

第一个参数为上面提到的五个level, 后面为可变参数列表,与printf类似。

 

此功能在android上编译,把源码包放在external/下面,mm即可编译。

 

目录结构:

/android/external/hello

 

├── Android.mk

├── CleanSpec.mk

├── include

│   └── logger.h

└── src

    ├── Android.mk

    ├── hello.cpp

    └── logger.cpp

 
代码:
logger.h
 

/*! \file

 *

 * \brief Logging routines,Support for logging to console.

 *

 * \author openser <openser@yeah.net>

 *

 * \extref  android/log.h

 *

 *

 * - this is a wraper for  android log, user may see log in logcat.

 * - utility-related API functions, used by internal.

 * - 

 *

 * \ref none

 */

 

#ifndef _LOGGER_H_

#define _LOGGER_H_

 

#include <android/log.h>

#include <stdio.h>

#include <unistd.h>

#include <sys/time.h>

#include <time.h>

#include <stdarg.h>

#include <ctype.h>

#include <stdlib.h>

#include <string.h>

 

 

#define LOGLEVEL  5

 

 

#define ESC 0x1b

#define ATTR_RESET 0

#define ATTR_BRIGHT 1

#define ATTR_DIM 2

#define ATTR_UNDER 4

#define ATTR_BLINK 5

#define ATTR_REVER 7

#define ATTR_HIDDEN 8

 

/* termanal color define */

#define COLOR_BLACK 30

#define COLOR_GRAY   (30 | 128)

#define COLOR_RED 31

#define COLOR_BRRED (31 | 128)

#define COLOR_GREEN 32

#define COLOR_BRGREEN (32 | 128)

#define COLOR_BROWN 33

#define COLOR_YELLOW (33 | 128)

#define COLOR_BLUE 34

#define COLOR_BRBLUE (34 | 128)

#define COLOR_MAGENTA 35

#define COLOR_BRMAGENTA (35 | 128)

#define COLOR_CYAN      36

#define COLOR_BRCYAN    (36 | 128)

#define COLOR_WHITE     37

#define COLOR_BRWHITE   (37 | 128)

 

/* log level define */

#define _LOG_    __FILE__, __LINE__ ,__PRETTY_FUNCTION__

 

#ifdef LOG_VERBOSE 

#undef LOG_VERBOSE

#endif 

 

 

#ifdef LOG_VERBOSE

#undef LOG_VERBOSE

#endif

#define LOG_VERBOSE   0

#define LOGGER_VERBOSE    LOG_VERBOSE, _LOG_

 

#ifdef LOG_DEBUG

#undef LOG_DEBUG

#endif

 

#ifdef LOG_DEBUG

#undef LOG_DEBUG

#endif

#define LOG_DEBUG    1

#define LOGGER_DEBUG      LOG_DEBUG, _LOG_

 

#ifdef LOG_NOTICE

#undef LOG_NOTICE

#endif

#define LOG_NOTICE   2

#define LOGGER_NOTICE LOG_NOTICE, _LOG_

 

 

#ifdef LOG_WARNING

#undef LOG_WARNING

#endif

 

 

#ifdef LOG_WARNING

#undef LOG_WARNING

#endif

#define LOG_WARNING 3

#define LOGGER_WARNING LOG_WARNING, _LOG_

 

#ifdef LOG_ERROR

#undef LOG_ERROR

#endif

 

#ifdef LOG_ERROR

#undef LOG_ERROR

#endif

#define LOG_ERROR   4

#define LOGGER_ERROR  LOG_ERROR, _LOG_

 

extern const  char *loglevels[];

extern int colors[];

extern  char dateformat[256];

 

/*  out put time in a format */

void print_time();

 

/* fileter special sequeces ,such as ESC */

void term_filter_escapes(char *line);

 

/* copy string , This is similar to strncpy, with two important differences:

    - the destination buffer will  always be null-terminated

    - the destination buffer is not filled with zeros past the copied string length

  */

void tsk_copy_string(char *dst, const char *src, size_t size);

 

/* format the input sring to specific color */

char *term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout);

 

/* out put log to console in diff level 

     the level is : LOG_DEBUG, LOG_NOTICE, LOG_VERBOSE, LOG_ERROR, LOG_WARNING

     an out put example  :[Jan  2 04:55:55] DEBUG[1604]: src/transactions/tsip_transac_layer.c:282 tsip_transac_layer

  */

void _droid_log(int level, const char *file, int line, const char *function, const char *fmt, ...);

 

/*put a sring to console*/

void tsk_console_puts(char *str);

 

 

/*!

 * \brief Log a DEBUG message

 * \param level The minimum value of LOGLEVEL for this message

 *        to get logcat

 */

 

#define droid_log(level, ...) do {       \

        if (level <= (LOGLEVEL) ) { \

if(level == 0)  \

_droid_log(LOGGER_VERBOSE, __VA_ARGS__); \

else if( level == 1) \

_droid_log(LOGGER_DEBUG, __VA_ARGS__); \

else if(level == 2)  \

_droid_log(LOGGER_NOTICE, __VA_ARGS__); \

else if(level == 3)  \

_droid_log(LOGGER_WARNING, __VA_ARGS__); \

else if(level == 4)  \

_droid_log(LOGGER_ERROR, __VA_ARGS__); \

else \

_droid_log(LOGGER_DEBUG, __VA_ARGS__); \

} \

} while (0)

 

#endif

 
 
logger.cpp
 
 
/*! \file
 *
 * \brief Logging routines,Support for logging to console.
 *
 * \author openser <openser@yeah.net>
 *
 * \extref  android/log.h
 *
 *
 * - this is a wraper for  android log, user may see log in logcat.
 * - utility-related API functions, used by internal ccdt.
 * - 
 *
 * \ref none
 */
 
#include "logger.h"
#include <android/log.h>
 
 
/* log level definition */
  const  char *loglevels[] = {
    "VERBOSE",
    "DEBUG",
    "NOTICE",
    "WARNING",
    "ERROR",
};
 
/* used by term_color */
  int colors[] = {
COLOR_GREEN,
COLOR_BRGREEN,
COLOR_YELLOW,
COLOR_BRRED,
COLOR_RED,
COLOR_BRBLUE,
COLOR_BRGREEN,
};
 
/* date format , example : Jan  2 04:55:55*/
  char dateformat[256] = "%b %e %T";
 
void print_time()
{
    struct timeval tv;
    struct tm* ptm;
    char time_str[128];
    long milliseconds;
    gettimeofday(&tv, NULL);
    ptm = localtime(&tv.tv_sec);
    strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", ptm);
    milliseconds = tv.tv_sec/1000;
    printf("%s.%03ld\n", time_str, milliseconds);
}
 
void tsk_copy_string(char *dst, const char *src, size_t size)
{
    while(*src && size) {
        *dst++ = *src++;
        size--;
    }
 
    if(__builtin_expect(!size, 0))
        dst--;
    *dst = '\0';
}
 
void tsk_console_puts(char *str)
{
fprintf(stderr,"%s", str);
fflush(stderr);
}
 
void term_filter_escapes(char *line)
{
int i;
int len = strlen(line);
 
for (i = 0; i < len; i++) {
if (line[i] != ESC)
continue;
if ((i < (len - 2)) &&
   (line[i + 1] == 0x5B)) {
switch (line[i + 2]) {
case 0x30:
case 0x31:
case 0x33:
continue;
}
}
/* replace ESC with a space */
line[i] = ' ';
}
}
 
char *term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
{
int attr=0;
char tmp[40];
 
memset(outbuf, 0, maxout);
if (!fgcolor && !bgcolor) {
tsk_copy_string(outbuf, inbuf, maxout);
return outbuf;
}
if ((fgcolor & 128) && (bgcolor & 128)) {
/* Can't both be highlighted */
tsk_copy_string(outbuf, inbuf, maxout);
return outbuf;
}
if (!bgcolor)
bgcolor =COLOR_BLACK;
 
if (bgcolor) {
bgcolor &= ~128;
bgcolor += 10;
}
if (fgcolor & 128) {
attr = ATTR_BRIGHT;
fgcolor &= ~128;
}
if (fgcolor && bgcolor) {
snprintf(tmp, sizeof(tmp), "%d;%d", fgcolor, bgcolor);
} else if (bgcolor) {
snprintf(tmp, sizeof(tmp), "%d", bgcolor);
} else if (fgcolor) {
snprintf(tmp, sizeof(tmp), "%d", fgcolor);
}
if (attr) {
snprintf(outbuf, maxout, "%c[%d;%sm%s%c[0;%d;%dm", ESC, attr, tmp, inbuf, ESC, 
    COLOR_WHITE, COLOR_BLACK + 10);
} else {
snprintf(outbuf, maxout, "%c[%sm%s%c[0;%d;%dm", ESC, tmp, inbuf, ESC, COLOR_WHITE, 
    COLOR_BLACK + 10);
}
return outbuf;
}
 
void  _droid_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
{
 
    if(level > LOGLEVEL){
      return;
    }
    time_t t;
    struct tm *tm;
    char date[64];
    char linestr[64];
    char tmp1[64];
    char buf[256];
    char buf1[256];
    char msg[512];
    int res;
    va_list ap;
 
    t = time(NULL);
    tm = localtime(&t);
    memset(date, 0, sizeof(date));
    memset(buf, 0, sizeof(buf));
    memset(buf1, 0, sizeof(buf1));
    memset(msg, 0, sizeof(msg));
 
    strftime(date, sizeof(date), dateformat, tm);
    snprintf(linestr,sizeof(linestr),"%d", line);
    snprintf(buf,sizeof(buf),"[%s] %s[%ld]: %s %s: ",date,term_color(tmp1, loglevels[level], colors[level], 0, sizeof(tmp1)),(long)getpid(),
                                        linestr, function);
    term_filter_escapes(buf);
 
    va_start(ap, fmt);
    res = vsnprintf(buf1,sizeof(buf1) - 1,fmt, ap);
    va_end(ap);
 
    snprintf(msg, sizeof(msg) -1, "%s%s",buf,buf1);
 
    __android_log_print(ANDROID_LOG_DEBUG, "%s",msg);
 
}
 
 
 # src/Android.mk 
 
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
 
LOCAL_SRC_FILES:= \
        hello.cpp logger.cpp
 
LOCAL_MODULE_TAGS:= optional
LOCAL_C_INCLUDES := external/hello/include
LOCAL_MODULE:= hello
LOCAL_SYSTEM_SHARED_LIBRARIES := libc libstdc++ libutils
 
include $(BUILD_EXECUTABLE)
 
============
文件 hello/Android.mk
 
 
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
 
LOCAL_MODULE_TAGS := optional
 
include $(call all-makefiles-under,$(LOCAL_PATH))
 
 
文件 src/hello.cpp :
 
#include "logger.h"
 
int main(int argc, char **argv)
{
    droid_log(LOG_DEBUG, "test debug\n");
    return 0;
}