Settings in Android

I'm not going to teach you how to writing an activity for settings here - that's kind of obvious. Instead I'm going to highlight a couple of interesting things you can do with settings on an Android Keyboard.

Opening your settings page

We want to be able to open our settings page from two places.
  • From the launcher. Add LAUNCHER to AndroidManifest.xml, like so:
<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=".MyInputMethodService"
    android:label="Konjugator Keyboard"
    android:permission="android.permission.BIND_INPUT_METHOD"
    >
    <meta-data android:name="android.view.im" android:resource="@layout/method"/>
    <intent-filter>
        <action android:name="android.view.InputMethod"/>
    </intent-filter>
</service>

  • From the Keyboard Settings (System > Languages & input > Virtual keyboard), with the following in method.xml:
<input-method
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:supportsSwitchingToNextInputMethod="true"
    android:settingsActivity="com.example.MainActivity"
    >
    <subtype android:imeSubtypeMode="keyboard" />
</input-method>

Popping up the Manage keyboards settings

If your keyboard hasn't been enabled yet, the user will have to go to Manage keyboards in Settings (System > Languages & input > Virtual keyboard > Manage keyboards) and enable your keyboard. Or you could just redirect them there.

We start the Setting intent (note how we safeguard in case the Activityy doesn't exist). Insert this in the onCreate of your in MainActivity or SettingsActivity:

final PackageManager pm  = getPackageManager();
final Intent settingsIntent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
if (pm.resolveActivity(settingsIntent, 0) != null) {
    startActivityForResult(settingsIntent, 0);
} else {
    Toast.makeText(getApplicationContext(), "Settings Intent not found.", Toast.LENGTH_LONG).show();
}


Popping up Change keyboard

Once the user has enabled your keyboard, they will still need to switch to your keyboard. Why not pop up the Change keyboard dialog? Do this with:

InputMethodManager imeManager = (InputMethodManager) getApplicationContext().getSystemService(INPUT_METHOD_SERVICE);
imeManager.showInputMethodPicker();

Finding out if your keyboard is enabled

You might want to know if the user has enabled your keyboard. Here's how:

private boolean isKeyboardEnabled() {
    InputMethodManager imeManager = (InputMethodManager) getApplicationContext().getSystemService(INPUT_METHOD_SERVICE);
    List<InputMethodInfo> imls = imeManager.getEnabledInputMethodList();
    String packageName = getApplicationContext().getPackageName();
    for (InputMethodInfo iml : imls) {
        if (iml.getPackageName().equals(packageName)) {
            return true;
        }
    }
    return false;
}

Finding out if your keyboard is selected

You can find out if your keyboard has been selected with this:

// returns {isKeyboardEnabled, isKeyboardSelected}
private boolean[] isKeyboardEnabledAndSelected() {
    InputMethodManager imeManager = (InputMethodManager) getApplicationContext().getSystemService(INPUT_METHOD_SERVICE);
    List<InputMethodInfo> imls = imeManager.getEnabledInputMethodList();
    InputMethodSubtype ims = imeManager.getCurrentInputMethodSubtype();
    String packageName = getApplicationContext().getPackageName();

    for (InputMethodInfo iml : imls) {
        if (iml.getPackageName().equals(packageName)) {
            int subtypeCount = iml.getSubtypeCount();
            for (int i = 0; i < subtypeCount; i++) {
                if (iml.getSubtypeAt(i).equals(ims)) {
                    return new boolean[]{true, true};
                }  
            }  
            return new boolean[]{true, false};
        }  
    }  
    return new boolean[]{false, false};
}


Damn, that's some ugly code, but it works. Let me know if you come up with a better solution

When should I check?

You probably want to override two methods: protected void onResume() and public void onWindowFocusChanged(boolean hasFocus).  An alternative for the former would be to give a requestCode greater than zero to startActivityForResult, and overriding onActivityResult instead.

Comments

Popular posts from this blog

Available Resources for Android

Using React Native in an Android Custom Keyboard

Popup Keyboard for Special Characters in Android