Android 实现自己的LOG信息
在程序开发过程中,log是广泛使用的用来记录程序执行过程的机制,它既可以用于程序调试,也可以用于产品运营中的事件记录。在android系统中,提供了简单、便利的log机制,开发人员可以方便地使用。在这一篇文章中,我们简单介绍在android内核空间和用户空间中log的使用和查看方法。
一. 内核开发时log的使用。android内核是基于linux kerne 2.36的,因此,linux kernel的log机制同样适合于android内核,它就是有名的printk,与c语言的printf齐名。与printf类似,printk提供格式化输入功能,同时,它也具有所有log机制的特点--提供日志级别过虑功能。printk提供了8种日志级别(<linux/kernel.h>):
#define kern_emerg "<0>" /* system is unusable */ #define kern_alert "<1>" /* action must be taken immediately */ #define kern_crit "<2>" /* critical conditions */ #deinfe kern_err "<3>" /* error conditions */ #deinfe kern_warning "<4>" /* warning conditions */ #deinfe kern_notice "<5>" /* normal but significant condition */ #deinfe kern_info "<6>" /* informational */ #deinfe kern_debug "<7>" /* debug-level messages */
printk的使用方法:
printk(kern_alert"this is the log printed by printk in linux kernel space.");
kern_alert表示日志级别,后面紧跟着要格式化字符串。
在android系统中,printk输出的日志信息保存在/proc/kmsg中,要查看/proc/kmsg的内容,参照android内核源码 在ubuntu上下载,编译,安装一文,在后台中运行模拟器:
user-name@machine-name:~/android$ emulator &
启动adb shell工具:
user-name@machine-name:~/android$ adb shell
查看/proc/kmsg文件:
root@android:/ # cat /proc/kmsg
二. 用户空间程序开发时log的使用。android系统在用户空间中提供了轻量级的logger日志系统,它是在内核中实现的一种设备驱动,与用户空间的logcat工具配合使用能够方便地跟踪调试程序。在android系统中,分别为c/c++ 和java语言提供两种不同的logger访问接口。c/c++日志接口一般是在编写硬件抽象层模块或者编写jni方法时使用,而java接口一般是在应用层编写app时使用。
android系统中的c/c++日志接口是通过宏来使用的。在system/core/include/android/log.h定义了日志的级别:
/* * android log priority values, in ascending priority order. */ typedef enum android_logpriority { android_log_unknown = 0, android_log_default, /* only for setminpriority() */ android_log_verbose, android_log_debug, android_log_info, android_log_warn, android_log_error, android_log_fatal, android_log_silent, /* only for setminpriority(); must be last */ } android_logpriority;
在system/core/include/cutils/log.h中,定义了对应的宏,如对应于android_log_verbose的宏logv:
/* * this is the local tag used for the following simplified * logging macros. you can change this preprocessor definition * before using the other macros to change the tag. */ #ifndef log_tag #define log_tag null #endif /* * simplified macro to send a verbose log message using the current log_tag. */ #ifndef logv #if log_ndebug #define logv(...) ((void)0) #else #define logv(...) ((void)log(log_verbose, log_tag, __va_args__)) #endif #endif /* * basic log message macro. * * example: * log(log_warn, null, "failed with error %d", errno); * * the second argument may be null or "" to indicate the "global" tag. */ #ifndef log #define log(priority, tag, ...) \ log_pri(android_##priority, tag, __va_args__) #endif /* * log macro that allows you to specify a number for priority. */ #ifndef log_pri #define log_pri(priority, tag, ...) \ android_printlog(priority, tag, __va_args__) #endif /* * ================================================================ * * the stuff in the rest of this file should not be used directly. */ #define android_printlog(prio, tag, fmt...) \ __android_log_print(prio, tag, fmt)
因此,如果要使用c/c++日志接口,只要定义自己的log_tag宏和包含头文件system/core/include/cutils/log.h就可以了:
#define log_tag "my log tag"
#include <cutils/log.h>
就可以了,例如使用logv:
logv("this is the log printed by logv in android user space.");
再来看android系统中的java日志接口。android系统在frameworks层中定义了log接口:
(frameworks/base/core/java/android/util/log.java):
................................................ public final class log { ................................................ /** * priority constant for the println method; use log.v. */ public static final int verbose = 2; /** * priority constant for the println method; use log.d. */ public static final int debug = 3; /** * priority constant for the println method; use log.i. */ public static final int info = 4; /** * priority constant for the println method; use log.w. */ public static final int warn = 5; /** * priority constant for the println method; use log.e. */ public static final int error = 6; /** * priority constant for the println method. */ public static final int assert = 7; ..................................................... public static int v(string tag, string msg) { return println_native(log_id_main, verbose, tag, msg); } public static int v(string tag, string msg, throwable tr) { return println_native(log_id_main, verbose, tag, msg + '\n' + getstacktracestring(tr)); } public static int d(string tag, string msg) { return println_native(log_id_main, debug, tag, msg); } public static int d(string tag, string msg, throwable tr) { return println_native(log_id_main, debug, tag, msg + '\n' + getstacktracestring(tr)); } public static int i(string tag, string msg) { return println_native(log_id_main, info, tag, msg); } public static int i(string tag, string msg, throwable tr) { return println_native(log_id_main, info, tag, msg + '\n' + getstacktracestring(tr)); } public static int w(string tag, string msg) { return println_native(log_id_main, warn, tag, msg); } public static int w(string tag, string msg, throwable tr) { return println_native(log_id_main, warn, tag, msg + '\n' + getstacktracestring(tr)); } public static int w(string tag, throwable tr) { return println_native(log_id_main, warn, tag, getstacktracestring(tr)); } public static int e(string tag, string msg) { return println_native(log_id_main, error, tag, msg); } public static int e(string tag, string msg, throwable tr) { return println_native(log_id_main, error, tag, msg + '\n' + getstacktracestring(tr)); } ..................................................................
因此,如果要使用java日志接口,只要在类中定义的log_tag常量和引用android.util.log就可以了:
private static final string log_tag = "my_log_tag";
log.i(log_tag, "this is the log printed by log.i in android user space.");
要查看这些log的输出,可以配合logcat工具。如果是在eclipse环境下运行模拟器,并且安装了android插件,那么,很简单,直接在eclipse就可以查看了:
如果是在自己编译的android源代码工程中使用,则在后台中运行模拟器:
user-name@machine-name:~/android$ emulator &
启动adb shell工具:
user-name@machine-name:~/android$ adb shell
使用logcat命令查看日志:
root@android:/ # logcat
这样就可以看到输出的日志了。
以上就是android 自己的log信息实现方法,有需要的朋友看下。
上一篇: 【LeetCode】初级专题-链表