java - 在 Android Studio 3 中设置 JNI

标签 java android c++ android-studio java-native-interface

我在我正在处理的 Android Studio 项目中使用 JNI。目前,我有一个看起来与此类似的 C++ 库。

#include <jni.h>
...
extern "C" {
    JNIEXPORT jobject JNICALL Java_com_cerbyarms_cerbyarms_esra_camera_CameraActivity_FindFeatures(JNIEnv* env, jobject, jlong maskMat)
    {
        ...
        jclass rectClass = env->FindClass("org/opencv/core/Rect");
        jmethodID rectID = env->GetMethodID(rectClass, "<init>", "(IIII)V");
        return env->NewObject(rectClass, rectID, x, y, width, height);
    }
}

这行得通。然而,它是低效的。每次运行时,rectClass 都必须重新查找类,并且每次调用函数 FindFeatures 时,都必须重新计算和重新定义程序中保持不变的其他变量。

我遇到了这个answer on Stack Overflow (除了它显示了我正在尝试做的事情的示例之外,它与这个问题无关),它显示了使用 JNI 时 native 文件的不同布局。

看起来像这样

static jclass java_util_ArrayList;
static jmethodID java_util_ArrayList_;
jmethodID java_util_ArrayList_size;
jmethodID java_util_ArrayList_get;
jmethodID java_util_ArrayList_add;
static thread_local JNIEnv* env;

void init() {
    java_util_ArrayList      = static_cast<jclass>(env->NewGlobalRef(env->FindClass("java/util/ArrayList")));
    java_util_ArrayList_     = env->GetMethodID(java_util_ArrayList, "<init>", "(I)V");
    java_util_ArrayList_size = env->GetMethodID (java_util_ArrayList, "size", "()I");
    java_util_ArrayList_get  = env->GetMethodID(java_util_ArrayList, "get", "(I)Ljava/lang/Object;");
    java_util_ArrayList_add  = env->GetMethodID(java_util_ArrayList, "add", "(Ljava/lang/Object;)Z");
}

std::vector<std::string> java2cpp(jobject arrayList) {
    jint len = env->CallIntMethod(arrayList, java_util_ArrayList_size);
    std::vector<std::string> result;
    result.reserve(len);
    for (jint i = 0; i < len; i++) {
        jstring element = static_cast<jstring>(env->CallObjectMethod(arrayList, java_util_ArrayList_get, i));
        const char* pchars = env->GetStringUTFChars(element, nullptr);
        result.emplace_back(pchars);
        env->ReleaseStringUTFChars(element, pchars);
        env->DeleteLocalRef(element);
    }
}

这显示了一个 native 文件,其中包含昂贵且常量的变量,这些变量似乎只声明和计算一次。

如何仅使用 Android Studio IDE 实现类似的效果?我不介意必须在 Android Studio IDE 设置中设置外部工具,但我不想每次编译代码时都在 Android Studio 和 CMD 之类的东西之间切换。

理想情况下,当点击 Make Project 时,这一切都可以正确处理。这在 Android Studio 3 中可行吗?

最佳答案

你是 100% 正确的,一些 JNI 值请求被缓存和重用。类引用和方法 ID 就是很好的例子。请记住,FindClass() 返回本地引用,因此您需要为缓存中保存的每个类使用 NewGlobalRef()

Android Studio 不会帮助我们进行此设置,而且我不知道可以为我们进行此类重构的可靠工具。您可以从开源代码中学习好的做法,例如来自 WebRTC JNI wrapper或来自 Spotify JNI helpers .

Android Studio 只能跟踪本地方法,不能跟踪缓存的对象、转换等。

关于java - 在 Android Studio 3 中设置 JNI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49466236/

相关文章:

android - 插入新项目后如何在回收站 View 中不丢失当前数据

c++ - C++中的显式代码并行性

java - 将ms access中结果集的数据插入到excel文件中

java - 表达式的非法开始(Android)

java - Google App Engine Cron 作业

java - 使用Java访问Magento API : Procedure ххх not present

android - 删除图片后如何刷新Recyclerview?

android - 我在 R.java 中有错误?

c++ - 如何在 C++ 中绑定(bind)构造函数?

c++ - 如何在实例化时打印类类型变量的名称?