jni 配置有两种方式:旧版本 Android.mk 配置和使用 cmake 配置,两种都会说明。
1、Android.mk 配置 jni
(1)在项目目录右键->New->Folder->JNI Folder,生成一个与 java 目录同级的 jni 目录
(2)在类中声明一个 native 方法
public class MainActivity extends AppCompatActivity {
public native String getStringFromJNI();
}
(3)在 AS 的 Terminal 中使用 javah 生成头文件(注:javah 在 java10 之后被删除,要使用 javac 生成头文件,这里使用 java8)
// AS 的 Terminal 打开时默认在 app/src/main 目录下,在该目录下执行下面命令
javah -d jni/include -classpath java com.example.ndk.MainActivity
-d:指定创建头文件的目标路径,头文件生成到 jni/include 目录下
-classpath:指定类路径,由于打开 AS 的 Terminal 时默认是 main 目录,所以指定 java 即可
执行完后,会在 jni 目录生成一个头文件
(4)在 jni 目录下创建 c 文件和 Android.mk 文件
com_example_ndk_MainActivity.c
// 因为头文件放在include目录下,所以要加上include目录才能找到头文件
#include "include/com_example_ndk_MainActivity.h"
#include <jni.h>
/*
* Class: com_example_ndk_MainActivity
* Method: getStringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_ndk_MainActivity_stringFromJNI
(JNIEnv *env, jobject thiz) {
return (*env)->NewStringUTF(env, "hello from jni!");
}
Android.mk
#LOCAL_PATH必须放在include $(CLEAR_VARS)之前
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#源文件
LOCAL_SRC_FILES := com_example_ndk_MainActivity.c
#生成的ndk库,libndk
LOCAL_MODULE := ndk
include $(BUILD_SHARED_LIBRARY)
(5)在 app 目录下的 build.gradle 配置 ndk,同步(同步后写 c/c++ 文件时就有代码提示)
android {
...
externalNativeBuild {
ndkBuild {
path "src/main/jni/Android.mk"
}
}
}
2、cmake 方式配置 jni
在新版本不再需要太多手动的配置,新建项目工程会有一个 cpp 目录,提供一个 CMakeLists.txt 和 native-lib.cpp,其中 native-lib.cpp 就是 jni 代码。
CMakeLists.txt:
cmake_minimum_required(VERSION 3.18.1)
# Declares and names the project.
# 编译出来的 so 名称
project("ndk")
add_library( # Sets the name of the library.
# 工程名称
ndk
# Sets the library as a shared library.
# 编译静态库或动态库,这里设置的是动态库
SHARED
# Provides a relative path to your source file(s).
# jni 代码源文件名
native-lib.cpp)
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)
target_link_libraries( # Specifies the target library.
ndk
# Links the target library to the log library
# included in the NDK.
${log-lib})
native-lib.cpp:
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_ndk_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "hello from jni!";
return env->NewStringUTF(hello.c_str());
}
并且在 app 的 build.gradle 还需要配置 cmake:
android {
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
version '3.18.1'
}
}
}
3、在 java 类中加载库
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("ndk");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tvNdk = findViewById(R.id.tv_ndk);
tvNdk.setText(stringFromJNI());
}
public native String stringFromJNI();
}