Android Studio NDK 入门教程--优雅的在C++中输出Logcat
Posted Wastrel_xyz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Studio NDK 入门教程--优雅的在C++中输出Logcat相关的知识,希望对你有一定的参考价值。
概述
本文讲述如何通过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 <stdarg.h>
#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);
以上是关于Android Studio NDK 入门教程--优雅的在C++中输出Logcat的主要内容,如果未能解决你的问题,请参考以下文章
Android Studio NDK 入门教程--优雅的在C++中输出Logcat
Android Studio NDK 入门教程--JNI动态注册本地方法
Android Studio NDK 入门教程--Java与C++之间的类型签名
Android Studio NDK 入门教程--Java对象的传递与修改