从头构建android 本地C++语言可执行程序


本文来自csdn lidp 转载著名出处。


上篇文章介绍了Android mk文件的编写,本篇举个具体例子,此程序的功能为对android 提供的log功能进行封装,提供统一的接口函数

droid_log(LOG_DEBUG,,,,,);

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

LOG_VERBOSE, LOG_DEBUG,LOG_NOTICE,LOG_WARNING, 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 <[email protected]>
 *
 * \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 <[email protected]>
 *
 * \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/hello.cpp :
#include "logger.h"
 
int main(int argc, char **argv)
{
    droid_log(LOG_DEBUG, "test debug\n");
    return 0;
}

# 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))



hello目录下执行mm生成可执行程序hello(out/targate/product/system/bin目录),拷贝到板子上 , 执行 ./hello

logcat 可看到打印。


谢绝转载。



你可能感兴趣的:(android)