diff --git a/docs/html/resources/articles/creating-input-method.jd b/docs/html/resources/articles/creating-input-method.jd index e4b77f4fd85e9..84c2704f5568e 100644 --- a/docs/html/resources/articles/creating-input-method.jd +++ b/docs/html/resources/articles/creating-input-method.jd @@ -3,248 +3,526 @@ parent.title=Articles parent.link=../browser.html?tag=article @jd:body -
To create an input method (IME) for entering text into text fields -and other Views, you need to extend the {@link android.inputmethodservice.InputMethodService}. -class. This class provides much of the basic implementation for an input -method, in terms of managing the state and visibility of the input method and -communicating with the currently visible activity.
- -A good starting point would be the SoftKeyboard sample code provided as part -of the SDK. You can modify the sample code to start building your own input -method.
- -An input method is packaged like any other application or service. In the
-AndroidManifest.xml file, you declare the input method as a
-service, with the appropriate intent filter and any associated meta data:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.fastinput"> - - <application android:label="@string/app_label">- -
- <!-- Declares the input method service --> - <service android:name="FastInputIME" - android:label="@string/fast_input_label" - 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> - - <!-- Optional activities. A good idea to have some user settings. --> - <activity android:name="FastInputIMESettings" android:label="@string/fast_input_settings"> - <intent-filter> - <action android:name="android.intent.action.MAIN"/> - </intent-filter> - </activity> - </application> -</manifest>
If your input method allows the user to tweak some settings, you should -provide a settings activity that can be launched from the Settings application. -This is optional and you may choose to provide all user settings directly in -your IME's UI.
- -The typical life-cycle of an InputMethodService looks like
-this:

There are two main visual elements for an input method—the input view and the -candidates view. You don't have to follow this style though, if one of them is -not relevant to your input method experience.
- -This is where the user can input text either in the form of keypresses,
-handwriting or other gestures. When the input method is displayed for the first
-time, InputMethodService.onCreateInputView() will be called. Create
-and return the view hierarchy that you would like to display in the input method
-window.
This is where potential word corrections or completions are presented to the
-user for selection. Again, this may or may not be relevant to your input method
-and you can return null from calls to
-InputMethodService.onCreateCandidatesView(), which is the default
-behavior.
An application's text fields can have different input types specified on -them, such as free form text, numeric, URL, email address and search. When you -implement a new input method, you need to be aware of the different input types. -Input methods are not automatically switched for different input types and so -you need to support all types in your IME. However, the IME is not responsible -for validating the input sent to the application. That's the responsibility of -the application.
- -For example, the LatinIME provided with the Android platform provides -different layouts for text and phone number entry:
- -

InputMethodService.onStartInputView() is called with an
-EditorInfo object that contains details about the input type and other
-attributes of the application's text field.
(EditorInfo.inputType
-& EditorInfo.TYPE_CLASS_MASK) can be one of many different values,
-including:
+ An input method editor (IME) is a user control that enables users to enter text. Android + provides an extensible input method framework that allows applications to provide users + alternative input methods, such as on-screen keyboards or even speech input. Once installed, + users can select which IME they want to use from the system settings and use it across the + entire system; only one IME may be enabled at a time. +
++ To add an IME to the Android system, you create an Android application + containing a class that extends {@link android.inputmethodservice.InputMethodService}. In + addition, you usually create a "settings" activity that passes options to the IME + service. You can also define a settings UI that's displayed as part of the system settings. +
+This article covers the following:
TYPE_CLASS_NUMBERTYPE_CLASS_DATETIMETYPE_CLASS_PHONETYPE_CLASS_TEXT+ If you haven't worked with IMEs before, you should read the introductory article + Onscreen Input Methods first. + Also, the Soft Keyboard sample app included in the SDK contains sample code that you can modify + to start building your own IME. +
++ The following diagram describes the life cycle of an IME: +
+
++ Figure 1. The life cycle of an IME. +
++ The following sections describe how to implement the UI and code associated with an IME that + follows this lifecycle. +
+
+ In the Android system, an IME is an Android application that contains a special IME service.
+ The application's manifest file must declare the service, request the necessary permissions,
+ provide an intent filter that matches the action action.view.InputMethod, and
+ provide metadata that defines characteristics of the IME. In addition, to provide a settings
+ interface that allows the user to modify the behavior of the IME, you can define a "settings"
+ activity that can be launched from System Settings.
+
+ The following snippet declares IME service. It requests the permission {@link
+ android.Manifest.permission#BIND_INPUT_METHOD} to allow the service to connect the IME to
+ the system, sets up an intent filter that matches the action
+ android.view.InputMethod, and defines metadata for the IME:
+
+<!-- Declares the input method service --> + <service android:name="FastInputIME" + android:label="@string/fast_input_label" + 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> ++
+ This next snippet declares the settings activity for the IME. It has an intent filter for + {@link android.content.Intent#ACTION_MAIN} that indicates this activity is the main entry point + for the IME application:
++ <!-- Optional: an activity for controlling the IME settings --> + <activity android:name="FastInputIMESettings" + android:label="@string/fast_input_settings"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + </intent-filter> + </activity> ++
+ You can also provide access to the IME's settings directly from its UI. +
++ Classes specific to IMEs are found in the {@link android.inputmethodservice} and {@link + android.view.inputmethod} packages. The {@link android.view.KeyEvent} class is important for + handling keyboard characters. +
++ The central part of an IME is a service component, a class that extends + {@link android.inputmethodservice.InputMethodService}. In addition to implementing the + normal service lifecycle, this class has callbacks for providing your IME's UI, handling user + input, and delivering text to the field that currently has focus. By default, the + {@link android.inputmethodservice.InputMethodService} class provides most of the implementation + for managing the state and visibility of the IME and communicating with the current + input field. +
++ The following classes are also important: +
++ There are two main visual elements for an IME: the input view and the + candidates view. You only have to implement the elements that are relevant to + the input method you're designing. +
++ The input view is the UI where the user inputs text, in the form of keyclicks, handwriting or + gestures. When the iIME is displayed for the first time, the system calls the + {@link android.inputmethodservice.InputMethodService#onCreateInputView()} callback. In your + implementation of this method, you create the layout you want to display in the IME + window and return the layout to the system. This snippet is an example of implementing the + {@link android.inputmethodservice.InputMethodService#onCreateInputView()} method: +
+ @Override
+ public View onCreateInputView() {
+ MyKeyboardView inputView =
+ (MyKeyboardView) getLayoutInflater().inflate( R.layout.input, null);
+
+ inputView.setOnKeyboardActionListener(this); inputView.setKeyboard(mLatinKeyboard);
+
+ return mInputView;
+ }
+
++ In this example, {@code MyKeyboardView} is an instance of a custom implementation of + {@link android.inputmethodservice.KeyboardView} that renders a + {@link android.inputmethodservice.Keyboard}. If you’re building a traditional QWERTY keyboard, + see the Soft Keyboard sample + app for an example of how to extend the {@link android.inputmethodservice.KeyboardView} class. +
++ The candidates view is the UI where the IME displays potential word corrections or + suggestions for the user to select. In the IME lifecycle, the system calls + {@link android.inputmethodservice.InputMethodService#onCreateCandidatesView()} when it's ready + to display the candidate view. In your implementation of this method, return a layout that shows + word suggestions, or return null if you don’t want to show anything (a null response is the + default behavior, so you don’t have to implement this if you don’t provide suggestions).
++ For an example implementation that provides user suggestions, see the + Soft Keyboard sample app. +
++ This section describes some specific UI design considerations for IMEs. +
++ The UI for your IME must be able to scale for different screen sizes, and it also + must handle both landscape and portrait orientations. In non-fullscreen IME mode, leave + sufficient space for the application to show the text field and any associated context, so that + no more than half the screen is occupied by the IME. In fullscreen IME mode this is not an + issue. +
++ Android text fields allow you to set a specific input type, such as free form text, numbers, + URLs, email addresses, and search strings. When you implement a new IME, you need to + detect the input type of each field and provide the appropriate interface for it. However, you + don't have to set up your IME to check that the user entered text that's valid for the + input type; that's the responsibility of the application that owns the text field. +
++ For example, here are screenshots of the interfaces that the Latin IME provided with the + Android platform provides for text and phone number inputs: +
+
+
++ Figure 2. Latin IME input types. +
++ When an input field receives focus and your IME starts, the system calls + {@link android.inputmethodservice.InputMethodService#onStartInputView(EditorInfo, boolean) + onStartInputView()}, passing in an {@link android.view.inputmethod.EditorInfo} object that + contains details about the input type and other attributes of the text field. In this object, + the {@link android.view.inputmethod.EditorInfo#inputType} field contains the text field's input + type. +
+
+ The {@link android.view.inputmethod.EditorInfo#inputType} field is an int
+ that contains bit patterns for various input type settings. To test it for the text field's
+ input type, mask it with the constant {@link android.text.InputType#TYPE_MASK_CLASS}, like
+ this:
+
+inputType & InputType.TYPE_MASK_CLASS ++
+The input type bit pattern can have one of several values, including: +
++ These constants are described in more detail in the reference documentation for + {@link android.text.InputType}. +
++ The {@link android.view.inputmethod.EditorInfo#inputType} field can contain other bits that + indicate a variant of the text field type, such as: +
++ Remember to mask {@link android.view.inputmethod.EditorInfo#inputType} with the appropriate + constant when you test for these variants. The available mask constants are listed in the + reference documentation for {@link android.text.InputType}. +
++ Caution: In your own IME, make sure you handle text correctly when you send it + to a password field. Hide the password in your UI both in the input view and in the candidates + view. Also remember that you shouldn't store passwords on a device. To learn more, see the Designing for Security guide. +
++ As the user inputs text with your IME, you can send text to the application by + sending individual key events or by editing the text around the cursor in the application's text + field. In either case, you use an instance of {@link android.view.inputmethod.InputConnection} + to deliver the text. To get this instance, call + {@link android.inputmethodservice.InputMethodService#getCurrentInputConnection + InputMethodService.getCurrentInputConnection()}. +
++ When you're handling the editing of existing text in a text field, some of the more useful + methods in {@link android.view.inputmethod.BaseInputConnection} are: +
++ For example, the following snippet shows how to replace the text "Fell" to the left of the + with the text "Hello!": +
+
+ InputConnection ic = getCurrentInputConnection();
+
+ ic.deleteSurroundingText(4, 0);
+
+ ic.commitText("Hello", 1);
+
+ ic.commitText("!", 1);
+
++ If your IME does text prediction or requires multiple steps to compose a glyph or + word, you can show the progress in the text field until the user commits the word, and then you + can replace the partial composition with the completed text. You may give special treatment to + the text by adding a "span" to it when you pass it to InputConnection#setComposingText(). +
++ The following snippet shows how to show progress in a text field: +
++ InputConnection ic = getCurrentInputConnection(); -See
- -android.text.InputTypefor more details.- -
EditorInfo.inputTypecan contain other masked bits that -indicate the class variation and other flags. For example, -TYPE_TEXT_VARIATION_PASSWORDorTYPE_TEXT_VARIATION_URI-orTYPE_TEXT_FLAG_AUTO_COMPLETE.Password fields
- -Pay -specific attention when sending text to password fields. Make sure that -the password is not visible within your UI — neither in the input -view or the candidates view. Also, do not save the password anywhere without -explicitly informing the user.
- -Landscape vs. portrait
- -The UI needs to be able to scale between landscape and portrait orientations. -In non-fullscreen IME mode, leave sufficient space for the application to show -the text field and any associated context. Preferably, no more than half the -screen should be occupied by the IME. In fullscreen IME mode this is not an -issue.
- -Sending text to the application
- -There are two ways to send text to the application. You can either send -individual key events or you can edit the text around the cursor in the -application's text field.
- -To send a key event, you can simply construct KeyEvent objects and call -
- -InputConnection.sendKeyEvent(). Here are some examples:InputConnection ic = getCurrentInputConnection(); -long eventTime = SystemClock.uptimeMillis(); -ic.sendKeyEvent(new KeyEvent(eventTime, eventTime, - KeyEvent.ACTION_DOWN, keyEventCode, 0, 0, 0, 0, - KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE)); -ic.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime, - KeyEvent.ACTION_UP, keyEventCode, 0, 0, 0, 0, - KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));- -Or use the convenience method:
- -InputMethodService.sendDownUpKeyEvents(keyEventCode);- -Note: -It is recommended to use the above method for certain fields such as -phone number fields because of filters that may be applied to the text -after each key press. Return key and delete key should also be sent as -raw key events for certain input types, as applications may be watching -for specific key events in order to perform an action.
- -When editing text in a text field, some of the more useful methods on -
- -android.view.inputmethod.InputConnectionare:
getTextBeforeCursor()getTextAfterCursor()deleteSurroundingText()commitText()For example, let's say the text "Fell" is to the left of the cursor -and you want to replace it with "Hello!":
- -InputConnection ic = getCurrentInputConnection();
-ic.deleteSurroundingText(4, 0);
-ic.commitText("Hello", 1);
-ic.commitText("!", 1);
-
-If your input method does some kind of text prediction or requires multiple -steps to compose a word or glyph, you can show the progress in the text field -until the user commits the word and then you can replace the partial composition -with the completed text. The text that is being composed will be highlighted in -the text field in some fashion, such as an underline.
- -InputConnection ic = getCurrentInputConnection();
-ic.setComposingText("Composi", 1);
+ ic.setComposingText("Composi", 1);
...
-ic.setComposingText("Composin", 1);
+
+ ic.setComposingText("Composin", 1);
+
...
-ic.commitText("Composing ", 1);
-
-
-
-
Even though the input method window doesn't have explicit focus, it receives
-hard key events first and can choose to consume them or forward them along to
-the application. For instance, you may want to consume the directional keys to
-navigate within your UI for candidate selection during composition. Or you may
-want to trap the back key to dismiss any popups originating from the input
-method window. To intercept hard keys, override
-InputMethodService.onKeyDown() and
-InputMethodService.onKeyUp(). Remember to call
-super.onKey* if you don't want to consume a certain key
-yourself.
+ The following screenshots show how this appears to the user: +
+
+
++ Figure 3. Composing text before committing. +
++ Even though the input method window doesn't have explicit focus, it receives hardware key + events first and can choose to consume them or forward them along to the application. For + example, you may want to consume the directional keys to navigate within your UI for candidate + selection during composition. You may also want to trap the back key to dismiss any popups + originating from the input method window.
++ To intercept hardware keys, override + {@link android.inputmethodservice.InputMethodService#onKeyDown(int, KeyEvent) onKeyDown()} + and {@link android.inputmethodservice.InputMethodService#onKeyUp(int, KeyEvent) onKeyUp()}. + See the Soft Keyboard sample + app for an example. +
+
+ Remember to call the super() method for keys you don't want to handle yourself.
+
+ Subtypes allow the IME to expose multiple input modes and languages supported by an IME. A + subtype can represent: +
+ Basically, the mode can be any text such as "keyboard", "voice", and so forth. +
+A subtype can also expose a combination of these.
++ Subtype information is used for an IME switcher dialog that's available from the notification + bar and also for IME settings. The information also allows the framework to bring up a + specific subtype of an IME directly. When you build an IME, use the subtype facility, because + it helps the user identify and switch between different IME languages and modes. +
+
+ You define subtypes in one of the input method's XML resource files, using the
+ <subtype> element. The following snippet defines an IME with two
+ subtypes: a keyboard subtype for the US English locale, and another keyboard subtype for the
+ French language locale for France:
+
+<input-method xmlns:android="http://schemas.android.com/apk/res/android" + android:settingsActivity="com.example.softkeyboard.Settings" + android:icon="@drawable/ime_icon" + <subtype android:name="@string/display_name_english_keyboard_ime" + android:icon="@drawable/subtype_icon_english_keyboard_ime" + android:imeSubtypeLanguage="en_US" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="somePrivateOption=true" + /> + <subtype android:name="@string/display_name_french_keyboard_ime" + android:icon="@drawable/subtype_icon_french_keyboard_ime" + android:imeSubtypeLanguage="fr_FR" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="foobar=30,someInternalOption=false" + /> + <subtype android:name="@string/display_name_german_keyboard_ime" + ... + /> +/> ++
+ To ensure that your subtypes are labeled correctly in the UI, use %s to get a subtype label + that is the same as the subtype’s locale label. This is demonstrated in the next two snippets. + The first snippet shows part of the input method's XML file: +
++ <subtype + android:label="@string/label_subtype_generic" + android:imeSubtypeLocale="en_US" + android:icon="@drawable/icon_en_us" + android:imeSubtypeMode="keyboard" /> ++
+ The next snippet is part of the IME's strings.xml file. The string
+ resource label_subtype_generic, which is used by the input method UI definition to
+ set the subtype's label, is defined as:
+
+<string name="label_subtype_generic">%s</string> ++
+ This sets the subtype’s display name to “English (United States)” in any English language + locale, or to the appropriate localization in other locales. +
++ The Android system manages all subtypes exposed by all IMEs. IME subtypes are + treated as modes of the IME they belong to. In the notification bar, a user can select an + available subtype for the currently-set IME, as shown in the following screenshot: +
+
++ Figure 4. Choosing an IME subtype from the notification bar. +
+
++ Figure 5. Setting subtype preferences in System Settings. +
+
+ A user can control how subtypes are used in the “Language & input” settings panel in the
+ System Settings area. In the Soft Keyboard sample, the file
+ InputMethodSettingsFragment.java contains an implementation that
+ facilitates a subtype enabler in the IME settings. Please refer to the SoftKeyboard sample in
+ the Android SDK for more information about how to support Input Method Subtypes in your IME.
+
++ Figure 6. Choosing a language for the IME. +
++ Here are some other things to consider as you're implementing your IME: +
+For a real world example, with support for multiple input types and text -prediction, see the LatinIME source code. The -Android SDK also includes a SoftKeyboard sample as well.
diff --git a/docs/html/resources/articles/images/inputmethod_composing_text_1.png b/docs/html/resources/articles/images/inputmethod_composing_text_1.png new file mode 100644 index 0000000000000..3403489189f11 Binary files /dev/null and b/docs/html/resources/articles/images/inputmethod_composing_text_1.png differ diff --git a/docs/html/resources/articles/images/inputmethod_composing_text_2.png b/docs/html/resources/articles/images/inputmethod_composing_text_2.png new file mode 100644 index 0000000000000..67bd1d93d51e8 Binary files /dev/null and b/docs/html/resources/articles/images/inputmethod_composing_text_2.png differ diff --git a/docs/html/resources/articles/images/inputmethod_composing_text_3.png b/docs/html/resources/articles/images/inputmethod_composing_text_3.png new file mode 100644 index 0000000000000..4fd1a30326289 Binary files /dev/null and b/docs/html/resources/articles/images/inputmethod_composing_text_3.png differ diff --git a/docs/html/resources/articles/images/inputmethod_lifecycle_image.png b/docs/html/resources/articles/images/inputmethod_lifecycle_image.png new file mode 100644 index 0000000000000..5f7cf95252e3c Binary files /dev/null and b/docs/html/resources/articles/images/inputmethod_lifecycle_image.png differ diff --git a/docs/html/resources/articles/images/inputmethod_numeric_type_screenshot.png b/docs/html/resources/articles/images/inputmethod_numeric_type_screenshot.png new file mode 100644 index 0000000000000..61b7483505798 Binary files /dev/null and b/docs/html/resources/articles/images/inputmethod_numeric_type_screenshot.png differ diff --git a/docs/html/resources/articles/images/inputmethod_subtype_notification.png b/docs/html/resources/articles/images/inputmethod_subtype_notification.png new file mode 100644 index 0000000000000..3f13927bcaa19 Binary files /dev/null and b/docs/html/resources/articles/images/inputmethod_subtype_notification.png differ diff --git a/docs/html/resources/articles/images/inputmethod_subtype_preferences.png b/docs/html/resources/articles/images/inputmethod_subtype_preferences.png new file mode 100644 index 0000000000000..d8aa0cf34e48a Binary files /dev/null and b/docs/html/resources/articles/images/inputmethod_subtype_preferences.png differ diff --git a/docs/html/resources/articles/images/inputmethod_subtype_settings.png b/docs/html/resources/articles/images/inputmethod_subtype_settings.png new file mode 100644 index 0000000000000..b8942c6f6bca1 Binary files /dev/null and b/docs/html/resources/articles/images/inputmethod_subtype_settings.png differ diff --git a/docs/html/resources/articles/images/inputmethod_text_type_screenshot.png b/docs/html/resources/articles/images/inputmethod_text_type_screenshot.png new file mode 100644 index 0000000000000..8008b27d9e3a5 Binary files /dev/null and b/docs/html/resources/articles/images/inputmethod_text_type_screenshot.png differ