Android App crashes on back button press

So far everything is working for me on android right now… except it crashes when I press the back button to close the app or do anything else.
It gives me the following error: com.roli.juce.JuceApp cannot be cast to android.app.Activity

The complete console output is:

2019-03-03 00:40:14.794 24523-24523/com.dustvoice.communicare_ev.client E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.dustvoice.communicare_ev.client, PID: 24523
    java.lang.ClassCastException: com.roli.juce.JuceApp cannot be cast to android.app.Activity
        at com.roli.juce.ComponentPeerView.onKeyDown(ComponentPeerView.java:243)
        at android.view.KeyEvent.dispatch(KeyEvent.java:2688)
        at android.view.View.dispatchKeyEvent(View.java:11712)
        at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1822)
        at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4768)
        at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4640)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4175)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4228)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4194)
        at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4321)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4202)
        at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4378)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4175)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4228)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4194)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4202)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4175)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4228)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4194)
        at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4354)
        at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:4515)
        at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2465)
        at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:2028)
        at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:2019)
        at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2442)
        at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
        at android.os.MessageQueue.nativePollOnce(Native Method)
        at android.os.MessageQueue.next(MessageQueue.java:325)
        at android.os.Looper.loop(Looper.java:142)
        at android.app.ActivityThread.main(ActivityThread.java:6798)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

This was reported in https://github.com/WeAreROLI/JUCE/issues/492 and fixed on the develop branch in https://github.com/WeAreROLI/JUCE/commit/6eab395204353d087a2ba4404dfbfa0f270aa319.

1 Like

Yep, I’ll cherry pick that onto master too.

Although it doesn’t crash anymore in the developer branch, it stops working rather fast: take the NativeAndroidJuceSample, add a GUI component (NewComponent) and put a rotary slider on it. Then instead of ‘Slider juceComponent’ in NativeAndroidJuceActivity.cpp, use NewComponent juceComponent; and include the header.
The back button stops working after moving the slider. When pushing the button to remove the Juce component, you can use the back button.

What is the “NativeAndroidJuceSample”? Can you reproduce this with any of the JUCE examples or a simple test app?

It was one of your examples some time ago:

Kind regards,

Davy

eXtream Software Development

http://www.extreamsd.com

What is the expected behaviour? I’ve just tried it and when pressing the back button it returns to the device’s home screen. If you want to do some specific behaviour when the user presses the back button you can override JUCEApplicationBase::backButtonPressed().

Did you do:

"add a GUI component (NewComponent) and put a rotary slider on it. Then instead of ‘Slider juceComponent’ in NativeAndroidJuceActivity.cpp, use NewComponent juceComponent; and include the header.

The back button stops working after moving the slider. When pushing the button to remove the Juce component, you can use the back button." ?

Kind regards,

Davy

eXtream Software Development

http://www.extreamsd.com

Yes… Are you using the emulator or a hardware device? Can you reproduce this with one of the JUCE examples like the DemoRunner?

Hardware device. This is the only applicable example for my use case (using JUCE in an existing app) that I found, so I didn’t try further. It’s probably some kind of focus thing.

Kind regards,

Davy

eXtream Software Development

http://www.extreamsd.com

Still not fixed in the latest version

This should now be fixed in 937991c. Pressing the back button on Android will now call Activity.finish() unless JUCEApplicationBase::backButtonPressed() has been overridden to do some custom back button press handling and returns true.

Thanks, that should fix it indeed. However, looking more into the issue and having made a work-around myself yesterday, I came to the conclusion that my use case might just deviate too much from ‘normal use’. In general though, back could also mean going back a fragment, not necessarily finishing an activity, so the fix would not work for everyone.

I sometimes need to handle the back-button with custom code to go back to another screen. So what I did was define a CustomKeyHandler interface class with a backButtonPressed() method that I call from the handleBackButtonCallback() call when no ApplicationBase is present and implement that method somewhere in a class that also derives from CustomKeyHandler. I also added a method to set the CustomKeyHandler to Component and this now works satisfactory to my needs.

Just as the Native Juce Example code, my app does not have an ApplicationBase, since it’s neither a plug-in or stand-alone app in the sense that JUCE handles the Android lifecycle etc. It will host several JUCE PluginProcessor’s from a third party and my own custom code that will use JUCE, primarily for cross-platform graphics/UI. So I am aware that in normal situations, one would roll their own ApplicationBase and just override that backButtonPressed() method. Anyway, I’m happy that JUCE is open source and I could roll my own custom solution.