sometimes my android app was not able to resume right after pausing (using the back nav key), but not every time. I could not clarify what was causing it (i’m attaching the main component to opengl, so maybe that’s a reason, …
When it happened the app just showed as black window on resume. I figured out, that in these cases the app was not suspended right when pausing before. The JUCE message handling thread seemed not to be stuck.
I’m working with the up-to-date JUCE 4.2.1 from github.
But i could fix it by luck: in the Activity java code i changed the onPause() mehtod to the following:
Well, I’m not sure what’s causing it. But when I was debugging (Android Studio) and set a breakpoint after suspendApp();
, then the problem never occured. So I presumed that native call might need some more time to finish. When the problem arised (black sceen on resuming the app) and I stop the debugger, the thread report looks like this (still waiting in surfaceDestroyedNative):
"Juce Message Thread@3975" prio=5 runnable
java.lang.Thread.State: RUNNABLE
at de.tud.inf.audiometer.MultitoneAudiometer$NativeSurfaceView.surfaceDestroyedNative(MultitoneAudiometer.java:-1)
at de.tud.inf.audiometer.MultitoneAudiometer$NativeSurfaceView.surfaceDestroyed(MultitoneAudiometer.java:856)
at android.view.SurfaceView.updateWindow(SurfaceView.java:567)
at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:239)
at android.view.View.dispatchWindowVisibilityChanged(View.java:9647)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1309)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1309)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1309)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1309)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1309)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1383)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
at android.view.Choreographer.doCallbacks(Choreographer.java:670)
at android.view.Choreographer.doFrame(Choreographer.java:606)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Method.java:-1)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
"FinalizerDaemon@4023" daemon prio=5 waiting
java.lang.Thread.State: WAITING
blocks FinalizerDaemon@4023
at java.lang.Object.wait(Object.java:-1)
at java.lang.Object.wait(Object.java:423)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:101)
- locked <0xfc8> (a java.lang.ref.ReferenceQueue)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:72)
at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:185)
at java.lang.Thread.run(Thread.java:818)
"FinalizerWatchdogDaemon@4021" daemon prio=5 waiting
java.lang.Thread.State: WAITING
blocks FinalizerWatchdogDaemon@4021
at java.lang.Object.wait(Object.java:-1)
at java.lang.Daemons$FinalizerWatchdogDaemon.waitForObject(Daemons.java:255)
- locked <0xfc7> (a java.lang.Daemons$FinalizerWatchdogDaemon)
at java.lang.Daemons$FinalizerWatchdogDaemon.run(Daemons.java:227)
at java.lang.Thread.run(Thread.java:818)
"ReferenceQueueDaemon@4019" daemon prio=5 waiting
java.lang.Thread.State: WAITING
blocks ReferenceQueueDaemon@4019
at java.lang.Object.wait(Object.java:-1)
at java.lang.Daemons$ReferenceQueueDaemon.run(Daemons.java:147)
- locked <0xbdc> (a java.lang.Class)
at java.lang.Thread.run(Thread.java:818)
"HeapTaskDaemon@4022" daemon prio=5 waiting for monitor entry
java.lang.Thread.State: BLOCKED
at dalvik.system.VMRuntime.runHeapTasks(VMRuntime.java:-1)
at java.lang.Daemons$HeapTaskDaemon.run(Daemons.java:355)
at java.lang.Thread.run(Thread.java:818)
"Pool@4003" prio=5 runnable
java.lang.Thread.State: RUNNABLE
at de.tud.inf.audiometer.MultitoneAudiometer$JuceThread.runThread(MultitoneAudiometer.java:-1)
at de.tud.inf.audiometer.MultitoneAudiometer$JuceThread.run(MultitoneAudiometer.java:1293)
"Juce Timer@4006" prio=7 runnable
java.lang.Thread.State: RUNNABLE
at de.tud.inf.audiometer.MultitoneAudiometer$JuceThread.runThread(MultitoneAudiometer.java:-1)
at de.tud.inf.audiometer.MultitoneAudiometer$JuceThread.run(MultitoneAudiometer.java:1293)
"Signal Catcher@4018" daemon prio=5 waiting
java.lang.Thread.State: WAITING
Incompatible thread state: thread not suspended
"Binder_1@4020" prio=5 runnable
java.lang.Thread.State: RUNNABLE
Incompatible thread state: thread not suspended
"Binder_2@4024" prio=5 runnable
java.lang.Thread.State: RUNNABLE
Incompatible thread state: thread not suspended
"Binder_3@4017" prio=5 runnable
java.lang.Thread.State: RUNNABLE
Incompatible thread state: thread not suspended
This is probably caused from drawing to the OpenGL context after the app is suspended. Giving the app 1s more time allows finalized rendering/animations to happen and complete.
For some the 1000ms time wait may be enough, depending on your app style. However its kind of a hack that does not really address the issue of allowing rendering to happen after an app is suspended.
I cannot attest if that part has been fixed in the latest tip as I am still using 3.0 (modified to my uses).
It would be really good to know if this still occurs on the latest branch (master or develop). We rewrote most of the OpenGL thread handling on Android to avoid the bug that you are reporting.