在Android核心库中使用Log相关函数

相关的博客

在Blog中搜索到了两个相关的文章,一个是来自 csdn 的Blog,里面介绍了如何通过jni来添加相应的log 函数,但是写的十分的杂乱,实际上测试也不是很成功。

另外一个Blog是 yuan1590 的Blog,这里记录了如何成功的调用Log函数,但是这里Log函数只能是类的私有函数, 对不同的核心库log需要添加不同的类。这对调试工作增加了难度。

补充的内容

在这个Blog中,我根据Android 4.4的源代码提供了完整的添加Log函数的方法。这些方法是public方法,可以在任意 核心库中复用。在这个工具的帮助下,我们可以顺利的调试本地核心库。

原理

Android中,有一套完善的Log系统,使用Log系统,我们可以顺利的调试Android的应用。但是在调试Android核心库的时候, 却不能得到Android Log系统的支持。其实,Android的Log系统是通过本地库中的相关函数来实现的。把相应的内容写入Log文件中, 就实现了Log日志的写入。

通过在一个类中,添加一个新的Log函数,比如File.Log。然后通过jni实现对本地Log函数的调用。从而在核心库中,写入Android的Log文件。

实施步骤

  • 修改本地代码

    首先修改libcore/luni/src/main/native/java_io_File.cpp:

    /*
     - In class android.util.Log:
     - public static native int println_native(int buffer, int priority, String tag, String msg)
     */
    static jint File_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;
        }
    
        clazz = clazz;
    
        if (tagObj != NULL)
            tag = env->GetStringUTFChars(tagObj, NULL);
        msg = env->GetStringUTFChars(msgObj, NULL);
    
        int res = __android_log_buf_write(bufID, priority, tag, msg);
    
        if (tag != NULL)
            env->ReleaseStringUTFChars(tagObj, tag);
        env->ReleaseStringUTFChars(msgObj, msg);
    
        return res;
    }
    

    这里,我们加入了一个新的函数,叫做File_println_native,这个函数会成为C++中的Log函数与Java中Log函数的桥梁。这个 会调用Android的Log函数生成Log。要使这个函数能被jni调用,需要在JNI注册函数中,注册我们新添加的这个函数。

    修改static JNINativeMethod gMethods[]数组,添加我们函数的信息:

    NATIVE_METHOD(File, println_native, "(IILjava/lang/String;Ljava/lang/String;)I")
    

    这里,File是我们的类名称,println_native是我们的函数名。后面的字符串是函数的接口。

    添加头文件

    要记得在这个cpp文件中,加入对cutils/log.h的引用,就是在CPP的开头,添加一行:

    #include "cutils/log.h"
    
  • 添加公共函数

    在libcore/luni/src/main/java/java/io/File.java中,加入如下函数:

    /**
    - Log function in core libraray
    */
    private static native int println_native(int bufID,
                   int priority, String tag, String msg);
    
    private static final int LOG_ID_MAIN = 0;
    private static final int DEBUG = 3;
    
    /**
    - @hide
    */
    public static int Log(String tag, String msg) {
      return println_native(LOG_ID_MAIN, DEBUG, tag, msg);
    }
    

    注意到那个Public方法中的 @hide ,这样就让Android文档生成不自动索引。这个就解决了之前 yuan1590 提到的,这个方法不能是公有方法的问题。

  • 实施效果

    我修改了一下Socket的相关文件,在应用访问网络的时候输出log,可以在Log中看到如下内容:

    D/Network (  781 ): NetWork Access Bytes: 268
    D/Network (  781 ): NetWork Access Bytes: 485
    D/Network (  781 ): NetWork Access Bytes: 950
    

Comments !

blogroll

social