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)
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 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().
"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." ?
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.
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.