Android Studio 2.2 版本完全支持 NDK 开发,当创建一个 Java 与 C++ 混编的工程时,程序默认使用的是 CMake 编译原生库。
CMake
- 概念
CMake 是一个跨平台的安装编译工具,可以用简单的语句来描述所有平台的安装编译过程。 - 为什么使用 CMake
- 可以直接的在 C/C++ 代码中加入断点,进行调试。
- Java 引用的 C/C++ 中的方法,可以直接 ctrl+ 左键进入。
- 对于 include 的头文件,或者库,也可以直接的进入。
- 不需要配置命令行操作,手动的生成头文件,不需要配置android.useDeprecatedNdk=true 属性。
现有项目中使用CMake构建原生库
第一步 首先在 app/src/main 下创建 cpp 目录,在新创建的目录下创建原生源文件,右键 new -> C/C++ Source File,文件名称为 native-lib.cpp。如图所示:
第二步 使用 CMake 构建脚本,在 cpp 目录下创建 CMakeLists.txt 文件,命名不能出错。文件内容如下所示:
#脚本配置
cmake_minimum_required(VERSION 3.4.1) #指定 cmake 版本
add_library(
native-lib #生成函数库名字
SHARED #生成动态函数库,配置该命令才能找到编译这个库
native-lib.cpp #依赖的 cpp 文件
)
#添加 NDK API
find_library(
log-lib #支持日志支持库名字和路径
log #库名字
)
#关联库
target_link_libraries(
native-lib #库名称
${log-lib} #连接的库
)
第三步 在 Java 类中加载库以及声明 native 方法,代码如下所示:
static {
System.loadLibrary("native-lib");
}
public native String GetStringFromC();
第四步 app 下 build.gradle 进行配置,关联原生库。android 标签下的 externalNativeBuild 配置可自动生成。右键 app 目录,从菜单中选择 Link C++ Project with Gradle,需要指定 CMakeLists.txt 文件的路径。defaultConfig 标签下 externalNativeBuild 配置手动完成,完整配置如下:
android {
compileSdkVersion 29
buildToolsVersion "29.0.1"
defaultConfig {
applicationId "com.example.hellondk"
minSdkVersion 15
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild{
cmake{
cppFlags "" //如果使用C++11标准,则使用cppFlags "-std=c++11"
abiFilters "armeabi-v7a","x86" //生成 .so 目标平台
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
}
}
}
第五步 编写新建的 native-lib.cpp 文件,书写 C 代码需要实现的功能。此例中C 代码返回文本字符串功能。代码如下所示:
#include "jni.h"
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_hellondk_MainActivity_GetStringFromC(JNIEnv *env, jobject ) {
std::string hello = "欢迎使用 C 语言";
return env->NewStringUTF(hello.c_str());
第六步 MainActivity 中调用 native 方法,本例中将 C 功能代码返回的字符串显示在文本框中。代码如下所示:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("native-lib");
}
public native String GetStringFromC();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.tv_text);
textView.setText(GetStringFromC());
}
}