Showing posts with label custom keyboard android example. Show all posts
Showing posts with label custom keyboard android example. Show all posts

Monday, May 2, 2016

Developing your own keyboard

Writing/ Developing your own keyboard is easy task,

follow the steps given below and you will have your own keyboard in your cellpahone.

1. Create a normal Android Project using Android Studio.

2. Edit Application tab in Manifest;
    Add the following lines into Application tab

<service
    android:name=".utils.SoftKeyboard"
    android:permission="android.permission.BIND_INPUT_METHOD">
    <intent-filter>
        <action android:name="android.view.InputMethod" />
    </intent-filter>
    <meta-data
        android:name="android.view.im"
        android:resource="@xml/method" />
</service>

<activity
    android:name=".activities.ImePreferences"
    android:label="@string/settings_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
    </intent-filter>
</activity>

3. Create a folder "xml" in res and Create method.xml

paste following line to method.xml

<input-method xmlns:android="http://schemas.android.com/apk/res/android"
    android:settingsActivity="com.example.android.softkeyboard.ImePreferences"
    android:supportsSwitchingToNextInputMethod="true">
    <subtype
        android:imeSubtypeLocale="en_US"
        android:imeSubtypeMode="keyboard"
        android:label="Ankit" />
    <subtype
        android:imeSubtypeLocale="en_GB"
        android:imeSubtypeMode="keyboard"
        android:label="Ankit" />
</input-method>

4. Create input keyboard layout input.xml in res/layout

<?xml version="1.0" encoding="utf-8"?>
<com.divyankit.keyboard.utils.LatinKeyboardView
xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/keyboard"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true" />



5.  Java Code for LatinKeyboardView is here

LatinKeyboardView.java

public class LatinKeyboardView extends KeyboardView {
    static final int KEYCODE_OPTIONS = -100;
    static final int KEYCODE_LANGUAGE_SWITCH = -101;
    static final int KEYCODE_API = -600;

    public LatinKeyboardView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public LatinKeyboardView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override    protected boolean onLongPress(Key key) {
        if (key.codes[0] == Keyboard.KEYCODE_CANCEL) {
            getOnKeyboardActionListener().onKey(KEYCODE_OPTIONS, null);
            return true;
        } else {
            return super.onLongPress(key);
        }
    }

    void setSubtypeOnSpaceKey(final InputMethodSubtype subtype) {
        final LatinKeyboard keyboard = (LatinKeyboard) getKeyboard();
         
         // keyboard.setSpaceIcon(getResources().getDrawable(subtype.getIconResId()));    
         // keyboard.setShifted(true);       
        
        invalidateAllKeys();
    }
}


6. Java Code for LatinKeyboard is here
LtinKeyboard.java
public class LatinKeyboard extends Keyboard {
    private Key mEnterKey;
    private Key mSpaceKey;
    
/**
* Stores the current state of the mode change key.
 Its width will be dynamically updated to    
 * match the region of {@link #mModeChangeKey} when {@link #mModeChangeKey} 
becomes invisible.*/

    private Key mModeChangeKey;
/**
* Stores the current state of the language switch key (a.k.a. globe key). This should be     
* visible while {@link InputMethodManager#shouldOfferSwitchingToNextInputMethod(IBinder)}  
   * returns true. When this key becomes invisible, its width will be shrunk to zero.*/
    private Key mLanguageSwitchKey;
    /**
* Stores the size and other information of {@link #mModeChangeKey} when   
* {@link #mLanguageSwitchKey} is visible. This should be immutable and will be used only as a
* reference size when the visibility of {@link #mLanguageSwitchKey} is changed.*/
    private Key mSavedModeChangeKey;
/**
* Stores the size and other information of {@link #mLanguageSwitchKey} when it is visible.
* This should be immutable and will be used only as a reference size when the visibility of 
* {@link #mLanguageSwitchKey} is changed.*/
    private Key mSavedLanguageSwitchKey;

    public LatinKeyboard(Context context, int xmlLayoutResId) {
        super(context, xmlLayoutResId);
    }

    public LatinKeyboard(Context context, int layoutTemplateResId,
                         CharSequence characters, int columns, int horizontalPadding) {
        super(context, layoutTemplateResId, characters, columns, horizontalPadding);
    }

    @Override
    protected Key createKeyFromXml(Resources res, Row parent, int x, int y,
     XmlResourceParser parser) {
        Key key = new LatinKey(res, parent, x, y, parser);
        if (key.codes[0] == 10) {
            mEnterKey = key;
        } else if (key.codes[0] == ' ') {
            mSpaceKey = key;
        } else if (key.codes[0] == Keyboard.KEYCODE_MODE_CHANGE) {
            mModeChangeKey = key;
            mSavedModeChangeKey = new LatinKey(res, parent, x, y, parser);
        } else if (key.codes[0] == LatinKeyboardView.KEYCODE_LANGUAGE_SWITCH) {
            mLanguageSwitchKey = key;
            mSavedLanguageSwitchKey = new LatinKey(res, parent, x, y, parser);
        }
        return key;
    }

/**
* Dynamically change the visibility of the language switch key (a.k.a. globe key). 
* * @param visible True if the language switch key should be visible.     */

void setLanguageSwitchKeyVisibility(boolean visible) {
        if (visible) {
      // The language switch key should be visible. Restore the size of the mode change key  
      // and language switch key using the saved layout.           

 mModeChangeKey.width = mSavedModeChangeKey.width;
            mModeChangeKey.x = mSavedModeChangeKey.x;
            mLanguageSwitchKey.width = mSavedLanguageSwitchKey.width;
            mLanguageSwitchKey.icon = mSavedLanguageSwitchKey.icon;
            mLanguageSwitchKey.iconPreview = mSavedLanguageSwitchKey.iconPreview;
        } else {
      // The language switch key should be hidden. Change the width of the mode change key 
      // to fill the space of the language key so that the user will not see any strange gap.         
            mModeChangeKey.width = mSavedModeChangeKey.width + mSavedLanguageSwitchKey.width;
            mLanguageSwitchKey.width = 0;
            mLanguageSwitchKey.icon = null;
            mLanguageSwitchKey.iconPreview = null;
        }
    }

    /**
* This looks at the ime options given by the current editor, to set the   
* appropriate label on the keyboard's enter key (if it has one).     */ 

    void setImeOptions(Resources res, int options) {
        if (mEnterKey == null) {
            return;
        }
        switch (options & (EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION)) {
            case EditorInfo.IME_ACTION_GO:
                mEnterKey.iconPreview = null;
                mEnterKey.icon = null;
                mEnterKey.label = res.getText(R.string.label_go_key);
                break;
            case EditorInfo.IME_ACTION_NEXT:
                mEnterKey.iconPreview = null;
                mEnterKey.icon = null;
                mEnterKey.label = res.getText(R.string.label_next_key);
                break;
            case EditorInfo.IME_ACTION_SEARCH:
                mEnterKey.icon = res.getDrawable(R.drawable.sym_keyboard_search);
                mEnterKey.label = null;
                break;
            case EditorInfo.IME_ACTION_SEND:
                mEnterKey.iconPreview = null;
                mEnterKey.icon = null;
                mEnterKey.label = res.getText(R.string.label_send_key);
                break;
            default:
                mEnterKey.icon = res.getDrawable(R.drawable.sym_keyboard_return);
                mEnterKey.label = null;
                break;
        }
    }
    void setSpaceIcon(final Drawable icon) {
        if (mSpaceKey != null) {
            mSpaceKey.icon = icon;
        }
    }
    static class LatinKey extends Key {

        public LatinKey(Resources res, Row parent, int x, int y,
                        XmlResourceParser parser) {
            super(res, parent, x, y, parser);
        }
        /**
* Overriding this method so that we can reduce the target area for the key that
* closes the keyboard.         */   
     @Override
        public boolean isInside(int x, int y) {
            return super.isInside(x, codes[0] == KEYCODE_CANCEL ? y - 10 : y);
        }
    }
}

5. Define the Keyboard Keys: 

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:horizontalGap="0px"
    android:keyHeight="@dimen/key_height"
    android:keyWidth="10%p"
    android:verticalGap="0px">
    <Row>
        <Key
            android:codes="113"
            android:keyEdgeFlags="left"
            android:keyLabel="q" />
        <Key
            android:codes="119"
            android:keyLabel="w" />
        <Key
            android:codes="101"
            android:keyLabel="e" />
        <Key
            android:codes="114"
            android:keyLabel="r" />
        <Key
            android:codes="116"
            android:keyLabel="t" />
        <Key
            android:codes="121"
            android:keyLabel="y" />
        <Key
            android:codes="117"
            android:keyLabel="u" />
        <Key
            android:codes="105"
            android:keyLabel="i" />
        <Key
            android:codes="111"
            android:keyLabel="o" />
        <Key
            android:codes="112"
            android:keyEdgeFlags="right"
            android:keyLabel="p" />
    </Row>

    <Row>
        <Key
            android:codes="97"
            android:horizontalGap="5%p"
            android:keyEdgeFlags="left"
            android:keyLabel="a" />
        <Key
            android:codes="115"
            android:keyLabel="s" />
        <Key
            android:codes="100"
            android:keyLabel="d" />
        <Key
            android:codes="102"
            android:keyLabel="f" />
        <Key
            android:codes="103"
            android:keyLabel="g" />
        <Key
            android:codes="104"
            android:keyLabel="h" />
        <Key
            android:codes="106"
            android:keyLabel="j" />
        <Key
            android:codes="107"
            android:keyLabel="k" />
        <Key
            android:codes="108"
            android:keyEdgeFlags="right"
            android:keyLabel="l" />
    </Row>

    <Row>
        <Key
            android:codes="-1"
            android:isModifier="true"
            android:isSticky="true"
            android:keyEdgeFlags="left"
            android:keyIcon="@drawable/sym_keyboard_shift"
            android:keyWidth="15%p" />
        <Key
            android:codes="122"
            android:keyLabel="z" />
        <Key
            android:codes="120"
            android:keyLabel="x" />
        <Key
            android:codes="99"
            android:keyLabel="c" />
        <Key
            android:codes="118"
            android:keyLabel="v" />
        <Key
            android:codes="98"
            android:keyLabel="b" />
        <Key
            android:codes="110"
            android:keyLabel="n" />
        <Key
            android:codes="109"
            android:keyLabel="m" />
        <Key
            android:codes="-5"
            android:isRepeatable="true"
            android:keyEdgeFlags="right"
            android:keyIcon="@drawable/sym_keyboard_delete"
            android:keyWidth="15%p" />
    </Row>

    <Row android:rowEdgeFlags="bottom">
        <Key
            android:codes="-2"
            android:keyLabel="\?123"
            android:keyWidth="12%p" />
        <Key
            android:codes="44"
            android:keyLabel=","
            android:keyWidth="13%p" />
        <Key
            android:codes="-101"
            android:keyIcon="@drawable/sym_keyboard_language_switch"
            android:keyWidth="10%p" />
        <Key
            android:codes="32"
            android:isRepeatable="true"
            android:keyIcon="@drawable/sym_keyboard_space"
            android:keyWidth="35%p" />
        <Key
            android:codes="46"
            android:keyLabel="."
            android:keyWidth="13%p" />
        <Key
            android:codes="10"
            android:keyEdgeFlags="right"
            android:keyIcon="@drawable/sym_keyboard_return"
            android:keyWidth="17%p" />
    </Row>
</Keyboard>  

   // Other layout can be found in github repo


6. Create a Class (Service) 


/** * Created by ankit on 4/4/16. */
   public class SoftKeyboard extends InputMethodService
        implements KeyboardView.OnKeyboardActionListener {
    static final boolean DEBUG = false;
    LinearLayout view;

    /**
  * This boolean indicates the optional example code for performing   
  * processing of hard keys in addition to regular text generation    
  * from on-screen interaction.  It would be used for input methods that  
  * perform language translations (such as converting text entered on   
  * a QWERTY keyboard to Chinese), but may not be used for input methods  
  * that are primarily intended to be used for on-screen text entry.     */  
  static final boolean PROCESS_HARD_KEYS = true;
    private InputMethodManager mInputMethodManager;
    private LatinKeyboardView mInputView;
    private CandidateView mCandidateView;
    private CompletionInfo[] mCompletions;

    private StringBuilder mComposing = new StringBuilder();
    private boolean mPredictionOn;
    private boolean mCompletionOn;
    private int mLastDisplayWidth;
    private boolean mCapsLock;
    private long mLastShiftTime;
    private long mMetaState;

    private LatinKeyboard mSymbolsKeyboard;
    private LatinKeyboard mSymbolsShiftedKeyboard;
    private LatinKeyboard mQwertyKeyboard;

    private LatinKeyboard mCurKeyboard;

    private String mWordSeparators;


    //Added for image upload 
   private String UPLOAD_URL = "http://simplifiedcoding.16mb.com/VolleyUpload/upload.php";
    private static final String KEY_IMAGE = "key_image";
    private static final String KEY_NAME = "key_name";
    private Bitmap bitmap;

    //
    /**
   * Main initialization of the input method component.  Be sure to call  
   * to super class.     */  
  @Override
    public void onCreate() {
        super.onCreate();
        mInputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
        mWordSeparators = getResources().getString(R.string.word_separators);
    }

    /**
      * This is the point where you can do all of your UI initialization.  It  
      * is called after creation and any configuration change.    
      */ 

   @Override 
   public void onInitializeInterface() {
        if (mQwertyKeyboard != null) {
          
   // Configuration changes can happen after the keyboard gets recreated,        
    // so we need to be able to re-build the keyboards if the available        
    // space has changed.       
     int displayWidth = getMaxWidth();
            if (displayWidth == mLastDisplayWidth) return;
            mLastDisplayWidth = displayWidth;
        }
        mQwertyKeyboard = new LatinKeyboard(this, R.xml.qwerty);
        mSymbolsKeyboard = new LatinKeyboard(this, R.xml.symbols);
        mSymbolsShiftedKeyboard = new LatinKeyboard(this, R.xml.symbols_shift);
    }

    /**
     * Called by the framework when your view for creating input needs to  
       * be generated.  This will be called the first time your input method    
      * is displayed, and every time it needs to be re-created such as due to   
         * a configuration change.     */   
 @Override 
   public View onCreateInputView() {
        mInputView = (LatinKeyboardView) getLayoutInflater().inflate(R.layout.input, null);
        mInputView.setOnKeyboardActionListener(this);
        setLatinKeyboard(mQwertyKeyboard);
        return mInputView;
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    private void setLatinKeyboard(LatinKeyboard nextKeyboard) {
        final boolean shouldSupportLanguageSwitchKey =
                mInputMethodManager.shouldOfferSwitchingToNextInputMethod(getToken());
        nextKeyboard.setLanguageSwitchKeyVisibility(shouldSupportLanguageSwitchKey);
        mInputView.setKeyboard(nextKeyboard);
    }


    /**
      * Called by the framework when your view for showing candidates needs to 
    * be generated, like {@link #onCreateInputView}.     */  
 
 @Override 
   public View onCreateCandidatesView() {
        mCandidateView = new CandidateView(this);
        mCandidateView.setService(this);
        return mCandidateView;
    }

    /**
  * This is the main point where we do our initialization of the input method  
  * to begin operating on an application.  At this point we have been     
    * bound to the client, and are now receiving all of the detailed information  
  * about the target of our edits.   
  */    
@Override  
  public void onStartInput(EditorInfo attribute, boolean restarting) {
        super.onStartInput(attribute, restarting);

        // Reset our state.  We want to do this even if restarting, because   
     // the underlying state of the text editor could have changed in any way.     
   mComposing.setLength(0);
        updateCandidates();

        if (!restarting) {
            // Clear shift states.        
    mMetaState = 0;
        }

        mPredictionOn = false;
        mCompletionOn = false;
        mCompletions = null;

        // We are now going to initialize our state based on the type of  
      // text being edited.    
    switch (attribute.inputType & InputType.TYPE_MASK_CLASS) {
            case InputType.TYPE_CLASS_NUMBER:
            case InputType.TYPE_CLASS_DATETIME:
              
           // Numbers and dates default to the symbols keyboard, with    
            // no extra features.              
  mCurKeyboard = mSymbolsKeyboard;
                break;

            case InputType.TYPE_CLASS_PHONE:
                
         // Phones will also default to the symbols keyboard, though 
         // often you will want to have a dedicated phone keyboard.         
       mCurKeyboard = mSymbolsKeyboard;
                break;

            case InputType.TYPE_CLASS_TEXT:
         // This is general text editing.  We will default to the       
         // normal alphabetic keyboard, and assume that we should              
         // be doing predictive text (showing candidates as the
         // user types).        
        mCurKeyboard = mQwertyKeyboard;
                mPredictionOn = true;

          // We now look for a few special variations of text that will      
          // modify our behavior.           
     int variation = attribute.inputType & InputType.TYPE_MASK_VARIATION;
                if (variation == InputType.TYPE_TEXT_VARIATION_PASSWORD ||
                        variation == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) {
       // Do not display predictions / what the user is typing             
       // when they are entering a password.           
         mPredictionOn = false;
                }

                if (variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS 
 || variation == InputType.TYPE_TEXT_VARIATION_URI 
 || variation == InputType.TYPE_TEXT_VARIATION_FILTER) {
                  
  // Our predictions are not useful for e-mail addresses  or URIs.            
        mPredictionOn = false;
                }

                if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
                 
       // If this is an auto-complete text view, then our predictions               
        // will not be shown and instead we will allow the editor         
      // to supply their own.  We only show the editor's         
      // candidates when in fullscreen mode, otherwise relying        
      // own it displaying its own UI.             
            mPredictionOn = false;
                    mCompletionOn = isFullscreenMode();
                }

      // We also want to look at the current state of the editor          
      // to decide whether our alphabetic keyboard should start out            
        // shifted.             
   updateShiftKeyState(attribute);
                break;

            default:
         // For all unknown input types, default to the alphabetic       
         // keyboard with no special features.          
      mCurKeyboard = mQwertyKeyboard;
                updateShiftKeyState(attribute);
        }

        // Update the label on the enter key, depending on what the application   
            // says it will do.      
  mCurKeyboard.setImeOptions(getResources(), attribute.imeOptions);
    }

    /** 
     * This is called when the user is done editing a field.  We can use  
      * this to reset our state.     */  
  @Override   
 public void onFinishInput() {
        super.onFinishInput();

        // Clear current composing text and candidates.   
     mComposing.setLength(0);
        updateCandidates();

    // We only hide the candidates window when finishing input on    
    // a particular editor, to avoid popping the underlying application     
   // up and down if the user is entering text into the bottom of     
   // its window.     
   setCandidatesViewShown(false);
        mCurKeyboard = mQwertyKeyboard;
        if (mInputView != null) {
            mInputView.closing();
        }
    }

    @Override    public void onStartInputView(EditorInfo attribute, boolean restarting) {
        super.onStartInputView(attribute, restarting);
        // Apply the selected keyboard to the input view.   
     setLatinKeyboard(mCurKeyboard);
        mInputView.closing();
        final InputMethodSubtype subtype = mInputMethodManager.getCurrentInputMethodSubtype();
        mInputView.setSubtypeOnSpaceKey(subtype);
    }

    @Override    public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) {
        mInputView.setSubtypeOnSpaceKey(subtype);
    }

    /**     * Deal with the editor reporting movement of its cursor.     */   
 @Override    public void onUpdateSelection(int oldSelStart, int oldSelEnd,
                                  int newSelStart, int newSelEnd,
                                  int candidatesStart, int candidatesEnd) {
        super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
                candidatesStart, candidatesEnd);

   // If the current selection in the text view changes, we should     
   // clear whatever candidate text we have.   
     if (mComposing.length() > 0 && (newSelStart != candidatesEnd
                || newSelEnd != candidatesEnd)) {
            mComposing.setLength(0);
            updateCandidates();
            InputConnection ic = getCurrentInputConnection();
            if (ic != null) {
                ic.finishComposingText();
            }
        }
    }

    /** * This tells us about completions that the editor has determined based    
 * on the current text in it.  We want to use this in fullscreen mode   
  * to show the completions ourself, since the editor can not be seen   
  * in that situation.     */  
  @Override
   public void onDisplayCompletions(CompletionInfo[] completions) {
        if (mCompletionOn) {
            mCompletions = completions;
            if (completions == null) {
                setSuggestions(null, false, false);
                return;
            }

            List<String> stringList = new ArrayList<String>();
            for (int i = 0; i < completions.length; i++) {
                CompletionInfo ci = completions[i];
                if (ci != null) stringList.add(ci.getText().toString());
            }
            setSuggestions(stringList, true, true);
        }
    }

    /**
 * This translates incoming hard key events in to edit operations on an   
  * InputConnection.  It is only needed when using the  
   * PROCESS_HARD_KEYS option.     */  
  private boolean translateKeyDown(int keyCode, KeyEvent event) {
        mMetaState = MetaKeyKeyListener.handleKeyDown(mMetaState,
                keyCode, event);
        int c = event.getUnicodeChar(MetaKeyKeyListener.getMetaState(mMetaState));
        mMetaState = MetaKeyKeyListener.adjustMetaAfterKeypress(mMetaState);
        InputConnection ic = getCurrentInputConnection();
        if (c == 0 || ic == null) {
            return false;
        }

        boolean dead = false;
        if ((c & KeyCharacterMap.COMBINING_ACCENT) != 0) {
            dead = true;
            c = c & KeyCharacterMap.COMBINING_ACCENT_MASK;
        }

        if (mComposing.length() > 0) {
            char accent = mComposing.charAt(mComposing.length() - 1);
            int composed = KeyEvent.getDeadChar(accent, c);
            if (composed != 0) {
                c = composed;
                mComposing.setLength(mComposing.length() - 1);
            }
        }

        onKey(c, null);

        return true;
    }

    /**
* Use this to monitor key events being delivered to the application.   
  * We get first crack at them, and can either resume them or let them   
  * continue to the app.     */  

  @Override    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_BACK:
               
     // The InputMethodService already takes care of the back         
       // key for us, to dismiss the input method if it is shown.           
     // However, our keyboard could be showing a pop-up window        
        // that back should dismiss, so we first allow it to do that.  

              if (event.getRepeatCount() == 0 && mInputView != null) {
                    if (mInputView.handleBack()) {
                        return true;
                    }
                }
                break;

            case KeyEvent.KEYCODE_DEL:
               
       // Special handling of the delete key: if we currently are        
       // composing text for the user, we want to modify that instead      
       // of let the application to the delete itself.        

        if (mComposing.length() > 0) {
                    onKey(Keyboard.KEYCODE_DELETE, null);
                    return true;
                }
                break;

            case KeyEvent.KEYCODE_ENTER:
                // Let the underlying text editor always handle these.        
        return false;

            default:
       // For all other keys, if we want to do transformations on        
        // text being entered with a hard keyboard, we need to process         
       // it and do the appropriate action.      
          if (PROCESS_HARD_KEYS) {
                    if (keyCode == KeyEvent.KEYCODE_SPACE && (event.getMetaState() & KeyEvent.META_ALT_ON) != 0) {
         // A silly example: in our input method, Alt+Space                
        // is a shortcut for 'android' in lower case.

         InputConnection ic = getCurrentInputConnection();
                        if (ic != null) {
           // First, tell the editor that it is no longer in the            
            // shift state, since we are consuming this.       
                ic.clearMetaKeyStates(KeyEvent.META_ALT_ON);
                            keyDownUp(KeyEvent.KEYCODE_A);
                            keyDownUp(KeyEvent.KEYCODE_N);
                            keyDownUp(KeyEvent.KEYCODE_D);
                            keyDownUp(KeyEvent.KEYCODE_R);
                            keyDownUp(KeyEvent.KEYCODE_O);
                            keyDownUp(KeyEvent.KEYCODE_I);
                            keyDownUp(KeyEvent.KEYCODE_D);
                          
            // And we consume this event.            
                return true;
                        }
                    }
                    if (mPredictionOn && translateKeyDown(keyCode, event)) {
                        return true;
                    }
                }
        }

        return super.onKeyDown(keyCode, event);
    }

    /**
* Use this to monitor key events being delivered to the application. 
* We get first crack at them, and can either resume them or let them  
* continue to the app.     */ 
   @Override    public boolean onKeyUp(int keyCode, KeyEvent event) {
    // If we want to do transformations on text being entered with a hard   
     // keyboard, we need to process the up events to update the meta key    
    // state we are tracking.  

      if (PROCESS_HARD_KEYS) {
            if (mPredictionOn) {
                mMetaState = MetaKeyKeyListener.handleKeyUp(mMetaState,
                        keyCode, event);
            }
        }

        return super.onKeyUp(keyCode, event);
    }

    /**
    * Helper function to commit any text being composed in to the editor.  
   */  

  private void commitTyped(InputConnection inputConnection) {
        if (mComposing.length() > 0) {
            inputConnection.commitText(mComposing, mComposing.length());
            mComposing.setLength(0);
            updateCandidates();
        }
    }

    /**
* Helper to update the shift state of our keyboard based on the initial  
   * editor state.     */ 
   private void updateShiftKeyState(EditorInfo attr) {
        if (attr != null && mInputView != null && mQwertyKeyboard == mInputView.getKeyboard()) {
            int caps = 0;
            EditorInfo ei = getCurrentInputEditorInfo();
            if (ei != null && ei.inputType != InputType.TYPE_NULL) {
                caps = getCurrentInputConnection().getCursorCapsMode(attr.inputType);
            }
            mInputView.setShifted(mCapsLock || caps != 0);
        }
    }

    /** * Helper to determine if a given character code is alphabetic.     */   

 private boolean isAlphabet(int code) {
        if (Character.isLetter(code)) {
            return true;
        } else {
            return false;
        }
    }

    /** * Helper to send a key down / key up pair to the current editor.     */  
 
 private void keyDownUp(int keyEventCode) {
        getCurrentInputConnection().sendKeyEvent(
                new KeyEvent(KeyEvent.ACTION_DOWN, keyEventCode));
        getCurrentInputConnection().sendKeyEvent(
                new KeyEvent(KeyEvent.ACTION_UP, keyEventCode));
    }

    /*** Helper to send a character to the editor as raw key events.     */  

  private void sendKey(int keyCode) {
        switch (keyCode) {
            case '\n':
                keyDownUp(KeyEvent.KEYCODE_ENTER);
                break;
            default:
                if (keyCode >= '0' && keyCode <= '9') {
                    keyDownUp(keyCode - '0' + KeyEvent.KEYCODE_0);
                } else {
                    getCurrentInputConnection().commitText(String.valueOf((char) keyCode), 1);
                }
                break;
        }
    }

    // Implementation of KeyboardViewListener  
  public void onKey(int primaryCode, int[] keyCodes) {
        if (isWordSeparator(primaryCode)) {
            // Handle separator            if (mComposing.length() > 0) {
                commitTyped(getCurrentInputConnection());
            }
            sendKey(primaryCode);
            updateShiftKeyState(getCurrentInputEditorInfo());
        } else if (primaryCode == Keyboard.KEYCODE_DELETE) {
            handleBackspace();
        } else if (primaryCode == Keyboard.KEYCODE_SHIFT) {
            handleShift();
        } else if (primaryCode == Keyboard.KEYCODE_CANCEL) {
            handleClose();
            return;
        } else if (primaryCode == LatinKeyboardView.KEYCODE_LANGUAGE_SWITCH) {
            handleLanguageSwitch();
            return;
        } else if (primaryCode == LatinKeyboardView.KEYCODE_OPTIONS) {
            // Show a menu or somethin'        
} else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE && mInputView != null) {
            Keyboard current = mInputView.getKeyboard();
            if (current == mSymbolsKeyboard || current == mSymbolsShiftedKeyboard) {
                setLatinKeyboard(mQwertyKeyboard);
            } else {
                setLatinKeyboard(mSymbolsKeyboard);
                mSymbolsKeyboard.setShifted(false);
            }
        } else {
            handleCharacter(primaryCode, keyCodes);
        }
    }

    public void onText(CharSequence text) {
        InputConnection ic = getCurrentInputConnection();
        if (ic == null) return;
        ic.beginBatchEdit();
        if (mComposing.length() > 0) {
            commitTyped(ic);
        }
        ic.commitText(text, 0);
        ic.endBatchEdit();
        updateShiftKeyState(getCurrentInputEditorInfo());
    }

    /**
    * Update the list of available candidates from the current composing  
     * text.  This will need to be filled in by however you are determining   
      * candidates.     */   

 private void updateCandidates() {
        if (!mCompletionOn) {
            if (mComposing.length() > 0) {
                ArrayList<String> list = new ArrayList<String>();
                list.add(mComposing.toString());
                setSuggestions(list, true, true);
            } else {
                setSuggestions(null, false, false);
            }
        }
    }

    public void setSuggestions(List<String> suggestions, boolean completions,
                               boolean typedWordValid) {
        if (suggestions != null && suggestions.size() > 0) {
            setCandidatesViewShown(true);
        } else if (isExtractViewShown()) {
            setCandidatesViewShown(true);
        }
        if (mCandidateView != null) {
            mCandidateView.setSuggestions(suggestions, completions, typedWordValid);
        }
    }

    private void handleBackspace() {
        final int length = mComposing.length();
        if (length > 1) {
            mComposing.delete(length - 1, length);
            getCurrentInputConnection().setComposingText(mComposing, 1);
            updateCandidates();
        } else if (length > 0) {
            mComposing.setLength(0);
            getCurrentInputConnection().commitText("", 0);
            updateCandidates();
        } else {
            keyDownUp(KeyEvent.KEYCODE_DEL);
        }
        updateShiftKeyState(getCurrentInputEditorInfo());
    }

    private void handleShift() {
        if (mInputView == null) {
            return;
        }

        Keyboard currentKeyboard = mInputView.getKeyboard();
        if (mQwertyKeyboard == currentKeyboard) {
            // Alphabet keyboard            checkToggleCapsLock();
            mInputView.setShifted(mCapsLock || !mInputView.isShifted());
        } else if (currentKeyboard == mSymbolsKeyboard) {
            mSymbolsKeyboard.setShifted(true);
            setLatinKeyboard(mSymbolsShiftedKeyboard);
            mSymbolsShiftedKeyboard.setShifted(true);
        } else if (currentKeyboard == mSymbolsShiftedKeyboard) {
            mSymbolsShiftedKeyboard.setShifted(false);
            setLatinKeyboard(mSymbolsKeyboard);
            mSymbolsKeyboard.setShifted(false);
        }
    }

    private void handleCharacter(int primaryCode, int[] keyCodes) {
        if (isInputViewShown()) {
            if (mInputView.isShifted()) {
                primaryCode = Character.toUpperCase(primaryCode);
            }
        }
        if (isAlphabet(primaryCode) && mPredictionOn) {
            mComposing.append((char) primaryCode);
            getCurrentInputConnection().setComposingText(mComposing, 1);
            updateShiftKeyState(getCurrentInputEditorInfo());
            updateCandidates();
        } else {
            getCurrentInputConnection().commitText(
                    String.valueOf((char) primaryCode), 1);
        }
    }

    private void handleClose() {
        commitTyped(getCurrentInputConnection());
        requestHideSelf(0);
        mInputView.closing();
    }

    private IBinder getToken() {
        final Dialog dialog = getWindow();
        if (dialog == null) {
            return null;
        }
        final Window window = dialog.getWindow();
        if (window == null) {
            return null;
        }
        return window.getAttributes().token;
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    private void handleLanguageSwitch() {
        mInputMethodManager.switchToNextInputMethod(getToken(), false /* onlyCurrentIme */);
    }

    private void checkToggleCapsLock() {
        long now = System.currentTimeMillis();
        if (mLastShiftTime + 800 > now) {
            mCapsLock = !mCapsLock;
            mLastShiftTime = 0;
        } else {
            mLastShiftTime = now;
        }
    }

    private String getWordSeparators() {
        return mWordSeparators;
    }

    public boolean isWordSeparator(int code) {
        String separators = getWordSeparators();
        return separators.contains(String.valueOf((char) code));
    }

    public void pickDefaultCandidate() {
        pickSuggestionManually(0);
    }

    public void pickSuggestionManually(int index) {
        if (mCompletionOn && mCompletions != null
 && index >= 0 && index < mCompletions.length) {
            CompletionInfo ci = mCompletions[index];
            getCurrentInputConnection().commitCompletion(ci);
            if (mCandidateView != null) {
                mCandidateView.clear();
            }
            updateShiftKeyState(getCurrentInputEditorInfo());
        } else if (mComposing.length() > 0) {
            // If we were generating candidate suggestions for the current  
          // text, we would commit one of them here.  But for this sample,      
      // we will just commit the current text.       

     commitTyped(getCurrentInputConnection());
        }
    }

    public void swipeRight() {
        if (mCompletionOn) {
            pickDefaultCandidate();
        }
    }

    public void swipeLeft() {
        handleBackspace();
    }

    public void swipeDown() {
        handleClose();
    }

    public void swipeUp() {
    }

    public void onPress(int primaryCode) {
    }

    public void onRelease(int primaryCode) {
    }

    @Override    public void onDestroy() {
        super.onDestroy();
    }

    private void takeScreenshot() {
        Date now = new Date();
        android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);

        try {
            // image naming and path  to include sd card  appending name you choose for file    

        String mPath = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg";

            view = new LinearLayout(getApplicationContext());
            WindowManager wm = (WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE);
            Display display = wm.getDefaultDisplay();
            Point size = new Point();
            display.getSize(size);
            int width = size.x;
            int height = size.y;
            view.setLayoutParams(new ViewGroup.LayoutParams(width, height));
            // create bitmap screen capture            View v1 = view.getRootView();
            v1.setDrawingCacheEnabled(true);
            Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
            v1.setDrawingCacheEnabled(false);

            File imageFile = new File(mPath);

            FileOutputStream outputStream = new FileOutputStream(imageFile);
            int quality = 100;
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
            outputStream.flush();
            outputStream.close();
            Log.d("Screen", "taken");
            //openScreenshot(imageFile);        } catch (Throwable e) {
            // Several error may come out with file handling or OOM      

      e.printStackTrace();
        }
    }
}
And you are done keyboard now...
If you like it, then like it on Facebook and recommend on G+
Full Source code can be downloaded from here