ioPixel's blog

More Mobile applications ;-)

Virtual Keyboard Input with NDK

Some Moblox users reported that they had an issue with their delete key when they wanted to enter their name in the text box.

Moblox is mostly written in C++ and we have to use a trick to open the virtual keyboard. The same trick that Phil Hassey (Galcon developer) described on his blog.

After some investigation, it was clear that the problem come from Swype (or other alternative keyboards): the delete key is not intercepted by our code, in fact the DELETE key events are not generated by these alternative virtual keyboards.

Currently, the only solution was to tell our users to switch to the default keyboard to enter text in Moblox.

Two solutions:

  • develop your own virtual keyboard as Polarbit (Raging Thunder). Elegant but no real keyboard support;
  • use an Android TextView in an AlertDialog from the Java code and send text with JNI to your (native C++) edit box;

For our next release (1.0.7), we developed the second approach.
First we declare two attributes in the main activity:

public class MobloxActivity extends Activity {
public AlertDialog mTextInputDialog;
public EditText mTextInputWidget;
...

In the onCreate Method of this activity, we instantiate an AlertDialog

AlertDialog.Builder builder = new AlertDialog.Builder(this);
mTextInputWidget = new EditText(this);
mTextInputWidget.setHint("Please enter your username");
builder.setTitle("Username");
builder.setMessage("Please enter your username");
builder.setPositiveButton("done", null);
builder.setNegativeButton("cancel", null);

builder.setView(mTextInputWidget);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
  public void onClick(DialogInterface dialog, int whichButton) {
    nativeSendInputText(mTextInputWidget.getText().toString());
  }
});

builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
  public void onClick(DialogInterface dialog, int whichButton) {
    dialog.cancel();
  }
});
mTextInputDialog = builder.create();

Then, we declare a method to send text typed by user to our native layer via JNI.

public static native void nativeSendInputText(String text);

Code to show the AlertDialog. This method is called by the C part in the rendering Thread:

public static void showInputText(String text) {
  final String iText = text;
  sActivity.mHandler.post(new Runnable() {
    public void run() {
      sActivity.mTextInputWidget.setText(iText);
      sActivity.mTextInputDialog.show();
      InputMethodManager imm = (InputMethodManager)
      sActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
      imm.hideSoftInputFromWindow(sActivity.mTextInputWidget.getWindowToken(), 0);
      imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
      sActivity.mTextInputWidget.requestFocus();
    }
  });
}