5

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

没有通过的 JNI-ENV,C/C++ 怎么能得到呢?是否有可能 C/C++ 本机通过创建 JavaVM 在 Android 中调用 Java API?如果是,请分享链接。我已经完成了一个项目 CoCos2dx,但我无法找到明确的细节。github.com/nokia-developer/cocos2d-x-qt/tree/master/

提前致谢!

4

1 回答 1

2

这是我的做法。我通过参考Sheng Liang的 The Java Native Interface了解了如何;请参阅第 96 页。我有一个名为 ThreadEnv 的类,它拥有当前线程的 JNIEnv 指针,并在第一次需要时创建它:

class ThreadEnv
    {
    public:
    JNIEnv* GetEnv()
        {
        if (m_env == nullptr)
#if defined(ANDROID) || defined(__ANDROID__)
            TheJvm->AttachCurrentThread(&m_env,nullptr);
#else
            TheJvm->AttachCurrentThread((void**)&m_env,nullptr);
#endif
        return m_env;
        }
    ~ThreadEnv()
        {
        if (m_env)
            TheJvm->DetachCurrentThread();
        }

    private:
    JNIEnv* m_env = nullptr;
    };

然后,我通过使 ThreadEnv 对象成为我的 JNI 代码中需要它的任何 C++ 类的成员来使用它,并调用 GetEnv 来获取 JNIEnv 指针。下面是我如何在我的一个类中使用它的示例:看看 OnChange 成员函数。

class MyFrameworkObserver: public MFrameworkObserver, public MUserData
    {
    public:
    MyFrameworkObserver(jobject aFrameworkObject): m_framework_object(aFrameworkObject) { }
    ~MyFrameworkObserver()
        {
        JNIEnv* env = m_thread_env.GetEnv();
        if (env)
            env->DeleteGlobalRef(m_framework_object);
        }

    private:
    void OnViewChange() override { OnChange(TheFrameworkOnViewChangeMethodId); }
    void OnMainDataChange() override { OnChange(TheFrameworkOnMainDataChangeMethodId); }
    void OnDynamicDataChange() override { OnChange(TheFrameworkOnDynamicDataChangeMethodId); }

    void OnChange(jmethodID aMethodID)
        {
        JNIEnv* env = m_thread_env.GetEnv();
        if (env)
            env->CallVoidMethod(m_framework_object,aMethodID);
        }

    jobject m_framework_object;
    ThreadEnv m_thread_env;
    };
于 2019-03-06T15:09:05.630 回答