在安卓开发中,嵌入C语言主要通过 JNI(Java Native Interface) 实现,核心流程是将C/C++代码编译为动态库(.so文件),并通过Java/Kotlin代码调用本地方法,以下是实现步骤:
SDK Manager
安装对应版本的 NDK(Native Development Kit)。build.gradle
中配置CMake或ndk-build。在app/src/main
目录下创建cpp
文件夹(或jni
),存放.c
或.cpp
文件。
示例代码(native-lib.cpp
):
#include <jni.h> #include <string.h> extern "C" JNIEXPORT jstring JNICALL Java_com_example_myapp_MainActivity_stringFromJNI(JNIEnv env, jobject thiz) { std::string hello = "Hello from C++"; return env->NewStringUTF(hello.c_str()); }
app
目录下创建CMakeLists.txt
: cmake_minimum_required(VERSION 3.4.1) add_library(native-lib SHARED native-lib.cpp) find_library(log-lib log) target_link_libraries(native-lib ${log-lib})
build.gradle
中配置: android { externalNativeBuild { cmake { path "CMakeLists.txt" } } }
public class MainActivity extends AppCompatActivity { static { System.loadLibrary("native-lib"); // 加载动态库 } public native String stringFromJNI(); // 声明本地方法 }
String result = stringFromJNI(); // 调用C++方法
问题 | 解决方案 |
---|---|
函数命名不匹配 | 确保C函数名与Java声明的native 方法严格遵循JNI命名规则(包名+类名+方法名)。 |
数据类型转换错误 | 使用JNI提供的NewStringUTF 、GetIntArrayElements 等工具处理数据类型。 |
动态库未正确加载 | 确保System.loadLibrary 在调用本地方法前执行,且库文件存在于libs 目录。 |
多线程安全问题 | 避免在本地代码中直接操作UI,需通过Handler 切换到主线程。 |
解答:
Debugger
设置断点。ndk-gdb
或lldb
调试本地代码。Log.d
)以验证本地方法是否被调用。解答:
SetIntArrayRegion
、GetIntArrayElements
等函数。Parcel
序列化。JNIEXPORT void JNICALL Java_com_example_myapp_MainActivity_passArray(JNIEnv env, jobject thiz, jintArray arr) { jint elements = env->GetIntArrayElements(arr, NULL); // 操作elements... env->ReleaseIntArrayElements(arr, elements, 0); }