onPrepareOptionsMenu crashes

216 views
Skip to first unread message

luke...@gmail.com

unread,
Jun 6, 2014, 11:28:17 AM6/6/14
to codenameone...@googlegroups.com

I have code setup that periodically restructures the menu, and other stuff onscreen, after show events and certain other events (like custom ones emitted when you login)

The code is inside a base class that extends Form, and every other form I've made extends it so they al have the same functionality and menu items by default.

FormInitializer()
       addShowListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
...
updateEventBar();
                                updateCommands();
if(addActionBar)
BaseActivity.super.addComponent(actionBar);
verifyUser(UserManager.getID());
            }
        });

protected final void updateCommands() {

        removeAllCommands();

try {
Resources images = Resources.open("/images.res");
if (UserManager.isLogged()) {
addCommand(new Command("Logout", images.getImage("ic_action_backspace.png"), ID_USER_LOGOUT));
addCommand(new Command("My Profile", images.getImage("ic_action_person.png"), ID_NAVIGATE_HOME));
}
addCommand(new Command("Preferences", images.getImage("ic_action_settings.png"), ID_SHOW_PREFERENCES));

addCommand(new Command("Search", images.getImage("ic_action_search.png"), ID_START_SEARCH));
} catch (Throwable t) {
Log.e(t);
}
        if (extraCommands == null) {
            Vector<Command> vectorCommands = additionalCommands();
            extraCommands = vectorCommands.toArray(new Command[vectorCommands.size()]);
        }

        for (Command com : extraCommands) {
            addCommand(com);
        }


And every so often when switching from one form to another, it crashes with the following exception:

E/AndroidRuntime( 9080): java.lang.NullPointerException
E/AndroidRuntime( 9080): at com.codename1.impl.android.CodenameOneActivity.onPrepareOptionsMenu(CodenameOneActivity.java:470)
E/AndroidRuntime( 9080): at android.app.Activity.onPreparePanel(Activity.java:2556)
E/AndroidRuntime( 9080): at com.android.internal.policy.impl.PhoneWindow.preparePanel(PhoneWindow.java:464)
E/AndroidRuntime( 9080): at com.android.internal.policy.impl.PhoneWindow.doInvalidatePanelMenu(PhoneWindow.java:800)
E/AndroidRuntime( 9080): at com.android.internal.policy.impl.PhoneWindow$1.run(PhoneWindow.java:221)
E/AndroidRuntime( 9080): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
E/AndroidRuntime( 9080): at android.view.Choreographer.doCallbacks(Choreographer.java:574)
E/AndroidRuntime( 9080): at android.view.Choreographer.doFrame(Choreographer.java:543)
E/AndroidRuntime( 9080): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
E/AndroidRuntime( 9080): at android.os.Handler.handleCallback(Handler.java:733)
E/AndroidRuntime( 9080): at android.os.Handler.dispatchMessage(Handler.java:95)
E/AndroidRuntime( 9080): at android.os.Looper.loop(Looper.java:136)
E/AndroidRuntime( 9080): at android.app.ActivityThread.main(ActivityThread.java:5001)
E/AndroidRuntime( 9080): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 9080): at java.lang.reflect.Method.invoke(Method.java:515)
E/AndroidRuntime( 9080): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
E/AndroidRuntime( 9080): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
E/AndroidRuntime( 9080): at dalvik.system.NativeStart.main(Native Method)


Wondering how I can avoid this issue, and if its possible to make small changes, a class here or there, to the codename one source and upload it to the build servers instead of having to do an offline build to change core functionality.

Thanks

Shai Almog

unread,
Jun 6, 2014, 1:31:51 PM6/6/14
to codenameone...@googlegroups.com, luke...@gmail.com
This happens when the name of the command is null.

luke...@gmail.com

unread,
Jun 7, 2014, 10:50:43 AM6/7/14
to codenameone...@googlegroups.com, luke...@gmail.com
After doing a lot of debugging (stuck some .getCommandName() == null asserts everywhere), I fixed this by adding Display.getInstance().callSerially inside of my show listener.
It didn't seem to ever assert that a command was actually null, and I couldn't find anything else abnormal, it only seemed to happen if someone spammed between forms really obnoxiously.

Is there a chance that the show listener is in another thread or something?
Should I be reimplementing the onShow method instead?

            addShowListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
Display.getInstance().callSerially(new Runnable() {
public void run() {
...
updateCommands();
...
}
});
            }
        });

Shai Almog

unread,
Jun 7, 2014, 11:02:55 AM6/7/14
to codenameone...@googlegroups.com, luke...@gmail.com
No, all events occur on the EDT. What does updateCommands do?

luke...@gmail.com

unread,
Jun 7, 2014, 11:43:12 AM6/7/14
to codenameone...@googlegroups.com, luke...@gmail.com
Posted a snippet of it in the first post, basically just removes all the commands than remakes them, some forms have extra commands but all forms have a set of base commands like logout (if you're logged in), preferences, and so on.
Because of the amount of different contextual commands my app needs, like logout, event management, and other stuff that relies on the state of your account and other things from the website, this method is called everytime a form shows, and randomly when internal classes like UserManager emit an update (verifyUser).
After you said it was probably a command without a name, I checked into the android implementation on google code, and noticed that would make sense, and I have a method "protected Vector<Command> additionalCommands()" that lets subclasses provide additional commands to the forms in my app.
So I was thinking maybe somewhere I had a null, and so I added asserts everywhere to check if the command, or its name was ever null, and none of the asserts ever activated.
Ever since I added callSerially its been working fine though, I can spam between forms without any issues.

Shai Almog

unread,
Jun 8, 2014, 1:08:50 AM6/8/14
to codenameone...@googlegroups.com, luke...@gmail.com
It seems we have a race condition in the implementation layer. We're looking into this.

rafae...@gmail.com

unread,
Jul 3, 2016, 12:05:32 AM7/3/16
to CodenameOne Discussions, luke...@gmail.com
I have same error. In my case beside options menu I have Drawer menu with custom DialogFragment.
If I disable my custom dialog inflating, NullPointerError disappears.



private class DrawerItemClickListener implements android.widget.AdapterView.OnItemClickListener {
 
@Override
 
public void onItemClick(AdapterView parent, View view, int position, long id) {
 
if (position >= 10) {
 openPopupInfo
(position);
 
} else {
 selectItem
(position);
 
}
 
}

}

private void openPopupInfo(int position) {
 
switch (position){
 
case 11:
 
if (sidebarInfo != null) {
 
MoneyExchangeDialogFragment dialog = MoneyExchangeDialogFragment.newInstance(sidebarInfo.getCurrency());
 dialog
.show(getSupportFragmentManager(), "dialog");
 
Toast.makeText(MainActivity.this, "Open Exchange Popup", Toast.LENGTH_SHORT).show();
 
}
 
}
}



Shai Almog

unread,
Jul 3, 2016, 1:28:07 AM7/3/16
to CodenameOne Discussions, luke...@gmail.com, rafae...@gmail.com
There are some inherent bugs in Android actionbar we no longer recommend using the native menus and have switched to Toolbar by default.
Reply all
Reply to author
Forward
0 new messages