c语言中的printf我想大家都非常的熟悉了,他的基本格式如下
int printf(const char *format, ...);
前半部分 format 指向的字符串用于描述最终输出内容的格式,而后半部分则是被前面 format 所解析的各种变量/常量,这两部分则是构成输出的内容。而Android中也有类似的内容输出函数,用法和printf也是类似的及前半部为格式,后半部为各种变量/常量。
ALOGI(const char *format, ...);
printf打印内容到标准输出,而ALOG系列接口则是打印内容到Android的log系统中去。
在 Android 中,有着非常多的子系统,所以 Android 的 ALOG 系统是支持多个buffer的,即不同类型的log写入不同的buffer中。它所支持的log类型可以简单的使用对应版本的 logcat 工具查看
board:/ # logcat -h
Usage: logcat [options] [filterspecs]
General options:
-b, --buffer=<buffer> Request alternate ring buffer(s):
main system radio events crash default all
Additionally, 'kernel' for userdebug and eng builds, and
'security' for Device Owner installations.
Multiple -b parameters or comma separated list of buffers are
allowed. Buffers are interleaved.
Default -b main,system,crash,kernel.
在c语言风格的log接口中大致支持3种buffer,它们分别是 main/system/radio ,在使用的时候只要包含 liblog::log/log.h 即可
main类型的的buffer用来打印一般的log信息,注意了,虽然是一般,但是也不要打印垃圾内容,毕竟log系统的buffer是很紧俏的。
//system\logging\liblog\include\log\log_main.h
#define ALOGI(const char *format, ...)
该类型的 buffer 用来打印系统组件相关的log。同样的不要打印垃圾信息到这一类型的buffer中去。
//system\logging\liblog\include\log\log_system.h
#define SLOGI(const char *format, ...)
该类型的 buffer 用来打印电话相关的组件的log。同样的不要打印垃圾信息到这一类型的buffer中去。
//system\logging\liblog\include\log\log_radio.h
#define RLOGI(const char *format, ...)
手头需要做的事有轻重缓急,log中的信息所代表的事项也同样如此。下面是Android log 系统的几个级别
//file:system\logging\liblog\include\android\log.h
/**
* Android log priority values, in increasing order of priority.
*/
typedef enum android_LogPriority {
...
/** Verbose logging. Should typically be disabled for a release apk. */
ANDROID_LOG_VERBOSE,
/** Debug logging. Should typically be disabled for a release apk. */
ANDROID_LOG_DEBUG,
/** Informational logging. Should typically be disabled for a release apk. */
ANDROID_LOG_INFO,
/** Warning logging. For use with recoverable failures. */
ANDROID_LOG_WARN,
/** Error logging. For use with unrecoverable failures. */
ANDROID_LOG_ERROR,
/** Fatal logging. For use when aborting. */
ANDROID_LOG_FATAL,
...
} android_LogPriority;
每一个级别的使用场景在代码注释中说的也算详细,此处就不再赘述。其中 ANDROID_LOG_FATAL 级别的LOG最终会调用 abort,abort则会造成应用程序的意外退出。如果在非系统应用中则会导致应用本身退出。如果是系统级别的那么就有可能导致Android系统奔溃了
NAME
abort - cause abnormal process termination
SYNOPSIS
#include <stdlib.h>
void abort(void);
DESCRIPTION
The abort() first unblocks the SIGABRT signal, and then raises that signal for the calling process (as though raise(3) was called). This results in
the abnormal termination of the process unless the SIGABRT signal is caught and the signal handler does not return (see longjmp(3)).
If the abort() function causes process termination, all open streams are closed and flushed.
If the SIGABRT signal is ignored, or caught by a handler that returns, the abort() function will still terminate the process. It does this by
restoring the default disposition for SIGABRT and then raising the signal for a second time.
RETURN VALUE
The abort() function never returns.
//system\logging\liblog\include\log\log_main.h
#define ALOGV(const char *format, ...)
//system\logging\liblog\include\log\log_radio.h
#define RLOGV(const char *format, ...)
//system\logging\liblog\include\log\log_system.h
#define SLOGV(const char *format, ...)
//system\logging\liblog\include\log\log_main.h
#define ALOGD(const char *format, ...)
//system\logging\liblog\include\log\log_radio.h
#define RLOGD(const char *format, ...)
//system\logging\liblog\include\log\log_system.h
#define SLOGD(const char *format, ...)
//system\logging\liblog\include\log\log_main.h
#define ALOGI(const char *format, ...)
//system\logging\liblog\include\log\log_radio.h
#define RLOGI(const char *format, ...)
//system\logging\liblog\include\log\log_system.h
#define SLOGI(const char *format, ...)
//system\logging\liblog\include\log\log_main.h
#define ALOGW(const char *format, ...)
//system\logging\liblog\include\log\log_radio.h
#define RLOGW(const char *format, ...)
//system\logging\liblog\include\log\log_system.h
#define SLOGW(const char *format, ...)
//system\logging\liblog\include\log\log_main.h
#define ALOGE(const char *format, ...)
//system\logging\liblog\include\log\log_radio.h
#define RLOGE(const char *format, ...)
//system\logging\liblog\include\log\log_system.h
#define SLOGE(const char *format, ...)
//system\logging\liblog\include\log\log_main.h
ALOG(LOG_FATAL, LOG_TAG, const char *format, ...);
cc_binary {
name: "ALOGtest",
srcs: [
"*.cpp",
],
shared_libs: [
"liblog",
],
cppflags: [
"-Wno-unused-parameter",
],
}
C语言风格的log打印接口,只使用了库 liblog,所以只要包含它即可。
//ALOGtest.cpp
#define LOG_TAG "ALOGtest"
#include <stdlib.h>
#include <log/log.h>//from liblog
/**
* board:/ # logcat -b all -s ALOGtest&
* board:/ # ALOGtest
* board:/ # --------- beginning of main
* 11-27 14:40:09.361 5863 5863 I ALOGtest: ALOGI:write INFO level to main buffer
* 11-27 14:40:09.362 5863 5863 I ALOGtest: ALOGI_IF:write INFO level to main buffer
* --------- beginning of radio
* 11-27 14:40:09.362 5863 5863 I ALOGtest: RLOGI:write INFO level to radio buffer
* 11-27 14:40:09.362 5863 5863 I ALOGtest: RLOGI_IF:write INFO level to radio buffer
* --------- beginning of system
* 11-27 14:40:09.362 5863 5863 I ALOGtest: SLOGI:write INFO level to sytem buffer
* 11-27 14:40:09.362 5863 5863 I ALOGtest: SLOGI_IF:write INFO level to sytem buffer
*/
int main(int argc, char* argv[])
{
/*
logcat -b main -s ALOGtest&
*/
ALOGI("ALOGI:write INFO level to main buffer\n");
ALOGI_IF((3 > 2), "ALOGI_IF:write INFO level to main buffer\n");
/*
logcat -b radio -s ALOGtest&
*/
RLOGI("RLOGI:write INFO level to radio buffer\n");
RLOGI_IF((3 > 2), "RLOGI_IF:write INFO level to radio buffer\n");
/*
logcat -b system -s ALOGtest&
*/
SLOGI("SLOGI:write INFO level to sytem buffer\n");
SLOGI_IF((3 > 2), "SLOGI_IF:write INFO level to sytem buffer\n");
/**
* board:/ # ALOGtest
* 11-27 16:04:54.597 5883 5883 I ALOGtest: ALOGI:write INFO level to main buffer
* 11-27 16:04:54.597 5883 5883 I ALOGtest: ALOGI_IF:write INFO level to main buffer
* 11-27 16:04:54.597 5883 5883 I ALOGtest: RLOGI:write INFO level to radio buffer
* 11-27 16:04:54.597 5883 5883 I ALOGtest: RLOGI_IF:write INFO level to radio buffer
* 11-27 16:04:54.597 5883 5883 I ALOGtest: SLOGI:write INFO level to sytem buffer
* 11-27 16:04:54.598 5883 5883 I ALOGtest: SLOGI_IF:write INFO level to sytem buffer
* 11-27 16:04:54.598 5883 5883 F ALOGtest: ALOG:LOG_FATAL:write LOG_FATAL level to main buffer
*/
ALOG(LOG_FATAL, LOG_TAG, "ALOG:LOG_FATAL:write LOG_FATAL level to main buffer\n");
return EXIT_SUCCESS;
}
LOG_TAG需要在log/log.h前定义。
所有支持的接口都位于如下接口
file:system\logging\liblog\include\log\log.h
board:/ # ALOGtest
11-27 16:15:05.936 5885 5885 I ALOGtest: ALOGI:write INFO level to main buffer
11-27 16:15:05.937 5885 5885 I ALOGtest: ALOGI_IF:write INFO level to main buffer
11-27 16:15:05.937 5885 5885 I ALOGtest: RLOGI:write INFO level to radio buffer
11-27 16:15:05.937 5885 5885 I ALOGtest: RLOGI_IF:write INFO level to radio buffer
11-27 16:15:05.937 5885 5885 I ALOGtest: SLOGI:write INFO level to sytem buffer
11-27 16:15:05.938 5885 5885 I ALOGtest: SLOGI_IF:write INFO level to sytem buffer
11-27 16:15:05.938 5885 5885 F ALOGtest: ALOG:LOG_FATAL:write LOG_FATAL level to main buffer
Android log子系统也提供了通过属性来控制log级别的输出,格式如下
adb shell setprop log.tag.<TAG> <LEVEL>
LEVEL:
V
D
I
W
E
F
其中的TAG就是我们代码中设置的LOG_TAG
board:/ # setprop log.tag.ALOGtest F
board:/ # ALOGtest
11-27 16:18:10.801 5888 5888 F ALOGtest: ALOG:LOG_FATAL:write LOG_FATAL level to main buffer
board:/ # setprop log.tag.ALOGtest V
board:/ # ALOGtest
11-27 16:22:18.811 5891 5891 I ALOGtest: ALOGI:write INFO level to main buffer
11-27 16:22:18.812 5891 5891 I ALOGtest: ALOGI_IF:write INFO level to main buffer
11-27 16:22:18.812 5891 5891 I ALOGtest: RLOGI:write INFO level to radio buffer
11-27 16:22:18.812 5891 5891 I ALOGtest: RLOGI_IF:write INFO level to radio buffer
11-27 16:22:18.812 5891 5891 I ALOGtest: SLOGI:write INFO level to sytem buffer
11-27 16:22:18.812 5891 5891 I ALOGtest: SLOGI_IF:write INFO level to sytem buffer
11-27 16:22:18.812 5891 5891 F ALOGtest: ALOG:LOG_FATAL:write LOG_FATAL level to main buffer