Java call native with callback of anonymous inner class

  • Lib.kt

    package com.practice
    
    class Lib {
    
        external fun getJniVersion(callback: Callback)
    
        interface Callback {
            fun onResponse(version: String)
        }
    
        init {
            System.loadLibrary("native-lib")
        }
    }
    
  • CMakeLists.txt

    cmake_minimum_required(VERSION 3.10.2)
    
    add_library(native-lib SHARED native-lib.cpp)
    
    find_library(log-lib log)
    
    target_link_libraries(native-lib ${log-lib})
    
  • native-lib.cpp

    #include <jni.h>
    #include <android/log.h>
    
    jstring getVersion(JNIEnv *env) {
        switch (env->GetVersion()) {
            case JNI_VERSION_1_1:
                return env->NewStringUTF("JNI_VERSION_1_1");
            case JNI_VERSION_1_2:
                return env->NewStringUTF("JNI_VERSION_1_2");
            case JNI_VERSION_1_4:
                return env->NewStringUTF("JNI_VERSION_1_4");
            case JNI_VERSION_1_6:
                return env->NewStringUTF("JNI_VERSION_1_6");
            default:
                return env->NewStringUTF("UNKNOWN");
        }
    }
    
    extern "C" JNIEXPORT void JNICALL
    Java_com_practice_Lib_getJniVersion(JNIEnv *env, jobject /* this */, jobject callback) {
        __android_log_print(ANDROID_LOG_DEBUG, "native", "looking for class");
        jclass callbackClass = env->GetObjectClass(callback);
        if (callbackClass != nullptr) {
            jmethodID methodId = env->GetMethodID(callbackClass, "onResponse", "(Ljava/lang/String;)V");
            if (methodId != nullptr) {
                env->CallVoidMethod(callback, methodId, getVersion(env));
            } else {
                __android_log_print(ANDROID_LOG_DEBUG, "native", "can not find method");
            }
        } else {
            __android_log_print(ANDROID_LOG_DEBUG, "native", "can not find class");
        }
    }
    
  • MainActivity.kt

    package com.practice
    
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import kotlinx.android.synthetic.main.activity_main.*
    
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            Lib().getJniVersion(object : Lib.Callback {
                override fun onResponse(version: String) {
                    sample_text.text = version
                }
            })
        }
    
    }
    

use of deleted global reference error

When I call the Java method with wrong parameter type such as:

env->CallVoidMethod(callback, methodId, "jni version");

I will get below error:

JNI DETECTED ERROR IN APPLICATION: use of deleted global reference

Can't succeed in calling a Java function from a C++ module with JNI

illegal class name error

When I find class with wrong format jclass callbackClass = env->FindClass("com/practice/Lib.Callback");, I will get error.

A/art: art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: illegal class name 'com/practice/Lib.Callback'
A/art: art/runtime/java_vm_ext.cc:410]     (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')
A/art: art/runtime/java_vm_ext.cc:410]     in call to FindClass
A/art: art/runtime/java_vm_ext.cc:410]     from void com.practice.Lib.getJniVersion(com.practice.Lib$Callback)

It should be env->FindClass("com/practice/Lib$Callback") for inner class.

results matching ""

    No results matching ""