Posted by Josh Gordon, Developer Advocate
Channel surfing is a popular way of watching TV. You pick up the remote, lean back, and flip through channels to see what’s on. On Android TV, app developers can create their own channel-like experiences using the TV Input Framework.
To the user, the channels you create look and feel just like regular TV channel. But behind the scenes, they stream video over the internet. For example, you can create a channel from a video playlist.
Watch this DevByte for an overview of how to build to a channel, and see the sample app and developer training for more info. The sample shows how to work with a variety of media formats, including HLS, MPEG-Dash, and HTTP Progressive.
If you already have an app that streams video, consider also making your content available as a channel. It’s a great opportunity to increase engagement. We’re excited to see what you develop, and look forward to seeing your content on the big screen!
To create an input method (IME) for entering text into text fields and other Views, you need to extend the 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.
InputMethodService
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:
AndroidManifest.xml
<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.
InputMethodService.onCreateInputView()
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.
null
InputMethodService.onCreateCandidatesView()
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.
InputMethodService.onStartInputView()
EditorInfo
(EditorInfo.inputType & EditorInfo.TYPE_CLASS_MASK) can be one of many different values, including:
EditorInfo.inputType & EditorInfo.TYPE_CLASS_MASK
TYPE_CLASS_NUMBER
TYPE_CLASS_DATETIME
TYPE_CLASS_PHONE
TYPE_CLASS_TEXT
See android.text.InputType for more details.
android.text.InputType
EditorInfo.inputType can contain other masked bits that indicate the class variation and other flags. For example, TYPE_TEXT_VARIATION_PASSWORD or TYPE_TEXT_VARIATION_URI or TYPE_TEXT_FLAG_AUTO_COMPLETE.
EditorInfo.inputType
TYPE_TEXT_VARIATION_PASSWORD
TYPE_TEXT_VARIATION_URI
TYPE_TEXT_FLAG_AUTO_COMPLETE
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.
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.
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.sendKeyEvent()
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.InputConnection are:
android.view.inputmethod.InputConnection
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("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.
InputMethodService.onKeyDown()
InputMethodService.onKeyUp().
super.onKey
Starting from Android 1.5, the Android platform offers an Input Method Framework (IMF) that lets you create on-screen input methods such as software keyboards. This article provide an overview of what Android input method editors (IMEs) are and what an application needs to do to work well with them. The IMF is designed to support new classes of Android devices, such as those without hardware keyboards, so it is important that your application works well with the IMF and offers a great experience for users.
The Android IMF is designed to support a variety of IMEs, including soft keyboard, hand-writing recognizers, and hard keyboard translators. Our focus, however, will be on soft keyboards, since this is the kind of input method that is currently part of the platform.
A user will usually access the current IME by tapping on a text view to edit, as shown here in the home screen:
The soft keyboard is positioned at the bottom of the screen over the application's window. To organize the available space between the application and IME, we use a few approaches; the one shown here is called pan and scan, and simply involves scrolling the application window around so that the currently focused view is visible. This is the default mode, since it is the safest for existing applications.
Most often the preferred screen layout is a resize, where the application's window is resized to be entirely visible. An example is shown here, when composing an e-mail message:
The size of the application window is changed so that none of it is hidden by the IME, allowing full access to both the application and IME. This of course only works for applications that have a resizeable area that can be reduced to make enough space, but the vertical space in this mode is actually no less than what is available in landscape orientation, so very often an application can already accommodate it.
The final major mode is fullscreen or extract mode. This is used when the IME is too large to reasonably share space with the underlying application. With the standard IMEs, you will only encounter this situation when the screen is in a landscape orientation, although other IMEs are free to use it whenever they desire. In this case the application window is left as-is, and the IME simply displays fullscreen on top of it, as shown here:
Because the IME is covering the application, it has its own editing area, which shows the text actually contained in the application. There are also some limited opportunities the application has to customize parts of the IME (the "done" button at the top and enter key label at the bottom) to improve the user experience.
There are a number of things the system does to try to help existing applications work with IMEs as well as possible, such as:
There are also some simple things you can do in your application that will often greatly improve its user experience. Except where explicitly mentioned, these will work in any Android platform version, even those previous to Android 1.5 (since they will simply ignore these new options).
The most important thing for an application to do is to use the new android:inputType attribute on each EditText. The attribute provides much richer information about the text content. This attribute actually replaces many existing attributes (android:password, android:singleLine, android:numeric, android:phoneNumber, android:capitalize, android:autoText, and android:editable). If you specify the older attributes and the new android:inputType attribute, the system uses android:inputType and ignores the others.
android:inputType
EditText
android:
password
singleLine
numeric
phoneNumber
capitalize
autoText
editable
The android:inputType attribute has three pieces:
text
number
phone
datetime
textEmailAddress
numberSigned
textCapSentences
textAutoCorrect
textMultiline
As an example, here is the new EditText for the IM application's message text view:
<EditText android:id="@+id/edtInput" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="1" android:inputType="textShortMessage|textAutoCorrect|textCapSentences|textMultiLine" android:imeOptions="actionSend|flagNoEnterAction" android:maxLines="4" android:maxLength="2000" android:hint="@string/compose_hint"/>
A full description of all of the input types can be found in the documentation. It is important to make use of the correct input types that are available, so that the soft keyboard can use the optimal keyboard layout for the text the user will be entering.
The second most important thing for your app to do is to specify the overall behavior of your window in relation to the input method. The most visible aspect of this is controlling resize vs. pan and scan mode, but there are other things you can do as well to improve your user experience.
You will usually control this behavior through the android:windowSoftInputMode attribute on each <activity> definition in your AndroidManifest.xml. Like the input type, there are a couple different pieces of data that can be specified here by combining them together:
android:windowSoftInputMode
<activity>
adjustResize
adjustPan
stateVisible
A typical example of this field can be see in the edit contact activity, which ensures it is resized and automatically displays the IME for the user:
<activity name="EditContactActivity" android:windowSoftInputMode="stateVisible|adjustResize"> ... </activity>
Note:Starting from Android 1.5 (API Level 3), the platform offers a new method, {@link android.view.Window#setSoftInputMode(int mode)}, that non-Activity windows can use to control their behavior. Calling this method in your will make your application incompatible with previous versions of the Android platform.
The final customization we will look at is the "action" buttons in the IME. There are currently two types of actions:
These options are controlled with the android:imeOptions attribute on TextView. The value you supply here can be any combination of:
android:imeOptions
TextView
actionGo
actionSearch
actionSend
actionNext
actionDone
actionNone
flagNoEnterAction
flagNoAccessoryAction
flagNoExtractUi
The previous IM application message view also provides an example of an interesting use of imeOptions, to specify the send action but not let it be shown on the enter key:
imeOptions
android:imeOptions="actionSend|flagNoEnterAction"
For more advanced control over the IME, there are a variety of new APIs you can use. Unless special care is taken (such as by using reflection), using these APIs will cause your application to be incompatible with previous versions of Android, and you should make sure you specify android:minSdkVersion="3" in your manifest. For more information, see the documentation for the <uses-sdk> manifest element.
android:minSdkVersion="3"
The primary API is the new android.view.inputmethod.InputMethodManager class, which you can retrieve with Context.getSystemService(). It allows you to interact with the global input method state, such as explicitly hiding or showing the current IME's input area.
android.view.inputmethod.InputMethodManager
Context.getSystemService()
There are also new window flags controlling input method interaction, which you can control through the existing Window.addFlags() method and new Window.setSoftInputMode() method. The PopupWindow class has grown corresponding methods to control these options on its window. One thing in particular to be aware of is the new WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM constant, which is used to control whether a window is on top of or behind the current IME.
Window.addFlags()
Window.setSoftInputMode()
PopupWindow
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
Most of the interaction between an active IME and application is done through the android.view.inputmethod.InputConnection class. This is the API an application implement, which an IME calls to perform the appropriate edit operations on the application. You won't normally need to worry about this, since TextView provides its own implementation for itself.
There are also a handful of new View APIs, the most important of these being onCreateInputConnection() which creates a new InputConnection for an IME (and fills in an android.view.inputmethod.EditorInfo structure with your input type, IME options, and other data); again, most developers won't need to worry about this, since TextView takes care of it for you.
View
onCreateInputConnection()
InputConnection
android.view.inputmethod.EditorInfo