androidkeyboardandroid-softkeyboardandroid-8.0-oreoime

How to create multiple IME (Input Method Editor) subtypes on Android?


I am attempting to create multiple IME subtypes, but Android will only recognize one.

method.xml

<?xml version="1.0" encoding="utf-8"?>
<input-method
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:supportsSwitchingToNextInputMethod="true"
    android:settingsActivity="com.example.softkeyboard.Settings">


    <subtype android:name="@string/display_name_english_keyboard_dynamic_ime"
        android:imeSubtypeLocale="en_US"
        android:imeSubtypeMode="keyboard"
        android:imeSubtypeExtraValue="charDataFile=strokemaps_dynamic" />

    <subtype android:name="@string/display_name_english_keyboard_ime"
        android:imeSubtypeLocale="en_US"
        android:imeSubtypeMode="keyboard"
        android:imeSubtypeExtraValue="charDataFile=strokemaps" />

</input-method>

There are values in the strings.xml for each of the names.

<resources>
<string name="app_name">KK1</string>
<string name="display_name_english_keyboard_ime">English</string>
<string name="display_name_english_keyboard_dynamic_ime">English Dynamic</string>

My InputMethodService.onStartInputView method includes:

@Override
public void onStartInputView(EditorInfo ei, boolean restarting) {

    super.onStartInputView(ei, restarting);

    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    List<InputMethodInfo> imil = imm.getEnabledInputMethodList();
    for (InputMethodInfo imi: imil) {
        Log.e("osiv", "input method info: "+imi.toString());
    }

    List<InputMethodSubtype> imsl = imm.getEnabledInputMethodSubtypeList(imil.get(0), true);

    for (InputMethodSubtype ims: imsl) {
        Log.e("osiv", "input method subtype: "+ims.toString());
    }

and the listed InputMethodInfos include my IME, but the subtypes list includes only one subtype. Each of the subtypes functions if it is the only one in the file.

The Android 8.0 device does not present subtypes in its Language/Keyboard configuration option, just the IMEs themselves, so the subtypes cannot be individually enabled or disabled.

Is there another configuration item somewhere needed to tell Android to allow multiple IME subtypes?

Is there an obvious issue with above code?

Here is the AndroidManifest, in case that is helpful.

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

<uses-permission android:name="android.permission.VIBRATE" />

<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">

    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

    <service
        android:name=".KKInputMethodService"
        android:permission="android.permission.BIND_INPUT_METHOD"
        android:label="KK"
        android:configChanges="orientation">
        <intent-filter>
            <action android:name="android.view.InputMethod"/>
        </intent-filter>
        <meta-data
            android:name="android.view.im"
            android:resource="@xml/method"/>

    </service>

</application>


Solution

  • There seems to be one way to change the IME Subtype, that is to use the builtin subtype picker, which seems to only be available via an intent from an app or an IME.

    final Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
    intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, imId);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.putExtra(Intent.EXTRA_TITLE, “Select Enabled Subtypes”);
    context.startActivity(intent);
    

    The FLAG is necessary if you wish to start the Intent from within the InputMethodService.

    You can get the Input Method ID 'imId' from the inputMethodInfo object, with:

    String imId = inputMethodInfo.getId(); 
    

    or you can get the id using:

    String imId = Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
    

    The core of this answer is from: https://blog.swiftkey.com/tech-blog-android-input-method-subtypes/