java - Android C/C++ native 调用 Java API

标签 java android java-native-interface native-code jnienv

Android C/C++原生调用Java API的例子有很多。 但是,我读过的所有这些示例都是 Android Java API 调用 native 首先,然后 native 使用传递的 JNI-ENV 调用其他 Java API。

没有传入的JNI-ENV,C/C++怎么获取呢? C/C++ native 是否可以在没有 JNI-ENV 的情况下调用 Java API?

如果可能的话,你能举个例子或链接吗?

谢谢!

最佳答案

您需要先包含jni.h。这会带来大量有用的调用;对于较新的 android 版本,您还需要 JniInvocation.h。要启用此功能:

LOCAL_C_INCLUDES += ${JNI_H_INCLUDE}

这当然适用于源代码树,不确定 NDK,但也应该没问题。

其次,非常重要的是选择合适的信号链库。 Art 或 Dalvik 将加载 libsigchain.so,这是一个 stub 和 abort() 每次调用其任何方法时。在 Android 上,它通过一个小 hack 完成:本地符号被导出到全局符号表,因此 Art 选择 exec 的符号而不是加载共享库。这是如何完成的:

# Enable native helper calls
LOCAL_SHARED_LIBRARIES += libnativehelper

# Include all of the Android's libsigchain symbols
LOCAL_WHOLE_STATIC_LIBRARIES += libsigchain

# Export only libsigchain symbols to global symbol table.
LOCAL_LDFLAGS += \
    -Wl,--export-dynamic \
    -Wl,--version-script,art/sigchainlib/version-script.txt

现在链接您的可执行文件。仔细检查是否确实导出了所需的符号:

% readelf -a <output_binary> | grep InitializeSignalChain
654: 0002cab1   211 FUNC    GLOBAL PROTECTED   12 InitializeSignalChain

完成了吗?现在事情变得简单了:

  1. 初始化 JNI(以便您的代码使用正确的 VM)

    JniInvocation invocation;
    if (invocation.Init(nullptr)) return;
    
  2. 创建 JavaVM:

    JavaVM* vm;
    JNIEnv* env;
    JavaVMInitArgs* args;
    
    args.version = JNI_VERSION_1_4;  // _5, _6
    args.options = nullptr;
    args.nOptions = 0;
    args.ignoreUnrecognized = JNI_FALSE;
    
    if (JNI_CreateJavaVM(&vm, &env, &args) < 0) return;
    
  3. 此时您的vmenv 已经可以使用了。玩得开心。

  4. 检查异常情况,如果有的话

    if (env->ExceptionCheck()) {
        // ...
    }
    
  5. 完成后,清理

    vm->DetachCurrentThread();
    vm->DestroyJavaVM();
    

可以找到更多有趣的东西hereDalvikVM Main可能是最好的知识来源。祝你好运!

关于java - Android C/C++ native 调用 Java API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11573406/

相关文章:

android - 从url下载文件到cordova app错误

android - getFragmentManager().beginTransaction() 问题

java - JNI 上的 Java native 崩溃

android - 如何在android中基于CPU架构有条件地加载 native 库

java - 不幸的是,项目已在 android studio 中停止

java - 如何在同一个 Android 项目的多个资源文件夹之间进行更改?

java - 在 Android 上的 CalendarView 中触摸选定日期时无法生成事件

java - 如何避免在 Java 和 native C++ 代码之间复制数据

java - 为什么同步关键字不与原始变量一起使用。仅与方法和同步块(synchronized block)一起使用

java - volatile 写入 = volatile 读取