FindClass from any thread in Android JNI
After much trying and crashing of my app, a colleague and I managed to cache and succesfully use the class loader in another, native, thread. The code we used is shown below (C++11, but easily converted to C++2003), posted here since we couldn't find any examples of the aforementioned "Cache a reference to the ClassLoader object somewhere handy, and issue loadClass calls directly. This requires some effort.". Calling findClass worked perfectly when called from a thread different from the one of JNI_OnLoad. I hope this helps.
JavaVM* gJvm = nullptr;
static jobject gClassLoader;
static jmethodID gFindClassMethod;
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *pjvm, void *reserved) {
gJvm = pjvm; // cache the JavaVM pointer
auto env = getEnv();
//replace with one of your classes in the line below
auto randomClass = env->FindClass("com/example/RandomClass");
jclass classClass = env->GetObjectClass(randomClass);
auto classLoaderClass = env->FindClass("java/lang/ClassLoader");
auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader",
"()Ljava/lang/ClassLoader;");
gClassLoader = env->CallObjectMethod(randomClass, getClassLoaderMethod);
gFindClassMethod = env->GetMethodID(classLoaderClass, "findClass",
"(Ljava/lang/String;)Ljava/lang/Class;");
return JNI_VERSION_1_6;
}
jclass findClass(const char* name) {
return static_cast<jclass>(getEnv()->CallObjectMethod(gClassLoader, gFindClassMethod, getEnv()->NewStringUTF(name)));
}
JNIEnv* getEnv() {
JNIEnv *env;
int status = gJvm->GetEnv((void**)&env, JNI_VERSION_1_6);
if(status < 0) {
status = gJvm->AttachCurrentThread(&env, NULL);
if(status < 0) {
return nullptr;
}
}
return env;
}
Calling java method from different thread in ndk
The solution to my problem was to keep a reference to all the classes I will need in my different threads at the begginning of the ndk call before starting my threads and to use them inside those threads. I could also gave them to the thread as parameters.
Found it out thans to pskink and according to this documentation : https://developer.android.com/training/articles/perf-jni.html#faq_FindClass
JNI : Unable to find java class from native method in a callback
The answer and the official workaround can be found on developer.android. If you must go beyond pre-caching global references for all classes your native code might need, you will find a successful solution that caches the correct class loader here: FindClass from any thread in Android JNI
why JNIEnv can't find class com/google/android/gms/ads/identifier/AdvertisingIdClient?
Problem was solved.
The Application ClassLoader works well for my custom Class.
Because the App was not include com/google/android/gms/ads/identifier/AdvertisingIdClient
. so we can not found it. Usually we get advertisingId through Intent
to request Service.
Related Topics
Pass Arraylist<? Implements Parcelable> to Activity
Upload an Image from Camera or Gallery in Webview
Cannot Catch Toolbar Home Button Click Event
Does the Web View on Android Support Ssl
Run Code Only Once After an Application Is Installed on Android Device
Does Android Support Jdk 6 or 7
How to Get the Google Username on Android
How to Set Dropdown Arrow in Spinner
How to Get Multiple Icons to Launch Different Activities in One Application
Convert Bitmap Array to Yuv (Ycbcr Nv21)
Android:Passing a Hash Map Between Activities
Android - Supportmapfragment with Googlemaps API 2.0 Giving Illegalargumentexception
Getintent() Extras Always Null
List of Files in Assets Folder and Its Subfolders
How to Programmatically Enable/Disable Accessibility Service in Android