点击浏览 官网说明 (要翻墙)
安装插件
需要打开SDK Manager
菜单栏 Tools>Android>SDK Manager
点击切换到 SDK Tools 选项卡
勾选 LLDB、CMake、NDK 进行安装 如下图
当安装后,会在sdk目录下多出三个目录:cmake、lldb、ndk-bundle
建立支持c/c++的工程
新建工程时,勾选『include C++ Support』如下图
然后进行正常的向导选择,当进行到尾页出现:
上面下拉列表选择c++标准,下面复选框分别表示,是否需要支持异常处理机制 及 运行时类型识别(RTTI)
然后点击Finish 生成工程
下图是默认标准生成的工程,自动新增了一个cpp目录及目录下的默认.cpp文件
并在app/ 下新增了一个 CMakeLists.txt 文件,放入group-> External Build Files
在build.gradle中, defaultConfig配置下 添加了一个名为 externalNativeBuild配置
下图是使用c++11标准,并勾选了两个support选项后的工程视图:
与上图的区别是 在externalNativeBuild配置下的 cppFlags 赋值了
生成的文件与工程
当在创建工程时,选择创建一个默认Activity时,会生成一段简单的c++函数在native-lib.cpp文件中,
名为stringFromJNI()。
构建脚本在CMakeLists.txt中:
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds it for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
# Associated headers in the same location as their source
# file are automatically included.
src/main/cpp/native-lib.cpp )
# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
里面配置了库的名字、源文件位置、添加log-lib、链接lib等
运行后,生成的so文件在 <project-path>/app/build/ intermediates/ cmake/debug/obj/ 下
如果想分析apk文件:Build>Analyze然后会弹出一个选择文件对话框,默认选择当前工程的apk,
当然也可以选择其他apk,选定后如下图:
将C / C ++代码添加到现有项目
1. 创建新的本地源文件,并添加到项目中。如果已经有本地代码或要导入预建的本地库,可以跳过这一步2. 创建CMake的构建脚本。如果你已经有一个现有的本地库及CMakeLists.txt构建脚本,或者使用ndk-build,
并包括一个Android.mk的构建脚本,你可以跳过这一步
3. Gradle与提供了CMake或ndk-build脚本的本地库进行关联。Gradle使用构建脚本导入源代码到studio项目,
并将要地库(so文件)打包进apk中
创建新的本地源文件
创建cpp目录与源文件,步骤如下:
>在moudle>src>main 右键new 一个目录,比如名为cpp
>在目录上右键new c/c++ Source file,可以勾选同时创建头文件
创建CMake的构建脚本
> 该脚本必须是一个纯文本文件,且命名为CMakeLists.txt
> 可以创建在项目中的任何位置,脚本中的源文件、本地库的路径是相对于当前构建文件的
> 脚本命令 :
#最小需要的cmake版本
cmake_minimum_required(VERSION 3.4.1)
add_library(
#定义库的名字
native-lib
#声明为共享库
SHARED
#源文件路径
src/main/cpp/native-lib.cpp
#为了让CMake定位到头文件,可以指定头文件的目录
include_directories(src/main/cpp/include/)
)
可以使用多个add_library()命令:添加其它一些源文件,定义额外的库供CMake脚本来构建
>生成的so库名为:lib[库名].so,如上配置即生成:libnative-lib.so
在java代码中加载这个库时,只需要使用CMake中定义的库名:
static {
System.loadLibrary(“native-lib”);
}
注:如果从CMake构建脚本中重命名或移除了一个库,那就需要清理一个工程:Build>Clean Project
添加 NDK APIs
安卓NDK提供了一些有用的native APIs,可以在CMakeLists.txt进行添加> find_library()命令,来定位一个NDK库,并存储它的路径到一个变量中。
下面的例子演示了 定位Android-specific log support library (点击该串英文跳转到 安卓每个Api Level所对应新增支持的NDK libs
页面,类似LOCAL_LDLIBS := -lGLESv1_CM 即表示库名为GLESv1_CM;
而log库是 LOCAL_LDLIBS := -llog
),
并将其路径添加到变量log-lib中
find_library( # Defines the name of the path variable that stores the
# location of the NDK library.
log-lib
# Specifies the name of the NDK library that
# CMake needs to locate.
log )
> target_link_libraries()命令,为了在本地库使用NDK库,需要使用该命令进行链接
find_library(...)
# Links your native library against one or more other native libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the log library to the target library.
${log-lib} )
> 添加NDK源文件到本地库。比如NDK的路径保存在环境变量ANDROID_NDK中:
使用add_library命令添加源文件,并使用target_link_libraries命令进行链接
add_library( app-glue
STATIC
${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c )
# You need to link static libraries against your shared native library.
target_link_libraries( native-lib app-glue ${log-lib} )
添加其他预编译库
> 由于预编译库已经构建好了,你只需要引入即可,如下引入一个名为imported-lib 的库,使用了IMPORTED标识:
add_library( imported-lib
SHARED
IMPORTED )
> set_target_properties命令 指定库的路径
一些库,在不同的cpu架构上,生成了针对性的so库文件。
可以使用环境变量ANDROID_ABI ,它使用一个NDK支持的默认ABI列表,
也可以使用gradle里手动配置的abi过滤列表中的项(关于配置列表见下文:gradle中指定ABIs)
add_library(...)
set_target_properties( # Specifies the target library.
imported-lib
# Specifies the parameter you want to define.
PROPERTIES IMPORTED_LOCATION
# Provides the path to the library you want to import.
imported-lib/src/${ANDROID_ABI}/libimported-lib.so )
> include_directories命令 指定头文件位置
同样为了在编译时找到头文件,可以使用
include_directories( imported-lib/include/ )
注:当你想打包一个预编译库,且它不需要在构建时被你的库所依赖,那么即使它依赖了imported-lib库,也不需要执行以下的链接命令
> target_link_libraries命令,链接预编译库和本地库
target_link_libraries( native-lib imported-lib app-glue ${log-lib} )
Gradle关联本地库
界面操作
在一个新的moudle中,右键moudle-name,点击『Link C++ Project with Gradle』
选择构建系统是Cmake还是ndk-build,然后选择对应的某一本库的构建文件
Cmake 对应CMakeLists.txt
ndk-build 对应Android.mk
点击ok
在moudle下的build.gradle中添加externalNativeBuild{} (studio2.2后会自动生成)
android {
...
defaultConfig {...}
buildTypes {...}
// Encapsulates your external native build configurations.
externalNativeBuild {
// Encapsulates your CMake build configurations.
cmake {
// Provides a relative path to your CMake build script.
path "CMakeLists.txt"
}
}
}
这里添加的是Cmake脚本,如果是nkd-build脚本
externalNativeBuild {
ndkBuild{
path "Android.mk"
}
}
指定可选配置
可以在module级的build.gradle中defaultConfig{}下添加externalNativeBuild{}的可选配置
当然也可以添加在某一个或多个 product flavor (即渠道)中
比如,使用了CMake或ndk-build构建的工程中,定义了多个本地库,而在product flavor只使用一个库,
可以使用targets属性来配置:
android {
...
defaultConfig {
...
// This block is different from the one you use to link Gradle
// to your CMake or ndk-build script.
externalNativeBuild {
// For ndk-build, instead use ndkBuild {}
cmake {
// Passes optional arguments to CMake.
arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang"
// Sets optional flags for the C compiler.
cFlags "-D_EXAMPLE_C_FLAG1", "-D_EXAMPLE_C_FLAG2"
// Sets a flag to enable format macro constants for the C++ compiler.
cppFlags "-D__STDC_FORMAT_MACROS"
}
}
}
buildTypes {...}
productFlavors {
...
demo {
...
externalNativeBuild {
cmake {
...
// Specifies which native libraries to build and package for this
// product flavor. If you don't configure this property, Gradle
// builds and packages all shared object libraries that you define
// in your CMake or ndk-build project.
targets "native-lib-demo"
}
}
}
paid {
...
externalNativeBuild {
cmake {
...
targets "native-lib-paid"
}
}
}
}
// Use this block to link Gradle to your CMake or ndk-build script.
externalNativeBuild {
cmake {...}
// or ndkBuild {...}
}
}
注:要学习配置product flavors和构建变量,请转向ABIs the NDK supports
要学习配置Cmake变量,请转向Using CMake Variables
指定ABIs
默认情况下,生成的.so文件含ABIs the NDK supports 所支持的所有ABIs。如果仅想支持几项,可如下配置:
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {...}
// or ndkBuild {...}
}
ndk {
// Specifies the ABI configurations of your native
// libraries Gradle should build and package with your APK.
abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a',
'arm64-v8a'
}
}
buildTypes {...}
externalNativeBuild {...}
}
如果想控制生成多种ABI,又仅想把其中几个ABI生成的so打包进apk中,那么可以在
defaultConfig.externalNativeBuild.cmake {}
(以ndk-build构建的,则在defaultConfig.externalNativeBuild.ndkBuild {}) 下再添加一个abiFilters标识
只有defaultConfig.ndk{abiFilters }配置的abi才会打包进Apk中
如果想为每一种ABI生成单独的apk,参见 configuring ABI APK splits
例如
android {
...
splits {
// Configures screen ABI split settings
abi {
// Enable ABI APK splits
enable true
// By default all ABIs are included, so use reset() and include to specify that we only
// want APKs for x86, armeabi-v7a, and mips
// Resets the list of ABIs that Gradle should create APKs for to none
reset()
// Specifies a list of ABIs that Gradle should create APKs for
include "x86", "armeabi-v7a", "mips"
// Specify that we do not want to also generate a universal APK that includes all ABIs
universalApk false
}
}
}