Android Day 5: Keyboard, Multiplayer / Networking
After a weekend of recouping from last week’s barrage of code .. I’m back!
Step 1 – Displaying the Software Keyboard:
Okay, the keyboard took forever to figure out. In fact half of Day 4 was burned on this one. I’m not going to go into the horrifying details, but here’s the best hack I could come up with to show and hide the android keyboard on demand. I’ll leave the JNI integration as an exercise to the reader. (I also have included the event handler, this is pretty straightforward, but clearly demonstrates the obtuseness of Java APIs. In python, this would certainly be simpler 😉 Anyway, this code can be pasted into your main Activity where “app” is a static reference to your Activity object.
boolean _keyboard_state = false; public void toggle_keyboard() { InputMethodManager mgr = (InputMethodManager)app.getSystemService(Context.INPUT_METHOD_SERVICE); mgr.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT,0); app._keyboard_state = !app._keyboard_state; } // JNI used to call this from C/C++ public static void show_keyboard() { Log.v("keyboard","show"); if (!app._keyboard_state) { app.toggle_keyboard(); } } // JNI used to call this from C/C++ public static void hide_keyboard() { Log.v("keyboard","hide"); if (app._keyboard_state) { app.toggle_keyboard(); } } public boolean onKeyDown(int keycode, KeyEvent e) { Log.v("keydown",Character.toString(Character.toChars(e.getUnicodeChar())[0])); // native call to send Event to C/C++ code return true; }
And now we’re onto ..
Step 2 – Debugging Multiplayer:
Testing multiplayer. Well, it appears we might be entering some trouble. First of all, it seems I have to enable permission for my app to access the internet. I add this into my AndroidManifest.xml:
<ses-permission android:name="android.permission.INTERNET" />
This seemed to get it to do something, but usually that something is SIGSEGV. Time to fire up GDB. Earlier I covered basic debugging, but not how to use GDB with the Android. Basically, in the NDK, you’ll want to read “docs/NDK-GDB.TXT” .. Unfortunately this seems to crash the event loop in Java somehow everytime. So it isn’t doing me any good.
– When I first start gdb it gives me: “0xafd0eb68 in ?? ()” which blocks all event handling.
– I tell it to “continue” which seems to get things going again.
– But when it hits the MP code that crashes, it says
Child terminated with signal = b Program terminated with signal SIGSEGV, Segmentation fault. The program no longer exists. (gdb) Child terminated with signal = 0xb (SIGSEGV) GDBserver exiting (gdb) backtrace No stack.
So my attempt at getting a backtrace is futile. Huh. This made me think maybe I’m coming into some kind of multi-threading issue. (While the events were blocked, the logic loop and graphics continued, indicating some two separate threads.) ndk-gdb does not support multi-threaded apps. The Galcon code is also single threaded, so it can’t cope with multi-threaded stuff either. I went to all my native methods and added the synchronized keyword:
public synchronized native void event(....);
This cleared up some of my crashes. Â However, when joining a server I get a SIGBUS, which I’m not entirely sure what it is, but it sounds like a SIGSEG except worse.
This could be an alignment error. I’ll download enet 1.2.2 as it includes a changelog item: “now uses packed attribute for protocol structures on platforms with strange alignment rules” .. IIRC, I fixed that in my local copy of Enet to get it working on the iPad, but I’ll check this version out. And thanks to the general awesomeness of ENet the packing bug is fixed, so now I’ve got full-mulitplayer working. Embarrassingly enough I got noob-stomped pretty bad.
July 27th, 2010 at 8:36 am
I hope everything will go right on this port, I would like to kick some iPhone ass against my co-workers 😀