Flutter android project main thread issue

I am working on a flutter UI project with juce player (non UI). The flutter iOS is working properly but crashing Android When executing

    auto ins = juce::MessageManager::getInstance();
    ins->callAsync([=] {
        deviceManager = new juce::AudioDeviceManager();
        deviceManager->addAudioCallback(player);
        deviceManager->initialiseWithDefaultDevices(0, 2);
    });

Error logs

F/ple.flutter_app( 4233): java_vm_ext.cc:598] JNI DETECTED ERROR IN APPLICATION: JNI CallBooleanMethodV called with pending exception java.lang.RuntimeException: Can't create handler inside thread Thread[1.ui,6,main] that has not called Looper.prepare()
F/ple.flutter_app( 4233): java_vm_ext.cc:598]   at void android.os.Handler.<init>(android.os.Handler$Callback, boolean) (Handler.java:228)
F/ple.flutter_app( 4233): java_vm_ext.cc:598]   at void android.os.Handler.<init>() (Handler.java:130)
F/ple.flutter_app( 4233): java_vm_ext.cc:598]
F/ple.flutter_app( 4233): java_vm_ext.cc:598]     in call to CallBooleanMethodV
F/ple.flutter_app( 4233): runtime.cc:708] Runtime aborting...
F/ple.flutter_app( 4233): runtime.cc:708] Dumping all threads without mutator lock held
F/ple.flutter_app( 4233): runtime.cc:708] All threads:
F/ple.flutter_app( 4233): runtime.cc:708] DALVIK THREADS (22):
F/ple.flutter_app( 4233): runtime.cc:708] "main" prio=10 tid=1 Native
F/ple.flutter_app( 4233): runtime.cc:708]   | group="" sCount=1 ucsCount=0 flags=1 obj=0x732869b8 self=0xb4000076c520a380
F/ple.flutter_app( 4233): runtime.cc:708]   | sysTid=4233 nice=-10 cgrp=top-app sched=0/0 handle=0x785fd42d20
F/ple.flutter_app( 4233): runtime.cc:708]   | state=S schedstat=( 507985878 721643085 1001 ) utm=32 stm=18 core=2 HZ=100
F/ple.flutter_app( 4233): runtime.cc:708]   | stack=0x7fc5fbb000-0x7fc5fbd000 stackSize=8188KB
F/ple.flutter_app( 4233): runtime.cc:708]   | held mutexes=
F/ple.flutter_app( 4233): runtime.cc:708]   native: #00 pc 000be988  /apex/com.android.runtime/lib64/bionic/libc.so (__epoll_pwait+8) (BuildId: 1b9fecf834d610f77e641f026ca7269b)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #01 pc 00014030  /system/lib64/libutils.so (android::Looper::pollOnce+208) (BuildId: bca9105c866a03c2ff96b7e1fedd6c08)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #02 pc 00183bb8  /system/lib64/libandroid_runtime.so (android::android_os_MessageQueue_nativePollOnce+44) (BuildId: 7e2a886b7a4523debea27d91258da727)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #03 pc 0019d09c  [anon_shmem:dalvik-jit-code-cache] (offset 2000000) (art_jni_trampoline+140)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #04 pc 0006bc8c  [anon_shmem:dalvik-jit-code-cache] (offset 2000000) (android.os.MessageQueue.next+332)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #05 pc 0006b094  [anon_shmem:dalvik-jit-code-cache] (offset 2000000) (android.os.Looper.loopOnce+164)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #06 pc 0036de40  /apex/com.android.art/lib64/libart.so (art_quick_invoke_static_stub+640) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #07 pc 0036725c  /apex/com.android.art/lib64/libart.so (bool art::interpreter::DoCall<false>+2048) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #08 pc 0076e170  /apex/com.android.art/lib64/libart.so (void art::interpreter::ExecuteSwitchImplCpp<false>+12208) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #09 pc 003869d8  /apex/com.android.art/lib64/libart.so (ExecuteSwitchImplAsm+8) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #10 pc 0020c7c0  /system/framework/framework.jar (android.os.Looper.loop)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #11 pc 00359650  /apex/com.android.art/lib64/libart.so (art::interpreter::Execute +428) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #12 pc 00367a78  /apex/com.android.art/lib64/libart.so (bool art::interpreter::DoCall<false>+4124) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #13 pc 0076e170  /apex/com.android.art/lib64/libart.so (void art::interpreter::ExecuteSwitchImplCpp<false>+12208) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #14 pc 003869d8  /apex/com.android.art/lib64/libart.so (ExecuteSwitchImplAsm+8) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #15 pc 001d605c  /system/framework/framework.jar (android.app.ActivityThread.main)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #16 pc 003589dc  /apex/com.android.art/lib64/libart.so (artQuickToInterpreterBridge+1932) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #17 pc 00384498  /apex/com.android.art/lib64/libart.so (art_quick_to_interpreter_bridge+88) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #18 pc 0036de40  /apex/com.android.art/lib64/libart.so (art_quick_invoke_static_stub+640) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #19 pc 003698f4  /apex/com.android.art/lib64/libart.so (_jobject* art::InvokeMethod<8>+732) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #20 pc 006c6738  /apex/com.android.art/lib64/libart.so (art::Method_invoke +32) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #21 pc 00384370  /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline+144) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #22 pc 0036db74  /apex/com.android.art/lib64/libart.so (art_quick_invoke_stub+612) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #23 pc 003671e4  /apex/com.android.art/lib64/libart.so (bool art::interpreter::DoCall<false>+1928) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #24 pc 0076e170  /apex/com.android.art/lib64/libart.so (void art::interpreter::ExecuteSwitchImplCpp<false>+12208) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #25 pc 003869d8  /apex/com.android.art/lib64/libart.so (ExecuteSwitchImplAsm+8) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #26 pc 001d2704  /system/framework/framework.jar (com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #27 pc 003589dc  /apex/com.android.art/lib64/libart.so (artQuickToInterpreterBridge+1932) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   native: #28 pc 00384498  /apex/com.android.art/lib64/libart.so (art_quick_to_interpreter_bridge+88) (BuildId: 3f7d5a016e08d528f129bdd336d81168)
F/ple.flutter_app( 4233): runtime.cc:708]   at android.os.MessageQueue.nativePollOnce(Native method)
F/ple.flutter_app( 4233): runtime.cc:708]   at android.os.MessageQueue.next(MessageQueue.java:346)
F/ple.flutter_app( 4233): runtime.cc:708]   at android.os.Looper.loopOnce(Looper.java:189)
F/ple.flutter_app( 4233): runtime.cc:708]   at android.os.Looper.loop(Looper.java:317)
F/ple.flutter_app( 4233): runtime.cc:708]   at android.app.ActivityThread.main(ActivityThread.java:8705)
F/ple.flutter_app( 4233): runtime.cc:708]   at java.lang.reflect.Method.invoke(Native method)
F/ple.flutter_app( 4233): runtime.cc:708]   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580)
F/ple.flutter_app( 4233): runtime.cc:708]   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:886)
F/ple.flutter_app( 4233): runtime.cc:708]
F/ple.flutter_app( 4233): runtime.cc:708] "ReferenceQueueDaemon" prio=5 tid=6 Waiting
F/ple.flutter_app( 4233): runtime.cc:708]   | group="" sCount=1 ucsCount=0 flags=1 obj=0x14000830 self=0xb4000076c5205010
F/ple.flutter_app( 4233): runtime.cc:708]   | sysTid=4244 nice=4 cgrp=top-app sched=0/0 handle=0x7570700730
F/ple.flutter_app( 4233): runtime.cc:708]   | state=S schedstat=( 3709044 1465124 3 ) utm=0 stm=0 core=1 HZ=100
F/ple.flutter_app( 4233): runtime.cc:708]   | stack=0x75705fd000-0x75705ff000 stackSize=1037KB
F/ple.flutter_app( 4233): runtime.cc:708]   | held mutexes=

Note:

  1. Not using projucer to generate the android app project
  2. Generated android (shared) and iOS (static) libs binary
  3. Copy them to respected flutter project,
  4. Without main thread related juce apis working.
  5. Coppied flutter_app/android/app/src/main/java/com/rmsl/juce/Java.java and flutter_app/android/app/src/main/java/com/rmsl/juce/Receiver.java to flutter project

My project is open soruce, please take a look https://github.com/chanonly123/juce_audio_player

I’ve not seen this error before, but it sounds like you may not have initialised the message manager thread correctly. Are you using ScopedJuceInitialiser_GUI anywhere?

1 Like

Not using ScopedJuceInitialiser_GUI anywhere.
Since I am not using projucer generated android project, do I have to call some more juce setup methods?
Already caling Java.initialiseJUCE (this); in AndroidApplication.

That’s my best guess. Maybe you could try adding a ScopedJuceInitialiser_GUI instance that is created after loading your library, and destroyed just before unloading it.

1 Like

We had a very a rough time getting a similar setup working.

In our case, we did need the message thread to be started. Since the Dart VM and Java VM are completely separate, there was quite a bit of work that needed to be done to get things communicating properly. Many JUCE methods on Android rely on interacting with the Java side.

However, now that we’re past that pain we can set up functions in C++ and call them via Dart (via a C API) without touching JNI :slight_smile:

Thank you @reuk, ScopedJuceInitialiser_GUI isnt working.
Thank you @adamwilson kinda guessed the same dart_vm/java_vm issue. How much work/magic need exactly? can you suggest should I opt for flutter method channel?
Im spending sleepless nights here :smiling_face_with_tear:.

I have fixed the issue.
I had to call juce::MessageManager::getInstance(); from java using a jni method in Android.
also calling the same in the AppDelegate in iOS.
Now we can use the MessageManager from Flutter.

1 Like