This is how I do it for String:
void SampleSwitchCamera(const char *name)
{
jboolean isAttached;
JNIEnv *env;
jmethodID mid;
jstring js;
LOGE("SampleSwitchCamera Begin");
env = getJniEnv(&isAttached);
if (env == NULL)
goto FAIL0;
mid = getApplicationJniMethodId(env, applicationJniObj, "cameraSwitchCallback", "(Ljava/lang/String;)V");
if (mid == NULL)
goto FAIL1;
js = (*env)->NewStringUTF(env, name);
(*env)->CallVoidMethod(env, applicationJniObj, mid, js);
if (isAttached)
{
(*global_vm)->DetachCurrentThread(global_vm);
}
LOGE("SampleSwitchCamera End");
return;
FAIL1:
if (isAttached)
{
(*global_vm)->DetachCurrentThread(global_vm);
}
FAIL0:
LOGE("SampleSwitchCamera FAILED");
return;
}
So I tried like this:
void CallbackFromJni(const int *id)
{
jboolean isAttached;
JNIEnv *env;
jmethodID mid;
jstring js;
LOGE("callbackFromJni Begin %d", id);
env = getJniEnv(&isAttached);
if (env == NULL)
goto FAIL0;
mid = getApplicationJniMethodId(env, applicationJniObj, "callbackFromJni", "(Ljava/lang/Integer;)V");
if (mid == NULL)
goto FAIL1;
jintArray array = (*env)->NewIntArray(env, id);
(*env)->CallVoidMethod(env, applicationJniObj, mid, array);
if (isAttached)
{
(*global_vm)->DetachCurrentThread(global_vm);
}
LOGE("callbackFromJni End");
return;
FAIL1:
if (isAttached)
{
(*global_vm)->DetachCurrentThread(global_vm);
}
FAIL0:
LOGE("callbackFromJni FAILED");
return;
}
But I get this error:
01-26 11:17:36.654: E/VidyoMobile app/src/main/jni/ndkVidyoSample.c(22071): callbackFromJni Begin 101
01-26 11:17:36.655: E/art(22071): JNI ERROR (app bug): attempt to pass an instance of int[] as argument 1 to void com.vidyo.vidyocore.VidyoCoreApplication.callbackFromJni(java.lang.Integer)
01-26 11:17:36.692: A/art(22071): art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: bad arguments passed to void com.vidyo.vidyocore.VidyoCoreApplication.callbackFromJni(java.lang.Integer) (see above for details)
01-26 11:17:36.692: A/art(22071): art/runtime/java_vm_ext.cc:410] native: #09 pc 000024a9 /data/app/be.belfius.videocall-1/lib/arm/libndkVidyoSample.so (CallbackFromJni+104)
01-26 11:17:37.219: A/art(22071): art/runtime/runtime.cc:366] native: #12 pc 000024a9 /data/app/be.belfius.videocall-1/lib/arm/libndkVidyoSample.so (CallbackFromJni+104)
01-26 11:17:37.220: A/art(22071): art/runtime/runtime.cc:366] native: #14 pc 000024a9 /data/app/be.belfius.videocall-1/lib/arm/libndkVidyoSample.so (CallbackFromJni+104)
01-26 11:17:37.365: A/DEBUG(195): Abort message: 'art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: bad arguments passed to void com.vidyo.vidyocore.VidyoCoreApplication.callbackFromJni(java.lang.Integer) (see above for details)'
01-26 11:17:37.389: A/DEBUG(195): #14 pc 000024a9 /data/app/be.belfius.videocall-1/lib/arm/libndkVidyoSample.so (CallbackFromJni+104)
I am asumming cause I need an int and this is creating an intArray. How can I create an int, because there is no newInt , just newIntArray
you declared to get method that gets Integer
object as parameter
mid = getApplicationJniMethodId(env, applicationJniObj, "callbackFromJni", "(Ljava/lang/Integer;)V");
but then you are passing integer table int[]
as parameter
jintArray array = (*env)->NewIntArray(env, id);
(*env)->CallVoidMethod(env, applicationJniObj, mid, array);
correct way of declaring types to use are described here: https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html
if you want to pass Integer
as parameter, you need to change creating table to creating single Integer object
jclass int_cls = (*env)->FindClass(env, "java/lang/Integer");
if (int_cls == NULL)
goto FAIL1;
jmethodID int_constructor = (*env)->GetMethodID(env, int_cls, "<init>", "(I)V");
if (int_constructor == NULL)
goto FAIL1;
jobject java_int = (*env)->NewObject(env, int_cls, int_constructor, (jint)*id);
if (java_int == NULL)
goto FAIL1;
(*env)->CallVoidMethod(env, applicationJniObj, mid, java_int);
method in Java side in this case need to look like:
native void callbackFromJni(Integer result);
instead of Integer it would be a lot easier to pass simple int
rather than Integer
as primitive types can be passed directly instead of boxing them in objects
mid = getApplicationJniMethodId(env, applicationJniObj, "callbackFromJni", "(I)V");
if (mid == NULL)
goto FAIL1;
(*env)->CallVoidMethod(env, applicationJniObj, mid, *id);
method in Java side in this case need to look like:
native void callbackFromJni(int result);
if you were trying to pass integer array int[]
you would need to declare
mid = getApplicationJniMethodId(env, applicationJniObj, "callbackFromJni", "([I)V");
parameter passed to creating new table is the size, not the array itself, so you would need to get size of that array first and use it when creating table
jintArray array = (*env)->NewIntArray(env, size);
then set array content and pass it to callback
(*env)->SetIntArrayRegion(env, array, 0, size, id);
(*env)->CallVoidMethod(env, applicationJniObj, mid, array);
method in Java side in this case need to look like:
native void callbackFromJni(int[] result);