Sunday, March 30, 2014

Creating a simple soft keyboard for Android

Preface
Being able to have your own customized keyboard could become very handy and it could be fun. It gives you flexibility and versatility while your are using different apps. Especially, if you are going to use apps in different languages. Although you could find third party keyboards, they might not meet your requirements or you can not trust them. The important issue regarding third party keyboards is security. Since all your input data are being processed by third party keyboard,  they can steal all your information such as passwords quite easily without your consent.

Scenario
We are going to develop a single language keyboard. That is a keyboard supporting only one language. Note that, there are lots of capabilities I'm not covering. Here, I'm just trying to pave the way. Take the liberty to extend and bring new features to the keyboard you need. You can use whatever language characters you like in your keyboard.

Solution
So lets get our hands dirty. I tried to put comments in the code and make it self-explanatory. If you want  to develop your keyboard all you need are the classes and files below.
  •  android.inputmethodservice.InputMethodService : 
Provides standard implementation of an inputService that can be a keyboard, a drawable area or an speech recognition. In our case I'm rendering it as soft keyboard. 
  •  android.inoutmethodservice.KeyboardView.OnKeyboardActionListener : 
Provides us with the capability to listen for keyboard events.

public class InputMethod extends InputMethodService implements
  KeyboardView.OnKeyboardActionListener {

 private Keyboard keyboard;
 private KeyboardView keyboardView;

//Initializes the interface
 @Override
 public void onInitializeInterface() {
  super.onInitializeInterface();
//XML description of our keyboard
  keyboard = new Keyboard(this, R.xml.language_keys);
 }

 @Override
 public View onCreateInputView() {
  keyboardView = (KeyboardView) getLayoutInflater().inflate(
    R.layout.language_input, null);
  keyboardView.setOnKeyboardActionListener(this);
  //Setting our keyboard on to this view
  keyboardView.setKeyboard(keyboard);
  return keyboardView;
 }

//Here is our key Listener. It will get called when user touches a key 
 @Override
 public void onKey(int primaryCode, int[] keyCodes) {
    
  /*
   * If you need to attach a debugger in your project you can 
   * wait for the debugger as below. Otherwise comment out the 
   * line below.
   */
  android.os.Debug.waitForDebugger(); 
  
   /* We are trying to make a sound and a little vibration
    * when user clicks on any keys. AUDIO_SERVICE AND VIBRATOR_SERVICE are 
    * constants defined in android.content.Context
    */
  AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
  Vibrator vb = (Vibrator) getSystemService(VIBRATOR_SERVICE);
  vb.vibrate(50);
  am.playSoundEffect(AudioManager.FX_KEY_CLICK, 0.5f);

  if (primaryCode == Keyboard.KEYCODE_DELETE) {
   handleDelete();
  } else {
   handleCharacter(primaryCode, keyCodes);
  }
 }

 private void handleDelete() {
  //Dispatching delete event to the currently focused view. 
   The view could be TextView or EditText
  getCurrentInputConnection().sendKeyEvent(
    new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
 }

 private void handleCharacter(int primaryCode, int[] keyCodes) {
  InputConnection conn = getCurrentInputConnection();
  //Enters text to the currently active view (EditText).
    1 moves the cursor after the full text
  conn.commitText(String.valueOf((char) primaryCode), 1);
 }
//Rest of the code
}

  • R.xml.language_keys :
Defines the keyboard keys layout. As it is shown below you can see we have defined one row of our soft keyboard with only on key in it. Character "a". 97 is the decimal representation of character a. For the android:popupKeyboard="xml/popup_keys" read the definition of the next bullet point. You can have many rows and more than one key in a row. Here, only part of the file is shown. This file goes to xml folder of your project.

<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="10%p"
    android:horizontalGap="0px"
    android:verticalGap="0px"
    android:keyHeight="50dip">

   <Row android:keyWidth="10%p">
        <Key android:codes="97" 
             android:keyLabel="&#97;"
             android:popupCharacters="&#65;" 
             android:popupKeyboard="@xml/popup_keys" />
   </Row>
</Keyboard>
  • popup_keys : 
 XML representation of the popup keyboard containing alternate keys. This representation has a default layout. The character defined in the previous section as android:popupCharacters will be shown in this keyboard.  This view will be shown to the user when he log press on a key having this popup  character defined. This file goes to xml folder of your project.

<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="10%p"
    android:horizontalGap="0px"
    android:verticalGap="0px"
    android:keyHeight="50dp">
</Keyboard>

  • R.layout.language_input :
I could not find any better description as android documentation itself. "A view that renders a virtual Keyboard. It handles rendering of keys and detecting key presses and touch movements." This file goes to layout folder of your project.
<android.inputmethodservice.KeyboardView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/keyboard"
        android:layout_alignParentBottom="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />


  • method.xml : 
Defines metadata for the service. The content of this file could be as below. This file will be referenced in android manifest file with meta-data tag name android:name="android.view.im".

<input-method xmlns:android="http://schemas.android.com/apk/res/android">
    <subtype android:imesubtypelocale="en_US" 
                android:imesubtypemode="keyboard" 
                android:label="English">
    </subtype>
</input-method>

1 comment :

  1. Looks great mate, are you interested in uploading the complete project somewhere so I can learn from that as well?
    Cheers!!

    ReplyDelete