androidローカルC++言語実行可能プログラムを最初から構築

9658 ワード

本文はcsdn lidpから有名な出典を転載した.
前編ではAndroid mkファイルの作成について説明しましたが、本編では具体的な例を挙げます.このプログラムの機能はandroidが提供するlog機能をカプセル化し、統一的なインタフェース関数を提供します.
droid_log(LOG_DEBUG,,,,,);
ロゴの印刷レベルは、スイッチによって決定することができます(ロゴr.hのLOGLEVELマクロを変更します).
LOG_VERBOSE, LOG_DEBUG,LOG_NOTICE,LOG_WARNING, LOG_ERROR.
logcatでは、印刷レベル、タイムスタンプ、関数名、ファイル名、および異なるレベルの構文に基づいてハイライト表示されます.
使用例:
droid_log(LOG_DEBUG, "test debug");
最初のパラメータは、printfと同様に、上記の5つのレベルであり、後に可変パラメータのリストである.
この機能は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
", 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); }

ファイルcpp :
#include "logger.h"
 
int main(int argc, char **argv)
{
    droid_log(LOG_DEBUG, "test debug
"); 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)

============
ファイル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では印刷が表示されます.
転載お断り.