相关的博客
在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