Android无法识别软键盘

时间:2017-03-13 16:50:01

标签: java android keyboard ime

我是Android环境的新手,所以请耐心等待我:

我一直在努力开发软键盘,作为我正在创作的词汇构建应用程序的一部分。当我运行应用程序时,通过Android Studio(v2.3),应用程序成功启动,但输入法服务似乎被忽略了,键盘没有列在系统的输入法中(我得到的地方)通过输入设置 - >语言和输入 - >当前键盘 - >选择键盘)。我使用的是Nexus 5和Android版本6.0.1,如果有帮助的话。

为了创建键盘,我一直在关注Android开发者指南(在"创建输入法"下),以及那里引用的示例键盘(" SoftKeyboard& #34;,Link)。我不需要SoftKeyboard示例提供的所有功能(例如,候选人),因此我只将示例项目的一部分改编为我自己的;这可能是问题的原因。

为了澄清,该应用程序成功启动,但键盘服务似乎被忽略。我已经搜索了日志,发现了一个与输入法有关的错误,但看起来很小。可以找到完整日志here(注意错误从第274行开始)。

此外,这里有一些我认为对问题很重要的代码片段(当然,我可以提供任何其他请求的文件):

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.akuros.glossa.keyboard">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <!-- Declares the input method service -->
        <service android:name="GlossaKeyboard"
                 android:label="greek_keyboard"
                 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=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

method.xml:

<?xml version="1.0" encoding="utf-8"?>
<InputMethod
xmlns:android="http://schemas.android.com/apk/res/android"
android:supportsSwitchingToNextInputMethod="true"
>
    <Subtype
    android:label="@string/keyboard_grk_label"
    android:imeSubtypeLocale="el_Gr"
    android:imeSubtypeMode="keyboard"
    />
</InputMethod>

和中心类(扩展InputMethodService),GlossaKeyboard:

package com.akuros.glossa.keyboard;

/*
 * This class defines the Greek Keyboard used by this application.
 *
 * Created by Nitzan on 15/02/2017.
 */

//TODO have the keyboard adapt its state according to the language needed

import android.app.Dialog;
import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.os.IBinder;
import android.text.InputType;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;

import static android.inputmethodservice.Keyboard.KEYCODE_DELETE;
import static android.inputmethodservice.Keyboard.KEYCODE_SHIFT;

public class GlossaKeyboard extends InputMethodService
        implements KeyboardView.OnKeyboardActionListener
{
    //------ Key Codes ------//
    private static final int KEYCODE_ENGLISH = -101;
    private static final int KEYCODE_LANGUAGE_SWITCH = -102;
    private static final int KEYCODE_CAPS = -103;

    //------ Fields ------ //

    private GlossaKeyboardView keyboardView;
    private StringBuilder composing;

    private InputMethodManager imm;

    private Keyboard greekKeyboard;
    private Keyboard englishKeyboard;
    private Keyboard currKeyboard;

    private int shiftState;

    @Override
    public void onCreate()
    {
        super.onCreate();
        imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
        composing = new StringBuilder();

        shiftState = 0;
    }

    @Override
    public void onInitializeInterface()
    {
        greekKeyboard = new Keyboard(this, R.xml.qwerty_greek);
        englishKeyboard = new Keyboard(this, R.xml.qwerty_english);
    }

    @Override
    public View onCreateInputView()
    {
        keyboardView = (GlossaKeyboardView) getLayoutInflater().inflate(
                R.layout.keyboard_greek, null);
        keyboardView.setOnKeyboardActionListener(this);
        keyboardView.setKeyboard(greekKeyboard);
        return keyboardView;
    }

    @Override
    public void onStartInput(EditorInfo attribute, boolean restarting)
    {
        super.onStartInput(attribute, restarting);

        composing.setLength(0);
        shiftState = 0;

        currKeyboard = greekKeyboard;

    }


    @Override
    public void onFinishInput()
    {
        super.onFinishInput();

        composing.setLength(0);

        if (keyboardView != null)
            keyboardView.closing();
    }

    /* Interface Required Methods */

    @Override
    public void onPress(int primaryCode)
    {

    }

    @Override
    public void onRelease(int primaryCode)
    {

    }

    @Override
    //note the static import of Keyboard's KEYCODE values
    public void onKey(int primaryCode, int[] keyCodes)
    {

        switch (primaryCode)
        {
            case KEYCODE_SHIFT:
                shiftState = (shiftState == 0) ? 1 : 0;
                break;

            case KEYCODE_CAPS:
                shiftState = (shiftState == 0) ? 2 : 0;
                break;

            case KEYCODE_DELETE:
                handleBackspace();
                break;

            case KEYCODE_LANGUAGE_SWITCH:
                handleLanguageSwitch();
                break;

            case KEYCODE_ENGLISH:
                handleEnglishSwitch();
                break;

            default:
                handleCharacter(primaryCode);
                break;

        }

        updateShiftKeyState(getCurrentInputEditorInfo());

    }

    @Override
    public void onText(CharSequence text)
    {
        InputConnection ic = getCurrentInputConnection();
        if (ic == null) return;
        ic.beginBatchEdit();

        if (composing.length() > 0)
            commitTyped(ic);

        ic.commitText(text, 0); //not sure why this call needs to exist, commitText(ic) should already
        //do the work.

        ic.endBatchEdit();
        updateShiftKeyState(getCurrentInputEditorInfo());
    }


    //------ Private methods ------//

    /* Handlers */

    private void handleCharacter(int primaryCode)
    {
        if(isInputViewShown())
        {
            if(keyboardView.isShifted())
                primaryCode = Character.toUpperCase(primaryCode);
        }
        CharSequence str = String.valueOf((char) primaryCode);
        getCurrentInputConnection().commitText(str, 1);
    }

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

    private void handleLanguageSwitch()
    {
        imm.switchToNextInputMethod(getToken(), false);
    }

    private void handleEnglishSwitch()
    {
        if(currKeyboard != englishKeyboard )
        {
            currKeyboard = englishKeyboard;
            keyboardView.setKeyboard(englishKeyboard);
        }
    }

    /* Helper Methods */

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

    private void commitTyped(InputConnection ic)
    {
        if (composing.length() > 0)
        {
            ic.commitText(composing, composing.length());
            composing.setLength(0);
        }
    }

    private void keyDownUp(int keyEventCode)
    {
        getCurrentInputConnection().sendKeyEvent(
                new KeyEvent(KeyEvent.ACTION_DOWN, keyEventCode));
        getCurrentInputConnection().sendKeyEvent(
                new KeyEvent(KeyEvent.ACTION_UP, keyEventCode));
    }

    private void updateShiftKeyState(EditorInfo attr)
    {
        if (attr != null && keyboardView != null)
        {
            Keyboard keyboard = keyboardView.getKeyboard();
            if (keyboard == greekKeyboard
                    || keyboard == englishKeyboard)
            {
                int caps = 0;
                EditorInfo ei = getCurrentInputEditorInfo();
                if (ei != null && ei.inputType != InputType.TYPE_NULL)
                {
                    caps = getCurrentInputConnection().getCursorCapsMode(attr.inputType);
                }
                keyboardView.setShifted(shiftState > 0 || caps != 0);
            }
        }
        if (shiftState == 1)
            shiftState = 0;
    }


    /* Unused Methods */
    //These methods are implemented simply because the OnKeyboardActionListener interface demands it.
    //their implementation is empty.

    @Override
    public void swipeLeft()
    {
        //do nothing
    }

    @Override
    public void swipeRight()
    {
        //do nothing
    }

    @Override
    public void swipeDown()
    {
        //do nothing
    }

    @Override
    public void swipeUp()
    {
        //do nothing
    }
}

到目前为止,我已经尝试过了:

  • 将所有与输入法相关的文件移动到一个单独的项目中,然后运行(相同的结果)

  • 调试项目(从未到达GlossaKeyboard类的断点)

  • 搜索日志(如上所述,未找到任何内容)

  • 将我的文件与SoftKeyboard示例应用程序中的文件进行比较(我的版本中没有发现任何错误;除了不需要的功能[例如单词建议,拼写检查等]之外,没有发现任何遗漏)

感谢任何帮助。

0 个答案:

没有答案