在Android Studio 3中配置JNI及相关C++代码实现咨询
Hey there! Let's walk through both the JNI setup in Android Studio and the key technical points from your C++ snippet to help you get things running smoothly.
Since you're using OpenCV alongside JNI, we'll cover the full setup tailored to that stack:
1. Set up NDK and CMake
- Open your project in Android Studio, go to
File > Project Structure > SDK Tools. - Check NDK (Side by side) and CMake, then click "Apply" to install them. Android Studio will auto-configure paths in
local.propertiesfor you.
2. Configure CMakeLists.txt
Create a CMakeLists.txt file in your app module root (same level as build.gradle) with these contents:
cmake_minimum_required(VERSION 3.22.1) project("cerbyarms-features") # Compile your native C++ code into a shared library add_library( native-features SHARED src/main/cpp/your-native-file.cpp # Replace with your actual .cpp file path ) # Link OpenCV (critical since you're using Rect from OpenCV) find_package(OpenCV REQUIRED) include_directories(${OpenCV_INCLUDE_DIRS}) target_link_libraries(native-features ${OpenCV_LIBS}) # Link Android's log library for debugging find_library( log-lib log ) target_link_libraries(native-features ${log-lib})
3. Update Module-level build.gradle
Add the external native build config to your app's build.gradle (Module level) under the android block:
android { ... defaultConfig { ... externalNativeBuild { cmake { cppFlags "-std=c++17" # Match your C++ version abiFilters 'arm64-v8a', 'armeabi-v7a' # Match OpenCV's supported ABIs } } } externalNativeBuild { cmake { path file('CMakeLists.txt') version '3.22.1' # Match your installed CMake version } } }
4. Link Java Native Method
In your CameraActivity Java class, declare the native method to match your C++ function signature:
import org.opencv.core.Rect; public class CameraActivity extends AppCompatActivity { // Load the shared library first static { System.loadLibrary("native-features"); // Name matches add_library in CMakeLists.txt } // Native method declaration public native Rect FindFeatures(long maskMat); }
Looking at your snippet, here are key fixes and best practices to avoid crashes and bugs:
1. Validate OpenCV Mat Pointer
Your maskMat parameter is a jlong pointing to an OpenCV Mat object. First, safely cast and validate it:
#include <jni.h> #include <opencv2/core/core.hpp> #include <android/log.h> // Debug logging helper #define LOG_TAG "JNI-Features" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) extern "C" { JNIEXPORT jobject JNICALL Java_com_cerbyarms_cerbyarms_esra_camera_CameraActivity_FindFeatures(JNIEnv* env, jobject thiz, jlong maskMat) { // Cast jlong to Mat* and validate cv::Mat* mask = reinterpret_cast<cv::Mat*>(maskMat); if (!mask || mask->empty()) { LOGD("Invalid or empty mask Mat"); return nullptr; } // ... Your feature detection logic here to get x, y, width, height ... int x = 0, y = 0, width = 100, height = 100; // Example values
2. Safe JNI Object Creation with Error Checking
When creating the Rect object, add error checks to handle missing classes/methods and manage local references:
// Find Rect class jclass rectClass = env->FindClass("org/opencv/core/Rect"); if (!rectClass) { LOGD("Failed to find Rect class"); env->ExceptionClear(); // Clear pending exception to avoid app crash return nullptr; } // Get Rect constructor method ID (signature for (int,int,int,int)) jmethodID rectCtor = env->GetMethodID(rectClass, "<init>", "(IIII)V"); if (!rectCtor) { LOGD("Failed to find Rect constructor"); env->ExceptionClear(); env->DeleteLocalRef(rectClass); // Clean up local reference return nullptr; } // Create Rect object jobject rectObj = env->NewObject(rectClass, rectCtor, (jint)x, (jint)y, (jint)width, (jint)height); // Clean up local references to avoid memory leaks env->DeleteLocalRef(rectClass); return rectObj; } }
3. Critical Notes
extern "C"is mandatory: You already have this, which prevents C++ name mangling so JNI can locate your function correctly. Don't remove it!- ABI Consistency: Ensure the ABIs you specify in
build.gradlematch those provided by your OpenCV SDK. Mismatches will cause runtime crashes. - Local Reference Management: JNI has a limit on local references. Always call
DeleteLocalRefon objects likejclasswhen you're done with them.
内容的提问来源于stack exchange,提问作者Dan

