1

If I alter Juce's JNI_Onload to this:

extern "C" jint JNIEXPORT JNI_OnLoad (JavaVM* vm, void*)
{
    // Huh? JNI_OnLoad was called two times!
    jassert (androidJNIJavaVM == nullptr);

    androidJNIJavaVM = vm;

    auto* env = getEnv();

    // register the initialisation function
    auto juceJavaClass = env->FindClass("com/rmsl/juce/Java");
    __android_log_write(ANDROID_LOG_DEBUG, "Tag", "finding MainActivity");
    auto S = env->FindClass("com/my_app/flutter_app/MainActivity");
    __android_log_write(ANDROID_LOG_DEBUG, "Tag", "finding MainActivity END");
    if (!S) {
        __android_log_write(ANDROID_LOG_ERROR, "Tag", "finding MainActivity END");
    } else {
        __android_log_write(ANDROID_LOG_DEBUG, "Tag", "DID find MainActivity");
    }

It works without any problem. That is, the class MainActivity is found.

However, this line:

auto mainActivityClass1 = env->FindClass("com/my_app/flutter_app/MainActivity");

called in this code:

MyJuceApp() {
    JNIEnv* env = juce::getEnv();
    auto mainActivityClass1 = env->FindClass("com/my_app/flutter_app/MainActivity");

Where START_JUCE_APPLICATION (MyJuceApp) gives an error:

A/zygote64: java_vm_ext.cc:523] JNI DETECTED ERROR IN APPLICATION: JNI CallBooleanMethodV called with pending exception java.lang.ClassNotFoundException: Didn't find class "com.my_app.flutter_app.MainActivity" on path: DexPathList[[dex file "InMemoryDexFile[cookie=[0, 547943543104]]"],nativeLibraryDirectories=[/system/lib64, /system/vendor/lib64]]

It looks like when JNI_Onload() is called, it's called from the Java thread. Then, JNI_Onload() calls some Juce internal things that starts the app by calling MyJuceApp, where things fail. I think it fails because MyJuceApp is initialized from another thread.

So, the class definitely exists, because JNI_Onload finds it. But when MyJuceApp constructor is called, it cannot find the same class anymore.

I also tried attaching the thread:

JNIEnv* env = juce::getEnv();
JavaVM* vm;
env->GetJavaVM(&vm);
JavaVMAttachArgs args;
args.version = JNI_VERSION_1_6;
args.name = nullptr;
args.group = nullptr;
JNIEnv* env2 = juce::getEnv();
vm->AttachCurrentThread(&env2, &args);
auto mainActivityClass1 = env2->FindClass("com/my_app/flutter_app/MainActivity");

and got the same problem.

PS: env->FindClass("java/lang/String") works, where env->FindClass("com/my_app/flutter_app/MainActivity") does not, which makes things even more confusing. But the class name is correct, because it's found in JNI_Onload().

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Rafaelo
  • 33
  • 1
  • 15

1 Answers1

0

Last year When I was investigating the same issue, I wrote a lengthy blog post on how I identified and fixed the issue at https://atsushieno.github.io/2022/03/16/juce-android-threads.html

Looks like this SO question identical to the JUCE forum post that I mentioned on my blog post.

atsushieno
  • 11
  • 1
  • 1
  • 2