轻量级日志类Log

      Log在android应用开发中是使用频率非常高的一个类,在没有了解这个类之前都是使用System.out.println(),这个 是Java中的一个方法。
Log类定义了六个静态变量:
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;
    Log.v()、Log.d()、 Log.i()、 Log.w()、  Log.e() 首字母分别对应分VERBOSE(详细的),DEBUG(调试),INFO(信息), WARN(警告),ERROR(错误)。
从v到e,v总是会打印的,当发生错误时,e才会打印,v仍然会打印。ASSERT是为了让错误不要再报告而设置的,对应Log.wtf()方法。还有一个方法
是isLoggable(),通过这个方法可用日志的级别做设置,默认是Log.i(),当长度大于23时会抛出异常。这些方法是native方法。
在android源码的frameworks\base\core\jni下的android_util_Log.cpp文件中有相应的实现。

代码如下:
static jint android_util_Log_println_native(JNIEnv* env, jobject clazz,
        jint bufID, jint priority, jstring tagObj, jstring msgObj)
{
    const char* tag = NULL;
    const char* msg = NULL;

    if (msgObj == NULL) {
        jniThrowNullPointerException(env, "println needs a message");
        return -1;
    }

    if (bufID < 0 || bufID >= LOG_ID_MAX) {
        jniThrowNullPointerException(env, "bad bufID");
        return -1;
    }

    if (tagObj != NULL)
        tag = env->GetStringUTFChars(tagObj, NULL);
    msg = env->GetStringUTFChars(msgObj, NULL);

    int res = __android_log_buf_write(bufID, (android_LogPriority)priority, tag, msg);

    if (tag != NULL)
        env->ReleaseStringUTFChars(tagObj, tag);
    env->ReleaseStringUTFChars(msgObj, msg);
    }
    __android_log_buf_write位于Android源代码的system\core\liblog中的logd_write.c文件中。
int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
{
    struct iovec vec[3];
    char tmp_tag[32];

    if (!tag)
        tag = "";

    /* XXX: This needs to go! */
    if ((bufID != LOG_ID_RADIO) &&
         (!strcmp(tag, "HTC_RIL") ||
        !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
        !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
        !strcmp(tag, "AT") ||
        !strcmp(tag, "GSM") ||
        !strcmp(tag, "STK") ||
        !strcmp(tag, "CDMA") ||
        !strcmp(tag, "PHONE") ||
        !strcmp(tag, "SMS"))) {
            bufID = LOG_ID_RADIO;
            // Inform third party apps/ril/radio.. to use Rlog or RLOG
            snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
            tag = tmp_tag;
    }

    vec[0].iov_base   = (unsigned char *) &prio;//优先级
    vec[0].iov_len    = 1;
    vec[1].iov_base   = (void *) tag;       //tag标志
    vec[1].iov_len    = strlen(tag) + 1;
    vec[2].iov_base   = (void *) msg;     //msg 日志内容
    vec[2].iov_len    = strlen(msg) + 1;

    return write_to_log(bufID, vec, 3);
}
    从代码上看就是我们要调用的Log是带缓冲区的,接下来它自己又调用了不带缓冲区的。

static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;//初始化

__write_to_log_init接下来会调用内核提供的API

static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
{
#ifdef HAVE_PTHREADS
    pthread_mutex_lock(&log_init_lock);
#endif

    if (write_to_log == __write_to_log_init) {
        log_fds[LOG_ID_MAIN] = log_open("/dev/"LOGGER_LOG_MAIN, O_WRONLY);
        log_fds[LOG_ID_RADIO] = log_open("/dev/"LOGGER_LOG_RADIO, O_WRONLY);
        log_fds[LOG_ID_EVENTS] = log_open("/dev/"LOGGER_LOG_EVENTS, O_WRONLY);
        log_fds[LOG_ID_SYSTEM] = log_open("/dev/"LOGGER_LOG_SYSTEM, O_WRONLY);

        write_to_log = __write_to_log_kernel;

        if (log_fds[LOG_ID_MAIN] < 0 || log_fds[LOG_ID_RADIO] < 0 ||
                log_fds[LOG_ID_EVENTS] < 0) {
            log_close(log_fds[LOG_ID_MAIN]);
            log_close(log_fds[LOG_ID_RADIO]);
            log_close(log_fds[LOG_ID_EVENTS]);
            log_fds[LOG_ID_MAIN] = -1;
            log_fds[LOG_ID_RADIO] = -1;
            log_fds[LOG_ID_EVENTS] = -1;
            write_to_log = __write_to_log_null;
        }

        if (log_fds[LOG_ID_SYSTEM] < 0) {
            log_fds[LOG_ID_SYSTEM] = log_fds[LOG_ID_MAIN];
        }
    }

#ifdef HAVE_PTHREADS
    pthread_mutex_unlock(&log_init_lock);
#endif

    return write_to_log(log_id, vec, nr);
}
这样就成了文件IO操作了,原来打个日志还这么麻烦。

你可能感兴趣的:(android)