Phil Hassey - game dev blog
Phil Hassey as Syndrome
"Look, stores don't sell
costumes like this to just anyone."

Android Day 8: Bug fixin’

Step 1: Handling Back / Menu events.

Several people mentioned that it’s common to respond to pressing the BACK / MENU / HOME / SEARCH buttons on the bottom of your Android device. At least, BACK / MENU. I investigated the options and there are some methods for Activity that can be added doBackPressed, onMenuOpened, onUserLeaveHint, onSearchRequested. However, not all of these are supported in Android 1.6 (doBackPressed). And also, they all seem to work a bit differently.

What I found was a more direct approach to dealing with this was to capture the KeyUp events in onKeyUp. The keycodes are KEYCODE_BACK, KEYCODE_MENU, KEYCODE_HOME, KEYCODE_SEARCH. To capture them you just return “true” from that method and they won’t work anymore, except for HOME which works all the time, so leave that alone. If you really care, you’ll need to use onUserLeaveHint. Ideally you’d check for isCancelled, but again that’s not supported on older devices. I set up Galcon to intercept the BACK and MENU buttons to send an event to my code to fall back to pause screens. And I set it up to ignore the SEARCH button so that a user wouldn’t accidentally bring it up in-game. The HOME button I left alone.

Step 2: Getting OpenGL ES 1.0 compliance

I found that on low-end Android devices like the G1 and the Droid Eris, the visuals were not displaying properly and the log was showing a ton of “E/libEGL ( 494): called unimplemented OpenGL ES API” errors.

This was due to my use of the “glColor4ub” function which apparently isn’t supported. I changed those calls to “glColor4f” and that resolved that issue. I never found a decent way to figure out what function was causing the errors, I just figured it out by guesswork and trial and error. If someone has a tip here, that would be pretty great.

One issue I’m having is that the emulator running 1.6 is not displaying the game at all. I tried it with 2.1 on the emulator and it also does not display the game, so it looks like I might need to quickly attempt to acquire a G1 to do low-end testing on.

I also ran up against the GL stack at some point and had to reduce the number of glPushMatrix and glPopMatrix’s I was doing. A hint here is use glGetError() to find out if you’re getting any errors. This also seemed to clear up the emulator issues, but the emulator is running so slowly that I really can’t use it.

Step 3: Better keyboard support.

I found the soft keyboard input wasn’t always working quite right. This code snippet seemed to work better, maybe. The choice of SHOW_IMPLICITY or SHOW_FORCED is a lesser of two evils decision. Time will tell which decision will give me more tech support issues.

    public void toggle_keyboard(boolean show) {
        InputMethodManager mgr = (InputMethodManager)app.getSystemService(Context.INPUT_METHOD_SERVICE);
        mgr.hideSoftInputFromWindow (mGLSurfaceView.getWindowToken(),0);
        if (show) {
            mgr.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
            // On the Nexus One, SHOW_FORCED makes it impossible
            // to manually dismiss the keyboard.
            // On the Droid SHOW_IMPLICIT doesn't bring up the keyboard.
        }
    }

I wish there was a better way to do this that worked a bit more consistently, but this is the best I’ve come up with so far.

Step 4: Getting the application to quit and restart cleanly

It was requested that the “BACK” button quit the app from the main menu, which is the usual behavior of most apps. I added the call to finish() to force this to happen, but I found that whenever the app was launched again it would crash once, then on a second try it would work.

What was happening was this: the shared library “libigalcon2.so” was not being reloaded, so due to some failure on my part to smartly handle that, there were some critical values that were not being reset when the app relaunched. I had to carefully make sure to initialize those values on each start of my app. Here’s the symptom that clued me in:

D/dalvikvm(21863): Trying to load lib
    /data/data/com.galcon.igalcon/lib/libigalcon2.so 0x447a7048
D/dalvikvm(21863): Shared lib
    '/data/data/com.galcon.igalcon/lib/libigalcon2.so' already loaded in same CL 0x447a7048

Also note that the JNI_OnLoad was not being called each time my app was started up. It was only called the first time the shared library was loaded, so that was why on second launch my app would crash. (The real problem was I was saving the JNIEnv as a global variable, and it was not being reset when my app restarted.) Lesson learned: be very careful with globals!

Whew, that was a long day .. But we’re getting closer and closer to being ready!  The beta testers now report that the game is working nicely on all devices.  But they report that the framerate is awful on the G1 still, so we’re going to investigate improving frame rate yet.

-Phil

5 Responses to “Android Day 8: Bug fixin’”

  1. Mark Says:

    You’re still on day 7?

  2. philhassey Says:

    Good call, “Day 7” updated to “Day 8” 🙂

    This port is taking a bit of time ‘eh !

    -Phil

  3. Mark Says:

    “If the port isn’t working in about a week, I’ll be giving up.”

    You had better hurry, “about a week” is almost up!

    : P

  4. philhassey Says:

    Man, I get no slack here 😉

  5. shinmai Says:

    It’s quite impossible for me to explain how damn awesome it is that you’re porting Galcon to Android. I love Galcon Fusion, it’s one of my favorite PC games of all time, and it’d be awesome beoynd words to be able to play a version of the game on the go.

    As an aspiring android developer it’s also awesome to see you post your thoughts and snippets of code as you progress. You, sir, are a great man.