Use JNI FindClass on Android properly
Improper usage of JNIEnv::FindClass
function will return NULL
or even crash the application. Things you should know about how FindClass
does work:
You should pass into FindClass
a fully-qualified class name and replace dots with slashes, for example: android/net/Uri
instead of android.net.Uri
.
You should call FindClass
from the main Java thread only. This is the thread where you do event polling with ALooper_pollAll
function.
That's enough if you're using FindClass
to find built-in classes. However that won't work in case you need to find a class from your own package — using it directly you'll still get NULL
.
To find a class from your own package you'll have to use a class loader. So, if you need to find com.package_name.MyClassName
you should do this instead:
JNIEnv* env;
android->activity->vm->AttachCurrentThread(&env, nullptr);
jclass native_activity_class = env->GetObjectClass(android->activity->clazz);
jmethodID get_class_loader = env->GetMethodID(native_activity_class, "getClassLoader", "()Ljava/lang/ClassLoader;");
jobject class_loader_object = env->CallObjectMethod(android->activity->clazz, get_class_loader);
jclass class_loader = env->FindClass("java/lang/ClassLoader");
jmethodID load_class = env->GetMethodID(class_loader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
jstring class_name = env->NewStringUTF("com.package_name.MyClassName");
jclass my_class = jclass(env->CallObjectMethod(class_loader_object, load_class, class_name));
env->DeleteLocalRef(class_name);
// my_class is what you're looking for
android->activity->vm->DetachCurrentThread();