zoukankan      html  css  js  c++  java
  • Android中关于JNI 的学习(五)在C文件里使用LogCat

    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中看到以下的记录:


    这说明了,在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++中去调试我们的程序了。

    结束。


  • 相关阅读:
    Redis面试题
    spring boot错误: 找不到或无法加载主类
    JAVA的高并发编程
    Redis多机多节点集群实验
    Redis单机多节点集群实验
    Redis集群概述
    Redis的持久化之AOF方式
    Redis的持久化之RDB方式
    Redis持久化介绍
    Redis Keys的通用操作
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10003724.html
Copyright © 2011-2022 走看看