Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Studio NDK 入門教程(4)--優雅的在C++中輸出Logcat

Android Studio NDK 入門教程(4)--優雅的在C++中輸出Logcat

編輯:關於Android編程

概述

本文講述如何通過android/log.h在native代碼中輸出logcat日志。

認識android/log.h

了解的最好方式就是直接看代碼,下面貼出其代碼,並對英文部分做中文注釋。

#ifndef _ANDROID_LOG_H
#define _ANDROID_LOG_H


 /*****************這段警告是針對所以android native庫的
 *  重要提示:
 *      這個文件是在Android NDK 1.5版本以上的一部分。
 *      如果在第三方源碼或二進制代碼中依賴此定義需要遵守:
 *      - 不要修改枚舉(除了你想新增一個32位的值)
 *      - 不要修改常量或者函數式宏
 *      - 不要改變方法的簽名
 *      - 不要改變結構體的前後順序或大小
 */

/* 支持Android內核程序將消息發送到日志緩沖區,稍後將可以在logcat浏覽日志。
 * 每一個日志必須包含
 *      - 一個優先級
 *      - 一個標簽
 *      - 一些文字
 * 標簽通常對應於發出日志消息的組件,應該小且合理。
 * 
 * 日志消息可能被特定實現截斷(例如:最大1023個字符)
 *
 * 如果日志消息沒有以"\n"結尾那麼將會自動追加。不可能出現多個日志在Logcat中被打印成一行。
 *
 * 請適度的使用LOGS
 *      - 發送日志消息吃CPU和減緩你的應用程序和系統。
 *      - 循環日志緩沖區很小(<64kb),發送很多消息可能推遲系統中剩下的其他重要的日志消息。
 *      - 在版本發布,只有發送日志消息來考慮異常情況。
 * 提示:這些方法必須實現/system/lib/liblog.so
 */


#include 

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Android日志優先級,升序排列 很容與Java中常見的日志等級V D I W E對應起來 
 */
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;

/*
 * 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,...)
 * 發送一個帶格式化的log,像printf一樣使用它
 */
int __android_log_print(int prio, const char *tag,  const char *fmt, ...)
/* 
 *如果是GNUC編譯器,這裡將會檢查format調用的正確性。下同。
 */
#if defined(__GNUC__)
    __attribute__ ((format(printf, 3, 4)))
#endif
    ;

/*
 * A variant of __android_log_print() that takes a va_list to list
 * additional parameters.
 * __android_log_print() 的一個變體,使用va_list代替可變參數
 */
int __android_log_vprint(int prio, const char *tag,
                         const char *fmt, va_list ap);

/*
 * Log an assertion failure and SIGTRAP the process to have a chance
 * to inspect it, if a debugger is attached. This uses the FATAL priority.
 * 日志斷言失敗和SIGTRAP過程有機會檢查它,如果一個調試器連接。這使用的是FATAL優先級。
 */
void __android_log_assert(const char *cond, const char *tag,
              const char *fmt, ...)    
#if defined(__GNUC__)
    __attribute__ ((noreturn))
    __attribute__ ((format(printf, 3, 4)))
#endif
    ;

#ifdef __cplusplus
}
#endif

#endif 

以上代碼由兩個注意點:1、使用__android_log_print()時可以像C語言中的printf一樣對輸出的字符串進行格式化。在實際應用中使用print函數較多。2、使用這個頭文件的時候必須包含log日志庫。

使用使用__android_log_print()打印日志

在編譯配置中添加log庫

如果你用的是正式版gradle,在ndk標簽中加入

ldLibs "log"
如果你用的是實驗版gradle,在ndk標簽中加入:

ldLibs.add("log")
如果你使用CMakeLists,在target_link_libraries標簽中加入log 如果你使用的是MK文件,加入如下語句:

LOCAL_LDLIBS := -llog

在代碼中使用

在代碼中包含頭文件include"android/log.h"
//打印一個簡單Info級別的日志 對應Java的Log.i("JNI","This is log")

__android_log_print(ANDROID_LOG_INFO,"JNI","This is log"); 

//打印格式化字符串 這裡使用的是C語言中printf中的格式。關於C中的printf格式化輸出可自行百度,文檔非常多。

int i=5;
__android_log_print(ANDROID_LOG_INFO,"JNI","i=%d",i); 

C語言printf格式化輸出詳解:http://blog.csdn.net/xuefu2008/article/details/4645026/

如何優雅的輸出日志

下面將通過C語言中的宏定義功能簡化日志輸出工具類。

//filename LogUtils.h
//
// Created by wastrel on 2016/4/7.
//



#include "android/log.h"

#ifndef LOG_TAG
    #define LOG_TAG "JNI"
#endif
#ifndef IS_DEBUG
    #define IS_DEBUG true
#endif

#define LOG_NOOP (void) 0
//__FILE__ 輸出文件名
//__LINE__ 輸出行數
//__PRETTY_FUNCTION__  輸出方法名
//可以按需選取 %s %u %s 分別與之對應
#define LOG_PRINT(level,fmt,...) __android_log_print(level,LOG_TAG,"(%s:%u) %s: " fmt,__FILE__,__LINE__,__PRETTY_FUNCTION__,##__VA_ARGS__)
//通過IS_DEBUG來控制是否輸出日志
#if IS_DEBUG
    #define LOGI(fmt,...) LOG_PRINT(ANDROID_LOG_INFO,fmt,##__VA_ARGS__)
#else
    #define LOGI(...) LOG_NOOP
#endif

#if IS_DEBUG
    #define LOGW(fmt,...) LOG_PRINT(ANDROID_LOG_WARN,fmt ,##__VA_ARGS__)
#else
    #define LOGW(...) LOG_NOOP
#endif

#if IS_DEBUG
    #define LOGD(fmt,...) LOG_PRINT(ANDROID_LOG_DEBUG,fmt ,##__VA_ARGS__)
#else
    #define LOGD(...) LOG_NOOP
#endif

#if IS_DEBUG
    #define LOGE(fmt,...) LOG_PRINT(ANDROID_LOG_ERROR,fmt ,##__VA_ARGS__)
#else
    #define LOGE(...) LOG_NOOP
#endif

#if IS_DEBUG
    #define LOGF(fmt,...) LOG_PRINT(ANDROID_LOG_FATAL,fmt ,##__VA_ARGS__)
#else
    #define LOGF(...) LOG_NOOP
#endif

新建一個LogUtils.h文件,拷貝以上代碼。然後在需要使用的cpp文件中include即可。

    #include"LogUtils.h"

    int func(int i)
    {
        LOGW("this is a warning");
        LOGE("i = %d",i);
    }
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved