在 Android 模块中编写 JNI 模块来调用第三方的 .so
文件,可以使用 NDK Build (老项目)或 CMake 两种方式。以下是详细的操作步骤:
使用 NDK Build
1. 创建 JNI 目录结构
在你的 Android 模块中创建一个 jni
目录,并在其中创建 Android.mk
和 Application.mk
文件。
your_android_module/
├── app/
│ ├── src/
│ └── jni/
│ ├── Android.mk
│ ├── Application.mk
│ └── your_jni_code.c
2. 编写 Android.mk 文件
在 jni/Android.mk
文件中定义你的模块和第三方库:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := your_jni_code
LOCAL_SRC_FILES := your_jni_code.c
LOCAL_LDLIBS := -llog
LOCAL_SHARED_LIBRARIES := third_party_lib # 这里是你的第三方.so库名称
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := third_party_lib
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libthird_party.so # 第三方库的位置
include $(PREBUILT_SHARED_LIBRARY)
3. 编写 Application.mk 文件
在 jni/Application.mk
文件中指定编译的目标架构和应用设置:
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
APP_PLATFORM := android-21
APP_STL := c++_shared
4. 编写你的 JNI 代码
在 jni/your_jni_code.c
文件中编写你的 JNI 代码:
#include <jni.h>
#include <string.h>
#include <android/log.h>
#define LOG_TAG "YourJNI"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
JNIEXPORT jstring JNICALL
Java_com_example_yourmodule_MainActivity_stringFromJNI(JNIEnv *env, jobject instance) {
LOGD("This is a debug message from JNI");
return (*env)->NewStringUTF(env, "Hello from JNI");
}
5. 在项目中使用 JNI
在你的 build.gradle
文件中配置 NDK 支持:
android {
...
defaultConfig {
...
externalNativeBuild {
ndkBuild {
path "src/main/jni/Android.mk"
}
}
}
externalNativeBuild {
ndkBuild {
path file("src/main/jni/Android.mk")
}
}
}
在 Java 代码中加载 JNI 库并调用本地方法:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("your_jni_code");
}
public native String stringFromJNI();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
}
}
使用 CMake
1. 创建 CMake 目录结构
在你的 Android 模块中创建一个 cpp
目录,并在其中创建 CMakeLists.txt
文件和你的 JNI 代码文件:
your_android_module/
├── app/
│ ├── src/
│ └── cpp/
│ ├── CMakeLists.txt
│ └── your_jni_code.cpp
2. 编写 CMakeLists.txt 文件
在 cpp/CMakeLists.txt
文件中定义你的模块和第三方库:
cmake_minimum_required(VERSION 3.4.1)
# 指定你的本地库名
add_library( your_jni_code SHARED your_jni_code.cpp )
# 引入log库
find_library( log-lib log )
# 引入第三方库
add_library( third_party_lib SHARED IMPORTED )
set_target_properties( third_party_lib PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libthird_party.so )
# 链接库
target_link_libraries( your_jni_code ${log-lib} third_party_lib )
3. 编写你的 JNI 代码
在 cpp/your_jni_code.cpp
文件中编写你的 JNI 代码:
#include <jni.h>
#include <string>
#include <android/log.h>
#define LOG_TAG "YourJNI"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_yourmodule_MainActivity_stringFromJNI(JNIEnv *env, jobject instance) {
LOGD("This is a debug message from JNI");
std::string hello = "Hello from JNI";
return env->NewStringUTF(hello.c_str());
}
4. 在项目中使用 JNI
在项目下的 build.gradle
文件中配置 CMake 支持:
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
}
}
}
externalNativeBuild {
cmake {
path file("src/main/cpp/CMakeLists.txt")
}
}
}
在 Java 代码中加载 JNI 库并调用本地方法:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("your_jni_code");
}
public native String stringFromJNI();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
}
}