Android Studio NDK开发
一直以来,在开发Android应用的过程中,时常需要接触许多使用C/C++编写的开源库,传统方式之前都是在虚拟机中使用ubuntu环境,或者Android源码环境编译成库之后,再拷贝到应用中来引用。最近发现使用Android Studio来进行NDK开发还是挺方便的,在此总结一下日常工作过程中使用Android Studio开发native应用相关的一些常见知识点,帮助自己系统性的巩固该方面的知识点,全文大纲如下:
目录
- Gradle文件配置
- cmake常见语法
- JNI的基本操作
- 官方手册地址
Gradle文件配置
模块支持NDK,需要在build.gradle中配置ndk以及cmake相关的参数,此处主要有两个点:
- 通过ndkVersion关键字配置ndk版本,ndk的版本号可以在sdk manager中查询,也可以在sdk的安装路径中,找到ndk文件夹,该目录下按照版本号存放了相关版本的ndk内容。
C:\Users\xxx\AppData\Local\Android\Sdk\ndk
- 指定的cmake工具,cmake工具的自定义可以在工程的local.properties文件中指定,关键字是
cmake.dir
,参数为cmake文件夹所在的绝对路径
sdk.dir=C\:\\Users\\xxx\\AppData\\Local\\Android\\Sdk
cmake.dir=C\:\\Users\\xxx\\AppData\\Local\\Android\\Sdk\\cmake\\3.17.2
- 配置cmake版本与解释文件路径,在模块的build.gradle文件中,与defaultConfig同级的目录下添加如下配置
externalNativeBuild {
cmake {
path "../CMakeLists.txt" //编译解释文件路径
version "3.17.2" //使用该版本的cmake
}
}
-
配置编译器参数, 在defaultConfig项中的externalNativeBuild项下添加cppFlags关键字可以用来配置编译器参数,如-fno-rtti 关闭运行时类型识别等
-
配置Cmake参数, 在defaultConfig项中的externalNativeBuild项下添加arguments关键字可以用来配置cmake参数,如-DCMAKE_BUILD_TYPE=Release等
相关配置文件如下所示:
defaultConfig {
applicationId ""
minSdk 21
targetSdk 30
versionCode 1
versionName "1.0"
//指定NDK版本
ndkVersion "23.0.7599858"
externalNativeBuild {
cmake {
//指定编译的CPU架构类型
abiFilters "arm64-v8a"
//配置编译器参数
cppFlags '-DANDROID','-fno-rtti','-s','-Os'
//配置CMake参数,gradle中配置arugments后,可以直接在
//cmakelists.txt中使用${CMAKE_BUILD_TYPE}获取该值
arguments "-DCMAKE_BUILD_TYPE=Release"
}
}
}
externalNativeBuild {
cmake {
path "../CMakeLists.txt" //编译解释文件路径
version "3.17.2" //使用该版本的cmake
}
}
cmake常见语法
- 添加子工程编译
命令:add_subdirectory
语法:add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
例子:add_subdirectory(子文件夹cmakelist.txt所在的文件夹路径)
具体场景: 我们在开发app的过程中,可能会存在多个不同功能模块的cpp工程,各个模块分开开发,各自管理编译,因此可以在项目的跟目录新建一个cmakelist.txt文件来包含这些子工程,用于apk的统一编译。 如下:
其中根目录的CMakeLists.txt中需要做一些属性值初始化,工程配置相关的逻辑,包含子工程的逻辑如下:
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.10.2)
# Declares and names the project.
project("CMakeDemo")
message(WARNING ========= start ============)
add_subdirectory(cpp_project)
add_subdirectory(cpp_project1)
add_subdirectory(app/src/main/cpp/)
message(WARNING ========= end ============)
- 引入第三方库
引入系统库
命令:find_library
语法:find_library (
<VAR>
name | NAMES name1 [name2 ...] [NAMES_PER_DIR]
[HINTS path1 [path2 ... ENV var]]
[PATHS path1 [path2 ... ENV var]]
[PATH_SUFFIXES suffix1 [suffix2 ...]]
[DOC "cache documentation string"]
[NO_DEFAULT_PATH]
[NO_CMAKE_PATH]
[NO_CMAKE_ENVIRONMENT_PATH]
[NO_SYSTEM_ENVIRONMENT_PATH]
[NO_CMAKE_SYSTEM_PATH]
[CMAKE_FIND_ROOT_PATH_BOTH |
ONLY_CMAKE_FIND_ROOT_PATH |
NO_CMAKE_FIND_ROOT_PATH]
)
例子:find_libraray(log-lib log) //从编译链的环境中查找log库, 对应查找的路径
${CMAKE_SYSROOT}/${CMAKE_SYSTEM_LIBRARY_PATH}
引入第三方库(不在系统环境中)
第一步:获取第三方库所在路径,如下图所示,根目录工程中的bin文件夹下存在动态与静态两个库,
在根目录的cmakelists.txt中手动配置如下代码
set(DYNAMIC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin/dynamic)
set(STATIC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin/static)
set(CMAKE_LIBRARY_PATH ${DYNAMIC_PATH} ${STATIC_PATH})
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
然后我们在子工程中,即可像引用系统库一样的引用第三方的库了
=============================================================
cmake_minimum_required(VERSION 3.10.2)
# Declares and names the project.
project("cpp_project")
message(WARNING >>>>>>>>>>>>>>> cpp_project)
//查找依赖的库
find_library(log-lib log)
find_library(dynamic-lib test_dynamic)
find_library(static-lib test_static)
//链接库
target_link_libraries(cpp_project dynamic-lib static-lib log)
- 设置输出路径
修改可执行文件的输出路径
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "输出路径")
修改库文件的输出路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "输出路径")
CMAKE_RUNTIME_OUTPUT_DIRECTORY,CMAKE_LIBRARY_OUTPUT_DIRECTORY都是cmake工具中自带的属性值,默认情况下,输出路径在工程的app\build\intermediates\cmake\debug\obj${cpu-abi} 中
- 设置产物文件格式
编译成库文件(动态库,静态库,插件)
add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
source1 [source2 ...])
编译成可执行文件
add_executable(<name> [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
source1 [source2 ...])