DSlomer64
DSlomer64

Reputation: 4283

Creating custom Android keyboard from well-known link; compiles, installs, but no option for this keyboard shows on device

I followed the instructions in this link using Eclipse Luna 2 (4.4.2).

The app compiled, and the apk was installed on my phone, but since it has no activity (which is by design) it can't be run. It's supposed to cause a new keyboard option to appear in the device's Settings | Language and Input, but nooooooooooo.

All I did was cut and paste file names and contents, so they're as shown at the link. Here's the project structure, the only item lacking in the link above:

enter image description here

enter image description here

Here's console output. All apparently went as it should have:

[2015-05-09 14:58:58 - SimpleKeyboard] ------------------------------
[2015-05-09 14:58:58 - SimpleKeyboard] Android Launch!
[2015-05-09 14:58:58 - SimpleKeyboard] adb is running normally.
[2015-05-09 14:58:58 - SimpleKeyboard] No Launcher activity found!
[2015-05-09 14:58:58 - SimpleKeyboard] The launch will only sync the application package on the device!
[2015-05-09 14:58:58 - SimpleKeyboard] Performing sync
[2015-05-09 14:58:58 - SimpleKeyboard] Automatic Target Mode: Unable to detect device compatibility. Please select a target device.
[2015-05-09 14:59:08 - SimpleKeyboard] Uploading SimpleKeyboard.apk onto device 'TA22807EL2'
[2015-05-09 14:59:08 - SimpleKeyboard] Installing SimpleKeyboard.apk...
[2015-05-09 14:59:11 - SimpleKeyboard] Success!
[2015-05-09 14:59:12 - SimpleKeyboard] \SimpleKeyboard\bin\SimpleKeyboard.apk installed on device
[2015-05-09 14:59:12 - SimpleKeyboard] Done!

But here's device screen, so it didn't QUITE go as it should have:

enter image description here

If you can spot an obvious error or omission, PLEASE let me know.

EDIT #1

Here's the .java for the project, in case I put something in wrong place, added or omitted an @Override etc. No imports were shown on the link:

import com.example.simplekeyboard.R;
import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.inputmethodservice.KeyboardView.OnKeyboardActionListener;
import android.media.AudioManager;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.InputConnection;

public class SimpleIME extends InputMethodService
    implements OnKeyboardActionListener{

    private KeyboardView kv;
    private Keyboard keyboard;
    private boolean caps = false;

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

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

    @Override
    public void onPress(int primaryCode) {
    }

    @Override
    public void onRelease(int primaryCode) {            
    }

    @Override
    public void onText(CharSequence text) {     
    }

    @Override
    public void swipeDown() {   
    }

    @Override
    public void swipeLeft() {
    }

    @Override
    public void swipeRight() {
    }

    @Override
    public void swipeUp() {
    }
}

EDIT #2

I just discovered that AndroidManifest.xml in bin folder (below) is NOT identical to AndroidManifest.xml under app!!:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.simplekeyboard"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        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>

AndroidManifest.xml under app:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.simplekeyboard"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />

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

</manifest>

EDIT #3 I changed the "short" manifest file to be same as "long" and now I DO GET the Simple IME keyboard as an option under Settings | Language and Input but the new keyboard (shown below) is NOT shown on device:

enter image description here

Upvotes: 0

Views: 364

Answers (2)

DSlomer64
DSlomer64

Reputation: 4283

The solution: Use Android Studio (AS) 1.1.0, NOT ECLIPSE.

It took 30 minutes to construct the project, correct ZERO errors, and INSTALL ON A DEVICE:

enter image description here

Seriously, Eclipse is finished for THIS Android Developer. The crud I had to suffer through because of the design and idiotsyncrasies (yes, misspelled) of Eclipse shouldn't have to happen to ANYONE. I chose Eclipse because the link said to do so; I figured, why chance AS?

The procedure described at the link atop this question is GREAT. Just don't develop it in Eclipse.

I'm posting the AS structure just to compare with Eclipse's.

enter image description here

Upvotes: 0

CommonsWare
CommonsWare

Reputation: 1007296

I just discovered that AndroidManifest.xml in bin folder (below) is NOT identical to AndroidManifest.xml under app!!:

You have two problems here.

First, bin/ is output. Never modify stuff in bin/. So the <service> that you put in the manifest needs to go in the AndroidManifest.xml file that is in your project root.

Second, assuming that you just move that <service> element over to the proper manifest, the Java class needs to be com.example.simplekeyboard.SimpleIME. Right now, you have SimpleIME in the default package in Java, which is rarely appropriate even in normal Java development, let alone in Android.

So, move the <service> element (and any other changes that you made) to the right manifest, and move SimpleIME to the right package.

Upvotes: 1

Related Questions