research.sg.edu.edapp.kb.KbSoftKeyboard.java Source code

Java tutorial

Introduction

Here is the source code for research.sg.edu.edapp.kb.KbSoftKeyboard.java

Source

/*
 * Copyright (C) 2008-2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package research.sg.edu.edapp.kb;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import android.app.ActivityManager;
import android.app.KeyguardManager;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.support.v4.view.VelocityTrackerCompat;
import android.telephony.TelephonyManager;
import android.text.InputType;
import android.text.method.MetaKeyKeyListener;
import android.util.Log;
import android.view.GestureDetector;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import android.widget.EditText;

import research.sg.edu.edapp.R;

import static java.lang.Math.abs;

/**
 * Example of writing an input method for a soft keyboard.  This code is
 * focused on simplicity over completeness, so it should in no way be considered
 * to be a complete soft keyboard implementation.  Its purpose is to provide
 * a basic example for how you would get started writing an input method, to
 * be fleshed out as appropriate.
 */
/*edit 0
 * added GestureListener
    
 */
public class KbSoftKeyboard extends InputMethodService implements KeyboardView.OnKeyboardActionListener {
    static final boolean DEBUG = false;

    /**
     * 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 KbLatinKeyboardView mInputView;//kv_r
    private KbCandidateView mCandidateView;
    private CompletionInfo[] mCompletions;

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

    private KbLatinKeyboard mSymbolsKeyboard;
    private KbLatinKeyboard mSymbolsShiftedKeyboard;
    private KbLatinKeyboard mQwertyKeyboard; //keyboard

    private KbLatinKeyboard mCurKeyboard;

    private String mWordSeparators;

    private String imei_no;
    private File dataDir, sdCardRoot;

    private static String tap_ctr = "000000";
    private static String old_pkg = "Dummy_Pkg";
    //*****************************************edit1 started**************************************************
    private String swipe = "", test = "", swipe2 = "";
    private List<Keyboard.Key> keyList;
    private double pressure, duration, velocity, start, end;
    private VelocityTracker mvel = null;
    private float old_x = 0, old_y = 0, olddir_x = 0, olddir_y = 0;
    private Save_feature sf;
    public static DataDBHelper featuredb;
    private GetSwipeWord swipeWord;
    double x_vel = 0, y_vel = 0;
    int n_event = 1, np_event = 1;
    char frequent_char = 0;

    public void retrieveKeys() {
        keyList = mInputView.getKeyboard().getKeys();
    }

    //given motion event find which key character is at that particular coordinate
    public char getkeylabel(MotionEvent event) {
        char c = 0;
        String s = "";

        // For each key in the key list
        for (Keyboard.Key k : keyList) {
            // If the coordinates from the Motion event are inside of the key
            if (k.isInside((int) event.getX(), (int) event.getY())) {
                // k is the key pressed
                Log.d("Debugging", "Key pressed: key=" + k.label + " X=" + k.x + " - Y=" + k.y);
                int centreX, centreY;
                centreX = (k.width / 2) + k.x;
                centreY = (k.width / 2) + k.x;
                if (k.label != null) {
                    s = k.label.toString();
                    if (s.equals("SPACE") || s.equals("CAPS") || s.equals("DEL")) {
                        Log.d("Debugging", "hereeeeee");
                        //swipe="";
                        c = 0;
                    } else
                        c = k.label.charAt(0);
                    // These values are relative to the Keyboard View
                    // Log.d("Debugging",
                    //       "Centre of the key pressed: X="+centreX+" - Y="+centreY);

                }
            }
        }

        return c;
    }

    //funtion to retrieve key if direction has changed
    public void check_change(MotionEvent event) {

        float new_x = event.getX(), new_y = event.getY();
        // if(((new_x-old_x)>0 && olddir_x<0)||((new_x-old_x)<0 && olddir_x>0)){
        swipe += getkeylabel(event);
        //}

        //   if(((new_y-old_y)>0 && olddir_y<0)||((new_y-old_y)<0 && olddir_y>0)){
        //  swipe+=getkeylabel(event);
        //}
    }
    //get unique characters in string

    public String get_final_string(String s) {
        String ans = "", s2 = "";
        int freq[] = new int[256];
        int count = 1, count1 = 1, count2 = 1, count3 = 1, len = s.length(), avg = 0, iter = 0;
        char c1 = 0, c2 = 0, c3 = 0;
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) >= 97 && s.charAt(i) <= 122)
                s2 += s.charAt(i);
        }
        s = s2;
        len = s.length();
        if (len == 0) {
            frequent_char = 0;
            return null;
        }
        if (len == 1) {
            frequent_char = 0;
            return s;
        }
        ans += s.charAt(0);

        //working method
        count1 = 1;
        count2 = 1;
        c1 = s.charAt(0);
        for (int i = 1; i < len; i++) {
            if (s.charAt(i - 1) == s.charAt(i)) {
                count1++;
                continue;
            } else {
                if (count1 > count2) {
                    count2 = count1;
                    c1 = s.charAt(i - 1);

                }
                count1 = 1;
                count += 1;
            }
        }
        avg = len / count;
        frequent_char = c1;
        int current = 1;

        for (int i = 1; i < len; i++) {
            if (s.charAt(i - 1) == s.charAt(i)) {
                current += 1;
                continue;
            } else {
                if (current > avg & ans.charAt(ans.length() - 1) != s.charAt(i - 1))
                    ans += s.charAt(i - 1);
                current = 1;
            }
        }

        return ans;
    }

    //*********************************************************edit 1 ended**************************************
    public static class RecentUseComparator implements Comparator<UsageStats> {

        @Override
        public int compare(UsageStats lhs, UsageStats rhs) {
            return (lhs.getLastTimeUsed() > rhs.getLastTimeUsed()) ? -1
                    : (lhs.getLastTimeUsed() == rhs.getLastTimeUsed()) ? 0 : 1;
        }
    }

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

        //Clear the SharedPreference
        //SharedPreferences prefs =
        //getApplicationContext().getSharedPreferences("TapSenseSharedPref", Context.MODE_WORLD_READABLE).edit().clear().apply();
        //SharedPreferences.Editor editor = prefs.edit();
        //editor.putString("TimeStamp", currentDateandTime);
    }

    /**
     * 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 KbLatinKeyboard(this, R.xml.qwerty);
        mSymbolsKeyboard = new KbLatinKeyboard(this, R.xml.symbols);
        mSymbolsShiftedKeyboard = new KbLatinKeyboard(this, R.xml.symbols_shift);
        sdCardRoot = Environment.getExternalStorageDirectory();
        dataDir = new File(sdCardRoot, getResources().getString(R.string.data_file_path));

        if (!dataDir.exists()) {
            dataDir.mkdirs();
        }

        TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        imei_no = (String) telephonyManager.getDeviceId();
    }

    /**
     * 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 = (KbLatinKeyboardView) getLayoutInflater().inflate(R.layout.input, null);
        mInputView.setKeyboard(mQwertyKeyboard);
        mInputView.setOnKeyboardActionListener(this);

        /****************************************************edit 2**************************************************************/

        featuredb = new DataDBHelper(this);
        KbSoftKeyboard gd = new KbSoftKeyboard();
        sf = new Save_feature();
        swipeWord = new GetSwipeWord(this);
        //gDetect.setOnDoubleTapListener(gd);
        mInputView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int index = event.getActionIndex();
                int action = event.getActionMasked();
                int pointerId = event.getPointerId(index);

                //check for actions of motion event
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    //retrieve key at current
                    char ch = getkeylabel(event);
                    if (ch > 0)
                        swipe += ch;
                    // test+=swipe.charAt(0);
                    //set up start timer for measuring duration
                    //  start=System.currentTimeMillis();
                    //setup velocity tracker
                    if (mvel == null) {
                        // Retrieve a new VelocityTracker object to watch the velocity of a motion.
                        mvel = VelocityTracker.obtain();
                    } else {
                        // Reset the velocity tracker back to its initial state.
                        mvel.clear();
                    }
                }

                if (event.getAction() == MotionEvent.ACTION_MOVE) {
                    mvel.addMovement(event);
                    mvel.computeCurrentVelocity(1000);
                    // Log velocity of pixels per second
                    // Best practice to use VelocityTrackerCompat where possible.
                    x_vel += abs(VelocityTrackerCompat.getXVelocity(mvel, pointerId));
                    y_vel += abs(VelocityTrackerCompat.getYVelocity(mvel, pointerId));
                    n_event += 1;
                    //  Log.d("", "X velocity: " +  x_vel);
                    //  Log.d("", "Y velocity: " +  y_vel);

                }
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    //record time when finger lifted up
                    //           end=System.currentTimeMillis();
                    //calculate duration
                    //         duration=(end-start)/100;
                    //calculate velocity pixels per sec
                    //  Log.d("", "X velocity: " +  x_vel);
                    // Log.d("", "Y velocity: " +  y_vel);

                    velocity = Math.sqrt(x_vel * x_vel + y_vel * y_vel);
                    //obtain pressure
                    pressure += event.getPressure();
                    np_event += 1;
                    swipe2 = get_final_string(swipe);
                    swipe = "";
                    if (swipe2 == null)
                        swipe2 = "";
                    //print generated string
                    System.out.println(swipe + "\n 2nd " + swipe2);
                }

                if (((int) old_x) == 0 & ((int) old_y) == 0) {
                    old_x = event.getX();
                    old_y = event.getY();
                    swipe += getkeylabel(event);
                } else if (((int) olddir_x) == 0 & ((int) olddir_y) == 0) {
                    olddir_x = event.getX() - old_x;
                    olddir_y = event.getY() - old_y;
                    old_x = event.getX();
                    old_y = event.getY();
                } else {
                    check_change(event);
                }

                // Return false to avoid consuming the touch event
                return false;
            }
        });

        //***********************************************edit 2 end*****************************************************************

        //Saved my life
        if (mInputView.isPreviewEnabled())
            mInputView.setPreviewEnabled(false);
        return mInputView;
    }

    /**
     * Called by the framework when your view for showing candidates needs to
     * be generated, like {@link #onCreateInputView}.
     */
    @Override
    public View onCreateCandidatesView() {
        mCandidateView = new KbCandidateView(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;
            //mPredictionOn = false;

            // 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();
        }
    }

    private void writeToFile(String data, Context context) {
        try {
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(
                    context.openFileOutput("config.txt", Context.MODE_PRIVATE));
            outputStreamWriter.write(data);
            outputStreamWriter.close();
        } catch (IOException e) {
            Log.e("Exception", "File write failed: " + e.toString());
        }
    }

    /* edit 3
        
     */

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

    @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);
            }
        }

        Log.d("Cum", "Cum");
        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) {
        String s = "" + event.getUnicodeChar();
        Log.d("CAME HERE", "CAME HERE");
        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) {
                //*********added changes here
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    swipe += (char) event.getUnicodeChar();
                    Log.d("msg", swipe);
                    System.out.println(swipe);
                    // keyDownUp(keyCode);
                    //   return true;
                }
                //*********done
                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);
            }
            //print swipe on the edit text field  after processing it
            keyDownUp(keyCode);
        }
        if (event.getAction() == KeyEvent.ACTION_UP) {
            Log.d("INUP ", swipe);
        }

        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) {
        System.out.print("came");

        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;
        }
    }

    public String getAppName() {
        String packagename;

        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {

            KeyguardManager myKM = (KeyguardManager) getApplicationContext()
                    .getSystemService(Context.KEYGUARD_SERVICE);
            if (myKM.inKeyguardRestrictedInputMode()) {
                //it is locked

                System.out.println("[AppLogger]Screen is locked");
                packagename = "LockScreen";
            } else {
                //it is not locked

                ActivityManager am = (ActivityManager) getApplicationContext().getSystemService(ACTIVITY_SERVICE);

                List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
                ComponentName componentInfo = taskInfo.get(0).topActivity;

                packagename = componentInfo.getPackageName();

                System.out.println(
                        "[AppLogger]Build Version:" + Build.VERSION.SDK_INT + ",Package Name:" + packagename);
            }
        }

        else {

            KeyguardManager myKM = (KeyguardManager) getApplicationContext()
                    .getSystemService(Context.KEYGUARD_SERVICE);
            if (myKM.inKeyguardRestrictedInputMode()) {
                //it is locked

                System.out.println("[AppLogger]Screen is locked");
                packagename = "LockScreen";
            }

            else {

                //ActivityManager am =(ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
                //packagename = am.getRunningAppProcesses().get(0).processName;

                packagename = getTopPackage();
            }

            System.out.println(
                    "[AlarmReceiver]Build Version:" + Build.VERSION.SDK_INT + "Package Name:" + packagename);
        }
        return packagename;
    }

    public String getTopPackage() {

        RecentUseComparator mRecentComp = new RecentUseComparator();

        long ts = System.currentTimeMillis();
        UsageStatsManager mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
        List<UsageStats> usageStats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST,
                ts - 1000 * 10, ts);
        if (usageStats == null || usageStats.size() == 0) {
            //return NONE_PKG;
            return old_pkg;
        }
        Collections.sort(usageStats, mRecentComp);
        old_pkg = usageStats.get(0).getPackageName();
        return usageStats.get(0).getPackageName();
    }

    // Implementation of KeyboardViewListener

    public void onKey(int primaryCode, int[] keyCodes) {
        /*String tap_file_name;
        String currentmood = "-99";
        boolean esm_event=false,esm_signal=false,esm_time=false;
            
        //SimpleDateFormat sdf = new SimpleDateFormat("yyyy:MM:dd__HH:mm:ss.SSS");
        SimpleDateFormat sdf = new SimpleDateFormat(getResources().getString(R.string.time_format));
        String currentDateandTime = sdf.format(new Date());
        //boolean mood_rdy_to_record;
            
        //Store the timestamp in SharedPref
        //SharedPreferences prefs = getApplicationContext().getSharedPreferences(getResources().getString(R.string.sharedpref_file), Context.MODE_WORLD_READABLE);
        SharedPreferences prefs = getApplicationContext().getSharedPreferences(getApplicationContext().getResources().getString(R.string.sharedpref_file), Context.MODE_WORLD_READABLE);
            
        //currentDateandTime1=prefs.getString("TimeStamp", "No Data");
        //System.out.println("[TimeStamp:"+currentDateandTime1+"]");
            
        //SharedPreferences.Editor editor = prefs.edit();
        SharedPreferences.Editor seditor =prefs.edit();
        seditor.putString(getResources().getString(R.string.sharedpref_tstamp), currentDateandTime);
        seditor.putString(getResources().getString(R.string.sharedpref_last_app_name), getAppName());
        seditor.putBoolean(getResources().getString(R.string.sharedpref_mood_rdy_to_record), true);
        //seditor.putString(getResources().getString(R.string.sharedpref_last_app_name), getAppName());
        //editor.apply();
        seditor.apply();
        seditor.commit();
            
        //System.out.println("Current Mood to Record:"+prefs.getBoolean(getResources().getString(R.string.sharedpref_mood_rdy_to_record),false));
            
        //Retrieve current mood from sharedpref
            
        try {
            
        Context con = getApplicationContext().createPackageContext(getResources().getString(R.string.moodrecorder_pkg), Context.CONTEXT_IGNORE_SECURITY);
        SharedPreferences mood_pref = con.getSharedPreferences(getResources().getString(R.string.tap_mood_sharedpref_file), Context.MODE_MULTI_PROCESS);
            
        currentmood = mood_pref.getString(getResources().getString(R.string.sharedpref_current_mood), "-99");
        esm_event = mood_pref.getBoolean(getResources().getString(R.string.sharedpref_esm_event),false);
        esm_signal = mood_pref.getBoolean(getResources().getString(R.string.sharedpref_esm_signal),false);
        esm_time = mood_pref.getBoolean(getResources().getString(R.string.sharedpref_esm_time),false);
        System.out.println("Current Mood:" + currentmood);
        }
        catch (Exception e) {
        e.printStackTrace();
        }*/

        SimpleDateFormat sdf = new SimpleDateFormat(getResources().getString(R.string.time_format));
        String currentDateandTime = sdf.format(new Date());

        ContentValues values = new ContentValues();
        values.put(KbTouchEvent.TouchEntry.TE_APP_NAME, getAppName());
        values.put(KbTouchEvent.TouchEntry.TE_TIMESTAMP, currentDateandTime);
        //values.put(TouchEvent.TouchEntry.TE_KEY, String.valueOf((char)primaryCode));
        values.put(KbTouchEvent.TouchEntry.TE_KEY, primaryCode);
        Uri uri = getContentResolver().insert(KbContentProvider.CONTENT_URI, values);

        //End of retrieving current mood from sharedpref

        //currentDateandTime1=prefs.getString("TimeStamp", "No Data");
        //System.out.println("[TimeStamp:"+currentDateandTime1+"]");

        String keypress = String.valueOf((char) primaryCode);
        Log.d("Key Pressed", keypress);
        System.out.println("Ascii value:" + (int) keypress.charAt(0));

        /*if(Character.va >=){
            
        }*/
        //System.out.println("Alternate way key pressed:"+Character.toChars(primaryCode)[0]);

        /*String string_t;
        //string_t = currentDateandTime+ "  ---->  " + "X = " + x_Coordinate + ", Y =  "+y_Coordinate+ "\n";
        //string_t = getAppName() + "," + currentDateandTime+ "," + keypress + "\n";
            
        string_t = getAppName() + "," + currentDateandTime + "," + currentmood + "," + esm_event + "," + esm_signal + "," + esm_time + "\n";
            
        //tap_file_name = imei_no + getResources().getString(R.string.tap_file_postfix);
            
        tap_file_name = imei_no + "_" + tap_ctr + getResources().getString(R.string.tap_file_postfix);
        File tap_file = new File(dataDir, tap_file_name);
            
        try{
           //String SDCARD = Environment.getExternalStorageDirectory().getAbsolutePath();
           //String FILENAME = "keylogger.txt";
            
          //File outfile = new File(SDCARD+File.separator+FILENAME);
          FileOutputStream fos = new FileOutputStream(tap_file,true);
          fos.write(string_t.getBytes());
          fos.close();
        }catch(Exception e) {
          Log.d("EXCEPTION",e.getMessage());
        }
            
        //Checks file size and move to ToBeUploaded folder
        int tap_file_size = Integer.parseInt(String.valueOf(tap_file.length() / 1024));
        //mood_file_size = mood_file_size /4;
        int tap_file_size_threshold = Integer.parseInt(getResources().getString(R.string.tap_file_size_limit));
        System.out.println("Tap File Size:" + tap_file_size + ", Tap File Threshold:" + tap_file_size_threshold );
            
        if (tap_file_size > tap_file_size_threshold) {
        int ctr = Integer.parseInt(tap_ctr) + 1;
        tap_ctr=String.valueOf(ctr);
        tap_ctr=String.format("%06d", Integer.parseInt(tap_ctr));
        //String.format("%05d", Integer.parseInt(mood_ctr));
        move_file(tap_file_name);
        }*/

        /********************************************************important edit edit 6****************************************/
        InputConnection ic = getCurrentInputConnection();
        // playClick(primaryCode)
        String suggested_string = "";
        /***********************************************************check edit***********************************************/
        if (isWordSeparator(primaryCode)) {
            // Handle separator
            if (mComposing.length() > 0) {
                commitTyped(getCurrentInputConnection());
                swipe = "";
            }
            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 == KbLatinKeyboardView.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) {

                current = mQwertyKeyboard;
            } else {
                current = mSymbolsKeyboard;
            }
            mInputView.setKeyboard(current);
            if (current == mSymbolsKeyboard) {
                current.setShifted(false);
            }
        } else {

            /****************************************************************8default handling******************************************/
            char code = (char) primaryCode;
            if (swipe2.length() != 0 && code != swipe2.charAt(swipe2.length() - 1)) {
                swipe2 += "+" + code;
            }
            if (frequent_char == 0 || frequent_char == code || frequent_char == test.charAt(0))
                test += ".*" + code;
            else
                test += ".*" + frequent_char + ".*" + code;
            Log.d("Pattern", test);
            if (Character.isLetter(code) && mCapsLock) {
                code = Character.toUpperCase(code);
            }
            if (swipe2.length() < 3) {
                ic.commitText(String.valueOf(code), 1);
                swipe = "";
                swipe2 = "";
            } else {
                suggested_string = strings_matched(test);
                suggested_string += " ";
                if (suggested_string.length() <= 1) {
                    ic.commitText(String.valueOf(code), 1);
                } else
                    ic.commitText(suggested_string, suggested_string.length());

                //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);
            mInputView.setKeyboard(mSymbolsShiftedKeyboard);
            mSymbolsShiftedKeyboard.setShifted(true);
        } else if (currentKeyboard == mSymbolsShiftedKeyboard) {
            mSymbolsShiftedKeyboard.setShifted(false);
            mInputView.setKeyboard(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(mComposing, 1);
            getCurrentInputConnection().commitText(String.valueOf((char) primaryCode), 1);
        }
    }

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

    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());
        }
    }

    /* testing  to store keys while swyping*/
    /*
    int downKeyCode = -1;
    private int getKeycode(int x, int y){
    int index = -1;
    List<Keyboard.Key> keys = mInputView.getKeyboard().getKeys();
    for(Keyboard.Key k:keys){
        if((x>=k.x && x<=k.x+ k.width) && (y>=k.y && y<=k.y + k.height))
            return k.codes[0];
    }
    return index;
    }
        
    public boolean onTouchEvent(MotionEvent me) {
    int x = (int)me.getX();
    int y = (int)me.getY();
    int action = me.getAction();
    int currKeyCode = getKeycode(x, y);
    switch (action) {
        
    case MotionEvent.ACTION_DOWN:
        downKeyCode = currKeyCode;
        break;
        
    case MotionEvent.ACTION_UP:
        if(downKeyCode == 'q'){
            if(currKeyCode == 'y')
            {
                Log.d("msg","qwerty");
                downKeyCode = -1;
                return true;
            }
        }
        downKeyCode = -1;
        break;
    }
    return true;
    }
    */
    //ended code
    public void swipeRight() {
        if (mCompletionOn) {
            pickDefaultCandidate();
        }
    }

    public void swipeLeft() {

        handleBackspace();
    }

    public void swipeDown() {
        handleClose();
    }

    public void swipeUp() {
    }

    public void onPress(int primaryCode) {
        //check larter
        /*****************************************************************edit 4**********************************************/
        String first = "" + (char) primaryCode;
        test += (char) primaryCode;
        Log.d("Like", first);
        //swipe=(char)primaryCode+swipe;
        //set up start timer for measuring duration
        start = System.currentTimeMillis();

        /*******************************************************8edit4 ended*********************************************/
    }

    /*************************************************edit5*****************************************************/
    public String strings_matched(String regex) {
        System.out.println("Yaha");
        ArrayList<String> suggest = swipeWord.get_suggestion(regex);
        String result = "";
        int count = 0;
        for (String s : suggest) {
            if (s.length() >= swipe2.length() - 2 && s.length() <= swipe2.length() + 2) {
                System.out.println("Dictionary are " + s);
                if (count == 0)
                    result = s;
                count++;
                if (count == 3)
                    break;
            }
        }

        return result;

    }

    /******************************************************edit5 ended**************************************************************/
    public void onRelease(int primaryCode) {
        /*********************************************edit3************************************************************/
        if (!(primaryCode == Keyboard.KEYCODE_DELETE || primaryCode == Keyboard.KEYCODE_SHIFT
                || (char) primaryCode == ' ')) {//record time when finger lifted up
            end = System.currentTimeMillis();
            //calculate duration
            duration = (end - start) / 1000;
            //pressure is pressure/nt
            pressure = pressure / np_event;
            Log.d("ans", "X velocity: " + x_vel / n_event);
            Log.d("ans", "Y velocity: " + y_vel / n_event);
            //save into database
            sf.set_duration(duration);
            sf.set_pressure(pressure);
            sf.set_speed(velocity);
            featuredb.add_feature(sf, this);
            // featuredb.databasetoString();
        }

        //end saving
        start = 0;
        end = 0;
        pressure = 0;
        np_event = 1;
        x_vel = 0;
        y_vel = 0;
        n_event = 1;
        swipe = "";
        test = "";
        /****************************edit3 ended*************************************************************************/
    }

    public void setTapCtr() {
        File sdCardRoot = Environment.getExternalStorageDirectory();
        File dataDir = new File(sdCardRoot, getResources().getString(R.string.data_file_path));

        if (!dataDir.exists()) {
            dataDir.mkdirs();
        }

        for (File f : dataDir.listFiles()) {
            if (f.isFile()) {
                String name = f.getName();
                if (name.contains(getResources().getString(R.string.tap_file_postfix))) {
                    String[] separated = name.split("_");
                    tap_ctr = separated[1];
                }
            }
        }
    }

    public void move_file(String file_name) {

        File sdCardRoot = Environment.getExternalStorageDirectory();

        File dataDir = new File(sdCardRoot, getResources().getString(R.string.data_file_path));
        File tobeuploadedDir = new File(sdCardRoot, getResources().getString(R.string.to_be_uploaded_file_path));

        File sourceLocation = new File(dataDir, file_name);
        File targetLocation = new File(tobeuploadedDir, file_name);

        try {
            InputStream in = new FileInputStream(sourceLocation);
            OutputStream out = new FileOutputStream(targetLocation);

            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
            in.close();
            out.close();

            //Now delete the mood file from the DataFiles location
            if (sourceLocation.exists()) {
                sourceLocation.delete();
            }
        } catch (Exception e) {
            Log.e("Exception", "File write failed: " + e.toString());
        }
    }
}