NDK学习笔记:AndroidStudio NDK 日志输出 & 断点调试
一、 Why I need log&debug ?
在我们正常的开发过程中,业务调整必须依靠日志的输出;出现非业务逻辑的异常状况,我们就必须靠断点调试来排查问题。so,我们在NDK开发,怎样设置合理的日志和调试功能呢?以下提供给大家,方便大家提高开发效率。
二、日志 log_common.h
#ifndef LOG_COMMON_H
#define LOG_COMMON_H
#include <android/log.h>
#include <string.h>
#define DEBUG //注释这行define,就可以一键关闭LOG的输出
// Windows 和 Linux 这两个宏是在 CMakeLists.txt 通过 ADD_DEFINITIONS 定义的
#ifdef Windows
#define __FILENAME__ (strrchr(__FILE__, '\\') + 1) // Windows下文件目录层级是'\\'
#elif Linux
#define __FILENAME__ (strrchr(__FILE__, '/') + 1) // Linux下文件目录层级是'/'
#else
#define __FILENAME__ (strrchr(__FILE__, '/') + 1) // 默认使用这种方式
#endif
#ifdef DEBUG
#define TAG "JNI"
#define LOGV(format, ...) __android_log_print(ANDROID_LOG_VERBOSE, TAG,\
"[%s][%s][%d]: " format, __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#define LOGD(format, ...) __android_log_print(ANDROID_LOG_DEBUG, TAG,\
"[%s][%s][%d]: " format, __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#define LOGI(format, ...) __android_log_print(ANDROID_LOG_INFO, TAG,\
"[%s][%s][%d]: " format, __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#define LOGW(format, ...) __android_log_print(ANDROID_LOG_WARN, TAG,\
"[%s][%s][%d]: " format, __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#define LOGE(format, ...) __android_log_print(ANDROID_LOG_ERROR, TAG,\
"[%s][%s][%d]: " format, __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define LOGV(format, ...) ;
#define LOGD(format, ...) ;
#define LOGI(format, ...) ;
#define LOGW(format, ...) ;
#define LOGE(format, ...) ;
#endif // DEBUG
#endif //LOG_COMMON_H
JNI 层的 Android Console Log 方法大家应该都有所了解,但是我们一般不会直接使用原生的接口,而是做一层简单的封装。为了扩展至windows平台,我简单的做了动态宏的编译开关,在CMake编译脚本加上如下语句:
IF (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Windows")
ADD_DEFINITIONS(-DWindows)
ELSE (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Linux")
ADD_DEFINITIONS(-DLinux)
ENDIF ()
其实不加也行,默认就是用LInux的,就是告诉大家有这么一回事。至于方法的使用也就贴个示例吧,不多说了。。。
#include "log_commmon.h"
LOGD("hello world");
LOGI("%s", "hello world");
LOGW("%s : %d", "year", 20);
int err_code = -1;
LOGW("%s : %d", "error!", err_code);
三、断点调试
日志可以帮我们解决大部分业务逻辑的繁杂问题,但是有时候我们会出现非业务逻辑的程序bug,这些bug只能依靠动态的断点调试方能找到解决方案。那么我们在NDK开发c/c++的过程中要怎样才能断点调试呢?下面就教大家:
下载NDK调试工具LLDB。在AS依次打开Tools -> Android -> SDKManager,然后在选项卡选择SDK Tools,勾选LLDB。
成功下载安装成功之后(最好重启一下),我们就开始正式配置断点调试的开关。
1、到对应模块的build.gradle,配置android标签节点下的buildTypes
buildTypes {
debug {
jniDebuggable true
jniDebuggable = true
}
}
2、配置AndroidManifest的Application属性:android:debuggable=“true” (release的时候记得取消掉)
<application
android:name="org.zzrblog.ZzrApplication"
android:debuggable="true"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
</application>
3、最后一步,也是最关键的一步。配置Run/Debug configurations
在哪配置这个东东? 看右图
然后跟着下图的1~2~3走起。
1、增加一个新的配置项,命名ndk-debug
2、到Genreral选项卡 -> Deployment Target Options -> USB Device(建议真机调试)
3、Debugger选项卡 -> Debug type -> Native
4、Apply -> OK
OK!以上配置搞定之后就能在我们编写的c/c++代码进行断点调试了,运行加载程序的时候,记得要选用新配置的ndk-debug作为启动项。(不行就重启一下)