Android推荐使用的NDK构建工具,从AS 2.2版本之后开始支持(包含2.2版本)
相关环境
- 操作系统mac
- Android Studio 4.0
环境搭建
在SDK Tools中安装NDK开发环境(Tools > SDK Manager > Appearance & Behavior > System Settings > Android SDK > SDK Tools)
选择NDK,CMake进行安装。
快捷工具配置
生成头文件快捷工具配制-javah-jni
Tools > External Tools选项,点击【+】按钮添加生成jni头文件以及ndk-build命令的快捷工具:
- Name:javah-jni
工具名称
- Program:
$JDKPath$/bin/javah
javah所在的路径,$JDKPath$
代表在环境变量中配置的JDK路径。
-
Parameters:
-jni -encoding UTF-8 -d $ProjectFileDir$/app/src/main/cpp/include $FileClass$
命令参数:-jni代表生成JNI样式的标头文件,文件名为当前包名+类名($FileClass$) -encoding代表编码格式为UTF-8 -d代表指定头文件的输出路径为jni目录($ProjectFileDir$/app/src/main/cpp/include )
Working directory:
$SourcepathEntry$
工作目录:$SourcepathEntry$为当前module的路径
javah用法:
javah [options]
其中, [options] 包括:
-o 输出文件 (只能使用 -d 或 -o 之一)
-d 输出目录
-v -verbose 启用详细输出
-h --help -? 输出此消息
-version 输出版本信息
-jni 生成 JNI 样式的标头文件 (默认值)
-force 始终写入输出文件
-classpath 从中加载类的路径
-cp 从中加载类的路径
-bootclasspath 从中加载引导类的路径
是使用其全限定名称指定的
(例如, java.lang.Object)。
NDK开发
这里以普通项目来进行编写(当然我们也可以采用Android Studio 自带创建C++项目来实现)。
创建 JniTest.java文件
package com.iblogstreet.myapplication;
/**
* @author junwang
* @date 2020/12/17 3:20 PM
*/
public class JniTest {
public native String java2C();
static {
System.loadLibrary("native-lib");
}
}
首先加载native-lib库,其中定义java2C方法。
生成头文件
选中JniTest文件,右键,选择External Tools > javah-jni,生成头文件com_iblogstreet_myapplication_JniTest.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_iblogstreet_myapplication_JniTest */
#ifndef _Included_com_iblogstreet_myapplication_JniTest
#define _Included_com_iblogstreet_myapplication_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_iblogstreet_myapplication_JniTest
* Method: java2C
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_iblogstreet_myapplication_JniTest_java2C
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
通过javah 命令生成头文件
"/Applications/Android Studio 2.app/Contents/jre/jdk/Contents/Home/bin/javah" -jni -encoding UTF-8 -d /Users/junwang/androidporject/MyApplication4/app/src/main/cpp/include
com.iblogstreet.myapplication.JniTest
新建cpp类
在cpp目录中新建cpp类native-lib.cpp
#include
#include
#include "include/com_iblogstreet_myapplication_JniTest.h"
extern "C" JNIEXPORT jstring JNICALL
Java_com_iblogstreet_myapplication_JniTest_java2C(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
接着在cpp目录下新建CMakeLists.txt配置文件。
新建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.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 them 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).
native-lib.cpp )
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries 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 this
# 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} )
gradle关联CMakeLists.txt
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
}
}
}
...
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
生成so文件
重新编译,在app > build > intermediates > cmake > debug > obj目录下会生成不同CPU架构对应的so文件。
CMakeLists.txt 相关命令解析
cmake_minimum_required
指定需要CMAKE的最小版本
cmake_minimum_required(VERSION 3.4.1)
add_library
添加 源文件或库,可以出现多次。
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).
native-lib.cpp )
include_directories
指定 原生代码 或 so库 的头文件路径。
# Specifies a path to native header files.
include_directories(src/main/cpp/include/)
find_library and target_link_libraries
添加 NDK API,向 CMake 构建脚本添加 find_library() 命令以找到 NDK 库并将其路径存储为一个变量。
可以使用此变量在构建脚本的其他部分引用 NDK 库。以下示例会找到 Android 专有的日志支持库,并将其路径存储在 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 )
为了让原生库能够调用 log 库中的函数,需要使用 CMake 构建脚本中的 target_link_libraries() 命令来关联这些库
# 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} )
相关参考
android 官方
Android NDK开发(一) 使用CMake构建工具进行NDK开发
Android NDK开发(二) 使用ndk-build构建工具进行NDK开发
CMAKE手册-中文版
CMake Tutorial