Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Want custom keyboard to ONLY be used for MY APP and restore previous when app loses focus

I made this "custom keyboard" by following the wonderful outline in this link AND NOT USING ECLIPSE. I used Android Studio (AS) 1.1.0.

Here's a screenshot from my device:

enter image description here

The only problem is that the procedure requires changing settings for Language and Input AND ALSO replaces the keyboard FOR ALL APPS. I don't want that. I just want MY app to change the keyboard for ITSELF and then revert to the previous keyboard as soon as my app goes off screen, otherwise I'm going to be a huge pain in users' butts. Rather than do that, I may as well just add buttons to perform the keypresses I hoped to invoke via a custom keyboard. (It's not gruesome; user just has to pull down the notification bar and select choose input method, but still too intrusive for most users.)

Here's the structure:

enter image description here

The keypad is altered in qwerty.xml by doing lots of this:

<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
          android:keyWidth="10%p"
          android:horizontalGap="0px"
          android:verticalGap="0px"
          android:keyHeight="60dp"
    >
    <Row>
        <Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left"/>
        <Key android:codes="50" android:keyLabel="2"/>
        <Key android:codes="51" android:keyLabel="3"/>
        <Key android:codes="52" android:keyLabel="4"/>
        <Key android:codes="53" android:keyLabel="5"/>
        <Key android:codes="54" android:keyLabel="6"/>
        <Key android:codes="55" android:keyLabel="7"/>
        <Key android:codes="56" android:keyLabel="8"/>
        <Key android:codes="57" android:keyLabel="9"/>
        <Key android:codes="48" android:keyLabel="0" android:keyEdgeFlags="right"/>
    </Row>
...

Here's method.xml:

<?xml version="1.0" encoding="utf-8"?>
<input-method xmlns:android="http://schemas.android.com/apk/res/android">
    <subtype
        android:label=              "@string/subtype_en_US"
        android:imeSubtypeLocale=   "en_US"
        android:imeSubtypeMode=     "keyboard" 
    />
</input-method>

Here's AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.dslomer64.simplekeyboard">

    <application

                android:allowBackup="true"
                android:label="@string/app_name"
                android:icon="@mipmap/ic_launcher"
                android:theme="@style/AppTheme">

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

    </application>

</manifest>

The service that's added to the manifest is what gets at the soft keyboard through the code in SimpleIME.java (empty overrides omitted):

import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.media.AudioManager;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.InputConnection;

public class SimpleIME extends InputMethodService
    implements KeyboardView.OnKeyboardActionListener
{

  private KeyboardView kv;
  private Keyboard keyboard;

  private boolean caps = false;

  @Override
  public View onCreateInputView() {
    kv = (KeyboardView)getLayoutInflater().inflate(R.layout.keyboard, null);
    keyboard = new Keyboard(this, R.xml.qwerty);
    kv.setKeyboard(keyboard);
    kv.setOnKeyboardActionListener(this);
    return kv;
  }
  private void playClick(int keyCode){
    AudioManager am = (AudioManager)getSystemService(AUDIO_SERVICE);
    switch(keyCode){
      case 32:
        am.playSoundEffect(AudioManager.FX_KEYPRESS_SPACEBAR);
        break;
      case Keyboard.KEYCODE_DONE:
      case 10:
        am.playSoundEffect(AudioManager.FX_KEYPRESS_RETURN);
        break;
      case Keyboard.KEYCODE_DELETE:
        am.playSoundEffect(AudioManager.FX_KEYPRESS_DELETE);
        break;
      default: am.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD);
    }
  }
  @Override
  public void onKey(int primaryCode, int[] keyCodes) {
    InputConnection ic = getCurrentInputConnection();
    playClick(primaryCode);
    switch(primaryCode){
      case Keyboard.KEYCODE_DELETE :
        ic.deleteSurroundingText(1, 0);
        break;
      case Keyboard.KEYCODE_SHIFT:
        caps = !caps;
        keyboard.setShifted(caps);
        kv.invalidateAllKeys();
        break;
      case Keyboard.KEYCODE_DONE:
        ic.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
        break;
      default:
        char code = (char)primaryCode;
        if(Character.isLetter(code) && caps){
          code = Character.toUpperCase(code);
        }
        ic.commitText(String.valueOf(code),1);
    }
  }
    ...
}

I wonder if anyone out there has done what I need: implement a custom keyboard JUST FOR ONE APP and restore original upon loss of screen focus.

like image 784
DSlomer64 Avatar asked Oct 20 '22 12:10

DSlomer64


1 Answers

I just want MY app to change the keyboard for ITSELF

That is not possible through the input method editor system. The user, not you, is in charge of the input method that the user uses.

Rather than do that, I may as well just add buttons to perform the keypresses I hoped to invoke via a custom keyboard.

That is your only option.

like image 60
CommonsWare Avatar answered Oct 22 '22 00:10

CommonsWare