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. 刷完了leetcode的数据库题目~

    很久很久很久之前,我上传了几条数据库题目,并没有坚持,今天跟新一下进度吧,其实没啥难度w(* ̄︶ ̄)

  2. jQuery 获取、设置表单元素的值

    获取表单元素值: 文本框,文本区域: $("#txt").attr("value"): 多选框 checkbox:$("#checkbox_id&qu ...

  3. Linux SSH隧道技术(端口转发,socket代理)

    动态转发(SOCKS5代理): 命令格式:ssh -D <local port> <SSH Server> ssh -fnND 0.0.0.0:20058 172.16.50. ...

  4. Ansible 小手册系列 八(Yaml 语法格式)

    YAML 语言(发音 /ˈjæməl/ )的设计目标,就是方便人类读写.它实质上是一种通用的数据串行化格式. 它的基本语法规则如下. • 大小写敏感 • 使用缩进表示层级关系 • 缩进时不允许使用Ta ...

  5. Ansible 小手册系列 三(命令介绍)

    仅仅只是介绍,可以选择跳过 ansible ansible是指令核心部分,其主要用于执行ad-hoc命令,即单条命令.默认后面需要跟主机和选项部分,默认不指定模块时,使用的是command模块. Us ...

  6. Sql server日期函数操作

    1.获取前一小时内的数据:DATEADD(HOUR,-1,GETDATE()),将"HOUR"替换成DAY,Month,YEAR就是前一天,前一月,前一年 2.获取日期部分,格式为 ...

  7. 【hive】子查询

    hive中是不支持子查询的 但是并不意味这不支持in 或者 not in in 或者not in 后边是定值的话是支持的 但是接定制是可以的 例如 select id from table not i ...

  8. python:打包成exe程序

    1.需要安装 py2exe 2.示例代码: #exetest.py #创建一个gui界面,只用一个标签和按钮,无功能 from Tkinter import * win = Tk() label = ...

  9. 032——VUE中表单控件处理之复选框的处理

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. SqlServer中存储过程 returnC#代码处理以及对应的MySQL如何改写

    一.SqlServer 中 1. 创建表 create table testuser( id int, --primary key, names ), address ), paw ) ) 2.创建存 ...