Log是开发过程中。对于我们调试程序非常重要的一个工具,有非常多时候,我们正是通过Log才干够看清楚程序是不是真的依照我们想像中的模式在跑,从而定位到问题所在的地方。而在Android开发中,毫无疑问,要是没有了logcat。我们调试程序的时候,就会痛苦死。

在NDK的开发中,虽然我们是利用C/C++来开发程序的,然后通过载入共享库的方法来调用C/C++程序,Android也提供了一套方法。能够让我们在LogCat中看到在C/C++代码中的数据流向,帮我们定位问题。

这一篇文章就简单地来说一下。怎样在JNI层使用log工具。

回到我们之前的demo中。我们在程序中为了查看在JNI层某个数的值是否被改变了,我们特意加入了以下的log:

	LOGI("before change testval = %d", val);
val = val + 1;
LOGI("after change testval = %d", val);

当程序在手机上执行的时候,我们就能够在LogCat中看到以下的记录:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlubWlhbnNoZW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />

这说明了,在C/C++中相同是能够利用log工具来调试的(事实上这是废话,由于Android中Log的实现本来就是通过JNI层。由C++实现的。)

以下我们就来说一下,怎样在C/C++文件里加入log吧。

1)在C/C++文件里。要加入log的引用文件,如以下第2行:

#include "com_lms_jni_ParamTransferTest.h"
#include <android/log.h>
#include <jni.h>

在这里,我们会引用android/log.h头文件,而log.h头文件定义了几个log函数,例如以下:

/*
* Send a simple string to the log.
*/
int __android_log_write(int prio, const char *tag, const char *text); /*
* Send a formatted string to the log, used like printf(fmt,...)
*/
int __android_log_print(int prio, const char *tag, const char *fmt, ...)
#if defined(__GNUC__)
__attribute__ ((format(printf, 3, 4)))
#endif
; /*
* A variant of __android_log_print() that takes a va_list to list
* additional parameters.
*/
int __android_log_vprint(int prio, const char *tag,
const char *fmt, va_list ap);

2)引入log.h头文件之后,我们能够在C/C++中直接使用__android_log_print方法,只是老这样使用,就太麻烦了,所以我们能够又一次定义一下。例如以下:

#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

在这里,我们定义了LOGD和LOGI 可变參数宏,分别相应不同级别的__andoid_log_print函数。这样我们在代码中,就能够直接通过LOGD和LOGI来写入log信息了。

在log.h头文件里,我们能够查到LOG相应的级别信息,例如以下:

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;

3)接下来。就是怎样使用LOGI或者LOGD了。例如以下,在程序中须要写入log的地方,调用函数:

JNIEXPORT void JNICALL Java_com_lms_jni_ParamTransferTest_changeTestVal
(JNIEnv * env, jobject obj){
jclass clazz = (*env)->GetObjectClass(env,obj);
jint val = (*env)->GetStaticIntField(env, clazz,
(*env)->GetStaticFieldID(env, clazz,"testval","I"));
LOGI("before change testval = %d", val);
val = val + 1;
LOGI("after change testval = %d", val);
(*env)->SetStaticIntField(env, clazz,(*env)->GetStaticFieldID(env, clazz,"testval","I"),val);
}

4)到这一步。在C/C++中的使用就结束了,可是JNI的使用一般都是通过编译成共享库的形式,所以我们还须要在Android.mk文件里指定相应的库文件,例如以下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := com_lms_jni_HwDemo

LOCAL_SRC_FILES := \
HwDemo.c \
JniTest.c \
ParamTransferTest.c LOCAL_LDLIBS += -llog include $(BUILD_SHARED_LIBRARY)

当中,我们能够看到 LOCAL_LDLIBS += -llog,在这里。LOCAL_LDLIBS 是告诉编译器,在编译这个共享库的时候,我们要去链接系统库中某一个库。而-llog,事实上就是代表

liblog库的意思,-l是表明lib,而log则是表明前缀是lib的liblog的库。跟LOCAL_MODULE一样。编译器和链接器会自己主动处理前缀lib跟后缀.so,而liblog.so这个库就是在ndk提供的系统库中。例如以下:

5)通过这几步。我们就能够像在Android调试一样,在C/C++中去调试我们的程序了。

结束。

Android中关于JNI 的学习(五)在C文件里使用LogCat的更多相关文章

  1. Android中关于JNI 的学习(零)简单的样例,简单地入门

    Android中JNI的作用,就是让Java可以去调用由C/C++实现的代码,为了实现这个功能.须要用到Anrdoid提供的NDK工具包,在这里不讲怎样配置了,好麻烦,配置了好久. . . 本质上,J ...

  2. Android中关于JNI 的学习(三)在JNI层訪问Java端对象

    前面两篇文章简介了JNI层跟Java层的一些相应关系,包含方法名,数据类型和方法名称等,相信在理论层面.可以非常好地帮助我们去了解JNI在Native本地开发中的作用,对JNI的一些概念也有了一个初步 ...

  3. Android中关于JNI 的学习(四)简单的样例,温故而知新

    在第零篇文章简单地介绍了JNI编程的模式之后.后面两三篇文章,我们又针对JNI中的一些概念做了一些简单的介绍,也不知道我究竟说的清楚没有.但相信非常多童鞋跟我一样.在刚開始学习一个东西的时候,入门最好 ...

  4. Android中关于JNI 的学习(六)JNI中注冊方法的实现

    在前面的样例中,我们会发现,当在Java类中定义一个方法的时候,例如以下: public class ParamTransferTest { public static int testval = 1 ...

  5. Android中关于JNI 的学习(一)对于JNIEnv的一些认识

    一个简单的样例让我们初步地了解JNI的作用.可是关于JNI中的一些概念还是需要了解清楚,才干够更好的去利用它来实现我们想要做的事情. 那么C++和Java之间的是怎样通过JNI来进行互相调用的呢? 我 ...

  6. Android中的SQLite使用学习

    Android中的SQLite使用学习 SQLite是非常流行的嵌入式关系型数据库,轻载, 速度快,而且是开源.在Android中,runtime提供SQLite,所以我们可以使用SQLite,而且是 ...

  7. android中使用jni对字符串加解密实现分析

    android中使用jni对字符串加解密实现分析 近期项目有个需求.就是要对用户的敏感信息进行加密处理,比方用户的账户password,手机号等私密信息.在java中,就对字符串的加解密我们能够使用A ...

  8. 深入理解Android(5)——从MediaScanner分析Android中的JNI

    前面几篇介绍了Android中的JNI和基本用法,这一篇我们通过分析Android源代码中的JNI实例,来对JNI部分做一个总结. 一.通向两个不同世界的桥梁 在前面我们说过,JNI就像一个桥梁,将J ...

  9. 深入理解Android(2)——理解Android中的JNI(中)

    阳光小强参加了CSDN博客之星评选,如果你觉得阳光小强的博客对你有所帮助,为小强投上一票吧:http://vote.blog.csdn.net/blogstar2014/details?usernam ...

随机推荐

  1. Knockout结合Bootstrap创建动态UI--产品列表管理

    本篇文章结合Bootstrap创建一个比较完整的应用,对产品列表进行管理,包括产品的增加.删除.修改. 需要的引用 <script type='text/javascript' src='htt ...

  2. request.getPathInfo() 方法的作用

    request.getPathInfo(); 这个方法返回请求的实际URL相对于请求的serlvet的url的路径.(个人理解.) 比如,有一个Servlet的映射是这样配置的: <servle ...

  3. LNMP的搭建与原理

    常见的web框架结构:例如:lnmp和:ampL=LINUX N=NGINX A=APACHE P=php T=Tomcat lnmp的原理 在LNMP组合工作时,首先是用户通过浏览器输入域名请求Ng ...

  4. 通过网页或Serverice远程系统网站(服务)所在服务器本地的应用程序(未成功)

    近日接了一个奇葩需求,内容如题. 实现过程中遇到一些问题,特将实现过程记录于此,供备忘及参考. 首先尝试了正常启动进程的方法,代码如下: public string RunSPApp() { Proc ...

  5. jinfo用法说明

    以下几种用法 -flags pid :打印当前VM的参数 -flag <name> pid:打印指定JVM的参数值 -flag [+|-]<name> pid:设置指定JVM参 ...

  6. SQL Server里查询表结构命令

    现提供两条命令查询表结构: 1.sp_help table_name;           如: [sql] sp_help Student;     2.sp_columns table_name; ...

  7. 圣诞节为大家推荐一些学习java书籍

    怎样学习才能从一名Java初级程序员成长为一名合格的架构师,或者说一名合格的架构师应该有怎样的技术知识体系,这是不仅一个刚刚踏入职场的初级程序员也是工作一两年之后开始迷茫的程序员经常会问到的问题 初级 ...

  8. PHP语法笔记二

    日期函数 date_default_timezone_set(“PRC”):时区设置为中国区 date(“日期格式”[,时间戳]):设置当前或某个时间戳的日期格式. 参数 format 表示时间格式化 ...

  9. js之放大镜效果

      HTML: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  10. 【剑指offer】把二叉树打印成多行,C++实现

    原创文章,转载请注明出处! 本题牛客网地址 博客文章索引地址 博客文章中代码的github地址 1.题目       从上到下按层打印二叉树,同一层结点从左至右输出,每一层输出一行.例如:下面二叉树的 ...