I try to call a java function from my c++ code, but the app keeps 'crashing'.
At first, I start the c++ code through JNI call, which works without any problem. Then I let the function which is called executing the callback:
#include <jni.h>
extern "C"
JNIEXPORT jstring JNICALL
Java_net_example_folder_Service_startSomething(JNIEnv *env, jobject obj) {
invoke_class(env);
return env->NewStringUTF("The End.\n"); //works if I only use this line
}
Trying to follow http://www.inonit.com/cygwin/jni/invocationApi/c.html (and a lot of other guides/tips etc.), I use this to call the java function:
void invoke_class(JNIEnv* env) {
jclass helloWorldClass;
jmethodID mainMethod;
helloWorldClass = env->FindClass("Java/net/example/folder/helloWorldClass");
mainMethod = env->GetStaticMethodID(helloWorldClass, "helloWorld", "()V");
env->CallStaticVoidMethod(helloWorldClass, mainMethod);
}
To call the java code:
package net.example.folder;
import android.util.Log;
public class helloWorldClass {
public static void helloWorld() {
Log.e("helloWorldCLass", "Hello World!");
}
}
The c++ code is called by a background service. Here is the function of the Activity that starts it:
public void startService() {
Intent i = new Intent(this, Service.class);
startService(i);
}
And this is a part of the Service:
public class SimService extends IntentService {
...
@Override
protected void onHandleIntent(Intent intent) {
System.loadLibrary("native-lib");
startSomething();
}
}
That all works, but when I now change the function 'invoke_class' to:
void invoke_class(JNIEnv* env) {
jclass helloWorldClass;
jmethodID mainMethod;
helloWorldClass = env->FindClass("net/example/folder/helloWorldClass");
mainMethod = env->GetStaticMethodID(helloWorldClass, "helloWorld", "([Ljava/lang/String;)V");
env->CallStaticVoidMethod(helloWorldClass, mainMethod, env->NewStringUTF("some text"));
}
and of course the java part to:
package net.example.folder;
import android.util.Log;
public class helloWorldClass {
public static void helloWorld(String msg) {
Log.e("helloWorldCLass", msg);
}
}
With that, I'll get the earlier mentioned crash.
Why is that? How do I pass arguments correctly?
Symbol [
is used to represent arrays (as if you had String[] msg), remove that from your GetStaticMethodID method.
You can see more information about JNI Types and Data Structures here
Also as Michael said - you should check for java exceptions in your native code, because otherwise your app will crash. You can do it using Exception jni functions. For example:
jclass exClass = env->FindClass("some/random/class");
if (exClass == nullptr || env->ExceptionOccurred()) {
env->ExceptionClear();
// do smth in case of failure
}