<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" /> <meta content="IE=edge" http-equiv="X-UA-Compatible"> <link rel="shortcut icon" type="image/x-icon" href="../../../favicon.ico" /> <link rel="alternate" href="http://developer.android.com/guide/topics/text/creating-input-method.html" hreflang="en" /> <link rel="alternate" href="http://developer.android.com/intl/es/guide/topics/text/creating-input-method.html" hreflang="es" /> <link rel="alternate" href="http://developer.android.com/intl/id/guide/topics/text/creating-input-method.html" hreflang="id" /> <link rel="alternate" href="http://developer.android.com/intl/ja/guide/topics/text/creating-input-method.html" hreflang="ja" /> <link rel="alternate" href="http://developer.android.com/intl/ko/guide/topics/text/creating-input-method.html" hreflang="ko" /> <link rel="alternate" href="http://developer.android.com/intl/pt-br/guide/topics/text/creating-input-method.html" hreflang="pt-br" /> <link rel="alternate" href="http://developer.android.com/intl/ru/guide/topics/text/creating-input-method.html" hreflang="ru" /> <link rel="alternate" href="http://developer.android.com/intl/vi/guide/topics/text/creating-input-method.html" hreflang="vi" /> <link rel="alternate" href="http://developer.android.com/intl/zh-cn/guide/topics/text/creating-input-method.html" hreflang="zh-cn" /> <link rel="alternate" href="http://developer.android.com/intl/zh-tw/guide/topics/text/creating-input-method.html" hreflang="zh-tw" /> <title>Creating an Input Method | Android Developers </title> <meta name="description" content="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…"> <!-- STYLESHEETS --> <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto+Condensed"> <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto"> <link href="../../../assets/css/default.css?v=16" rel="stylesheet" type="text/css"> <!-- JAVASCRIPT --> <script src="http://www.google.com/jsapi" type="text/javascript"></script> <script src="../../../assets/js/android_3p-bundle.js" type="text/javascript"></script> <script type="text/javascript"> var toRoot = "../../../"; var metaTags = ["ime","keyboard","inputmethodservice"]; var devsite = false; var useUpdatedTemplates = false; </script> <script src="../../../assets/js/docs.js?v=17" type="text/javascript"></script> <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-5831155-1', 'android.com'); ga('create', 'UA-49880327-2', 'android.com', {'name': 'universal'}); // New tracker); ga('send', 'pageview'); ga('universal.send', 'pageview'); // Send page view for new tracker. </script> </head> <body class="gc-documentation develop guide" itemscope itemtype="http://schema.org/Article"> <a name="top"></a> <!-- Header --> <div id="header-wrapper"> <div class="dac-header " id="header"> <div class="dac-header-inner"> <a class="dac-nav-toggle" data-dac-toggle-nav href="javascript:;" title="Open navigation"> <span class="dac-nav-hamburger"> <span class="dac-nav-hamburger-top"></span> <span class="dac-nav-hamburger-mid"></span> <span class="dac-nav-hamburger-bot"></span> </span> </a> <a class="dac-header-logo" href="../../../index.html"> <img class="dac-header-logo-image" src="../../../assets/images/android_logo.png" srcset="../../../assets/images/android_logo@2x.png 2x" width="32" height="36" alt="Android" /> Developers </a> <ul class="dac-header-tabs"> <li> <a class="dac-header-tab" href="../../../design/index.html" zh-tw-lang="設計" zh-cn-lang="设计" ru-lang="Проектирование" ko-lang="디자인" ja-lang="設計" es-lang="Diseñar">Design</a> </li> <li> <a class="dac-header-tab" href="../../../develop/index.html" zh-tw-lang="開發" zh-cn-lang="开发" ru-lang="Разработка" ko-lang="개발" ja-lang="開発" es-lang="Desarrollar">Develop</a> </li> <li> <a class="dac-header-tab" href="../../../distribute/index.html" zh-tw-lang="發佈" zh-cn-lang="分发" ru-lang="Распространение" ko-lang="배포" ja-lang="配布" es-lang="Distribuir">Distribute</a> </li> </ul> <a class="dac-header-console-btn" href="https://play.google.com/apps/publish/"> <span class="dac-sprite dac-google-play"></span> <span class="dac-visible-desktop-inline">Developer</span> Console </a> <form data-search class="dac-header-search"> <button class="dac-header-search-close" data-search-close> <i class="dac-sprite dac-back-arrow"></i> </button> <div class="dac-header-search-inner"> <i class="dac-sprite dac-search-white dac-header-search-icon"></i> <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q" class="dac-header-search-input" placeholder="Search" /> <button class="dac-header-search-clear dac-hidden" data-search-clear> <i class="dac-sprite dac-close-black"></i> </button> </div> </form> </div><!-- end header-wrap.wrap --> </div><!-- end header --> </div> <!--end header-wrapper --> <!-- Navigation--> <nav class="dac-nav"> <div class="dac-nav-dimmer" data-dac-toggle-nav></div> <div class="dac-nav-sidebar" data-swap data-dynamic="false" data-transition-speed="300" data-dac-nav> <div data-swap-container> <a class="dac-nav-back-button dac-swap-section dac-up dac-no-anim" data-swap-button href="javascript:;"> <i class="dac-sprite dac-nav-back"></i> <span class="dac-nav-back-title">Back</span> </a> <div class="dac-nav-sub dac-swap-section dac-right dac-active" itemscope itemtype="http://schema.org/SiteNavigationElement"> <ul id="nav"> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/index.html"> <span class="en">Introduction</span> </a></div> <ul> <li><a href="../../../guide/components/fundamentals.html"> <span class="en">App Fundamentals</span></a> </li> <li><a href="../../../guide/practices/compatibility.html"> <span class="en">Device Compatibility</span> </a></li> <li><a href="../../../guide/topics/security/permissions.html"> <span class="en">System Permissions</span> </a> </li> </ul> </li> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/components/index.html"> <span class="en">App Components</span> </a></div> <ul> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/components/intents-filters.html"> <span class="en">Intents and Intent Filters</span> </a></div> <ul> <li><a href="../../../guide/components/intents-common.html"> <span class="en">Common Intents</span> </a></li> </ul> </li> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/components/activities.html"> <span class="en">Activities</span> </a></div> <ul> <li><a href="../../../guide/components/fragments.html"> <span class="en">Fragments</span> </a></li> <li><a href="../../../guide/components/loaders.html"> <span class="en">Loaders</span> </a></li> <li><a href="../../../guide/components/tasks-and-back-stack.html"> <span class="en">Tasks and Back Stack</span> </a></li> <li><a href="../../../guide/components/recents.html"> <span class="en">Overview Screen</span> </a></li> </ul> </li> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/components/services.html"> <span class="en">Services</span> </a></div> <ul> <li><a href="../../../guide/components/bound-services.html"> <span class="en">Bound Services</span> </a></li> <li><a href="../../../guide/components/aidl.html"> <span class="en">AIDL</span> </a></li> </ul> </li> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/providers/content-providers.html"> <span class="en">Content Providers</span> </a></div> <ul> <li><a href="../../../guide/topics/providers/content-provider-basics.html"> <span class="en">Content Provider Basics</span> </a></li> <li><a href="../../../guide/topics/providers/content-provider-creating.html"> <span class="en">Creating a Content Provider</span> </a></li> <li><a href="../../../guide/topics/providers/calendar-provider.html"> <span class="en">Calendar Provider</span> </a></li> <li><a href="../../../guide/topics/providers/contacts-provider.html"> <span class="en">Contacts Provider</span> </a></li> <li><a href="../../../guide/topics/providers/document-provider.html"> <span class="en">Storage Access Framework</span> </a></li> </ul> </li> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/appwidgets/index.html"> <span class="en">App Widgets</span> </a></div> <ul> <li><a href="../../../guide/topics/appwidgets/host.html"> <span class="en">App Widget Host</span> </a></li> </ul> </li> <li><a href="../../../guide/components/processes-and-threads.html"> <span class="en">Processes and Threads</span> </a> </li> </ul> </li> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/resources/index.html"> <span class="en">App Resources</span> </a></div> <ul> <li><a href="../../../guide/topics/resources/overview.html"> <span class="en">Overview</span> </a></li> <li><a href="../../../guide/topics/resources/providing-resources.html"> <span class="en">Providing Resources</span> </a></li> <li><a href="../../../guide/topics/resources/accessing-resources.html"> <span class="en">Accessing Resources</span> </a></li> <li><a href="../../../guide/topics/resources/runtime-changes.html"> <span class="en">Handling Runtime Changes</span> </a></li> <li><a href="../../../guide/topics/resources/localization.html"> <span class="en">Localization</span> </a></li> <li><a href="../../../guide/topics/resources/complex-xml-resources.html"> <span class="en">Complex XML Resources</span> </a></li> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/resources/available-resources.html"> <span class="en">Resource Types</span> </a></div> <ul> <li><a href="../../../guide/topics/resources/animation-resource.html">Animation</a></li> <li><a href="../../../guide/topics/resources/color-list-resource.html">Color State List</a></li> <li><a href="../../../guide/topics/resources/drawable-resource.html">Drawable</a></li> <li><a href="../../../guide/topics/resources/layout-resource.html">Layout</a></li> <li><a href="../../../guide/topics/resources/menu-resource.html">Menu</a></li> <li><a href="../../../guide/topics/resources/string-resource.html">String</a></li> <li><a href="../../../guide/topics/resources/style-resource.html">Style</a></li> <li><a href="../../../guide/topics/resources/more-resources.html">More Types</a></li> </ul> </li><!-- end of resource types --> </ul> </li><!-- end of app resources --> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/manifest/manifest-intro.html"> <span class="en">App Manifest</span> </a></div> <ul> <li><a href="../../../guide/topics/manifest/action-element.html"><action></a></li> <li><a href="../../../guide/topics/manifest/activity-element.html"><activity></a></li> <li><a href="../../../guide/topics/manifest/activity-alias-element.html"><activity-alias></a></li> <li><a href="../../../guide/topics/manifest/application-element.html"><application></a></li> <li><a href="../../../guide/topics/manifest/category-element.html"><category></a></li> <li><a href="../../../guide/topics/manifest/compatible-screens-element.html"><compatible-screens></a></li> <li><a href="../../../guide/topics/manifest/data-element.html"><data></a></li> <li><a href="../../../guide/topics/manifest/grant-uri-permission-element.html"><grant-uri-permission></a></li> <li><a href="../../../guide/topics/manifest/instrumentation-element.html"><instrumentation></a></li> <li><a href="../../../guide/topics/manifest/intent-filter-element.html"><intent-filter></a></li> <li><a href="../../../guide/topics/manifest/manifest-element.html"><manifest></a></li> <li><a href="../../../guide/topics/manifest/meta-data-element.html"><meta-data></a></li> <li><a href="../../../guide/topics/manifest/path-permission-element.html"><path-permission></a></li> <li><a href="../../../guide/topics/manifest/permission-element.html"><permission></a></li> <li><a href="../../../guide/topics/manifest/permission-group-element.html"><permission-group></a></li> <li><a href="../../../guide/topics/manifest/permission-tree-element.html"><permission-tree></a></li> <li><a href="../../../guide/topics/manifest/provider-element.html"><provider></a></li> <li><a href="../../../guide/topics/manifest/receiver-element.html"><receiver></a></li> <li><a href="../../../guide/topics/manifest/service-element.html"><service></a></li> <li><a href="../../../guide/topics/manifest/supports-gl-texture-element.html"><supports-gl-texture></a></li> <li><a href="../../../guide/topics/manifest/supports-screens-element.html"><supports-screens></a></li><!-- ##api level 4## --> <li><a href="../../../guide/topics/manifest/uses-configuration-element.html"><uses-configuration></a></li> <li><a href="../../../guide/topics/manifest/uses-feature-element.html"><uses-feature></a></li> <!-- ##api level 4## --> <li><a href="../../../guide/topics/manifest/uses-library-element.html"><uses-library></a></li> <li><a href="../../../guide/topics/manifest/uses-permission-element.html"><uses-permission></a></li> <li><a href="../../../guide/topics/manifest/uses-permission-sdk-23-element.html"><uses-permission-sdk-23></a></li> <li><a href="../../../guide/topics/manifest/uses-sdk-element.html"><uses-sdk></a></li> </ul> </li><!-- end of the manifest file --> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/ui/index.html"> <span class="en">User Interface</span> </a></div> <ul> <li><a href="../../../guide/topics/ui/overview.html"> <span class="en">Overview</span> </a></li> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/ui/declaring-layout.html"> <span class="en">Layouts</span> </a></div> <ul> <li><a href="../../../guide/topics/ui/layout/linear.html"> <span class="en">Linear Layout</span> </a></li> <li><a href="../../../guide/topics/ui/layout/relative.html"> <span class="en">Relative Layout</span> </a></li> <!-- <li><a href="../../../guide/topics/ui/layout/grid.html"> <span class="en">Grid Layout</span> </a></li> --> <li><a href="../../../guide/topics/ui/layout/listview.html"> <span class="en">List View</span> </a></li> <li><a href="../../../guide/topics/ui/layout/gridview.html"> <span class="en">Grid View</span> </a></li> </ul> </li> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/ui/controls.html"> <span class="en">Input Controls</span> </a></div> <ul> <li><a href="../../../guide/topics/ui/controls/button.html"> <span class="en">Buttons</span> </a></li> <li><a href="../../../guide/topics/ui/controls/text.html"> <span class="en">Text Fields</span> </a></li> <li><a href="../../../guide/topics/ui/controls/checkbox.html"> <span class="en">Checkboxes</span> </a></li> <li><a href="../../../guide/topics/ui/controls/radiobutton.html"> <span class="en">Radio Buttons</span> </a></li> <li><a href="../../../guide/topics/ui/controls/togglebutton.html"> <span class="en">Toggle Buttons</span> </a></li> <li><a href="../../../guide/topics/ui/controls/spinner.html"> <span class="en">Spinners</span> </a></li> <li><a href="../../../guide/topics/ui/controls/pickers.html"> <span class="en">Pickers</span> </a></li> <!-- <li><a href="../../../guide/topics/ui/controls/progress.html"> <span class="en">Seek and Progress Bars</span> </a></li> --> </ul> </li> <li><a href="../../../guide/topics/ui/ui-events.html"> <span class="en">Input Events</span> </a></li> <li><a href="../../../guide/topics/ui/menus.html"> <span class="en">Menus</span></span> </a></li> <li><a href="../../../guide/topics/ui/settings.html"> <span class="en">Settings</span> </a></li> <li><a href="../../../guide/topics/ui/dialogs.html"> <span class="en">Dialogs</span> </a></li> <li><a href="../../../guide/topics/ui/notifiers/notifications.html"> <span class="en">Notifications</span> </a></li> <li><a href="../../../guide/topics/ui/notifiers/toasts.html"> <span class="en">Toasts</span> </a></li> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/search/index.html"> <span class="en">Search</span> </a></div> <ul> <li><a href="../../../guide/topics/search/search-dialog.html">Creating a Search Interface</a></li> <li><a href="../../../guide/topics/search/adding-recent-query-suggestions.html">Adding Recent Query Suggestions</a></li> <li><a href="../../../guide/topics/search/adding-custom-suggestions.html">Adding Custom Suggestions</a></li> <li><a href="../../../guide/topics/search/searchable-config.html">Searchable Configuration</a></li> </ul> </li> <li><a href="../../../guide/topics/ui/drag-drop.html"> <span class="en">Drag and Drop</span> </a></li> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/ui/accessibility/index.html"> <span class="en">Accessibility</span> </a></div> <ul> <li><a href="../../../guide/topics/ui/accessibility/apps.html"> <span class="en">Making Applications Accessible</span> </a></li> <li><a href="../../../guide/topics/ui/accessibility/checklist.html"> <span class="en">Accessibility Developer Checklist</span> </a></li> <li><a href="../../../guide/topics/ui/accessibility/services.html"> <span class="en">Building Accessibility Services</span> </a></li> </ul> </li> <li><a href="../../../guide/topics/ui/themes.html"> <span class="en">Styles and Themes</span> </a></li> <li><a href="../../../guide/topics/ui/custom-components.html"> <span class="en">Custom Components</span> </a></li> </ul> </li><!-- end of User Interface --> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/graphics/index.html"> <span class="en">Animation and Graphics</span> </a></div> <ul> <li class="nav-section"> <li><a href="../../../guide/topics/graphics/overview.html"> <span class="en">Overview</span> </a></li> <li><a href="../../../guide/topics/graphics/prop-animation.html"> <span class="en">Property Animation</span> </a></li> <li><a href="../../../guide/topics/graphics/view-animation.html"> <span class="en">View Animation</span> </a></li> <li><a href="../../../guide/topics/graphics/drawable-animation.html"> <span class="en">Drawable Animation</span> </a></li> <li><a href="../../../guide/topics/graphics/2d-graphics.html"> <span class="en">Canvas and Drawables</span> </a></li> <li><a href="../../../guide/topics/graphics/opengl.html"> <span class="en">OpenGL ES</span> </a></li> <li><a href="../../../guide/topics/graphics/hardware-accel.html"> <span class="en">Hardware Acceleration</span> </a></li> </ul> </li><!-- end of graphics and animation--> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/renderscript/index.html"> <span class="en">Computation</span> </a></div> <ul> <li><a href="../../../guide/topics/renderscript/compute.html"> <span class="en">RenderScript</span></a> </li> <li><a href="../../../guide/topics/renderscript/advanced.html"> <span class="en">Advanced RenderScript</span></a> </li> <li class="nav-section"> <div class="nav-section-header"> <a href="../../../guide/topics/renderscript/reference/overview.html"> <span class="en">Runtime API Reference</span> </a></div> <ul> <li><a href="../../../guide/topics/renderscript/reference/rs_value_types.html"> <span class="en">Numerical Types</span> </a></li> <li><a href="../../../guide/topics/renderscript/reference/rs_object_types.html"> <span class="en">Object Types</span> </a></li> <li><a href="../../../guide/topics/renderscript/reference/rs_convert.html"> <span class="en">Conversion Functions</span> </a></li> <li><a href="../../../guide/topics/renderscript/reference/rs_math.html"> <span class="en">Mathematical Constants and Functions</span> </a></li> <li><a href="../../../guide/topics/renderscript/reference/rs_vector_math.html"> <span class="en">Vector Math Functions</span> </a></li> <li><a href="../../../guide/topics/renderscript/reference/rs_matrix.html"> <span class="en">Matrix Functions</span> </a></li> <li><a href="../../../guide/topics/renderscript/reference/rs_quaternion.html"> <span class="en">Quaternion Functions</span> </a></li> <li><a href="../../../guide/topics/renderscript/reference/rs_atomic.html"> <span class="en">Atomic Update Functions</span> </a></li> <li><a href="../../../guide/topics/renderscript/reference/rs_time.html"> <span class="en">Time Functions and Types</span> </a></li> <li><a href="../../../guide/topics/renderscript/reference/rs_allocation_data.html"> <span class="en">Allocation Data Access Functions</span> </a></li> <li><a href="../../../guide/topics/renderscript/reference/rs_object_info.html"> <span class="en">Object Characteristics Functions</span> </a></li> <li><a href="../../../guide/topics/renderscript/reference/rs_for_each.html"> <span class="en">Kernel Invocation Functions and Types</span> </a></li> <li><a href="../../../guide/topics/renderscript/reference/rs_io.html"> <span class="en">Input/Output Functions</span> </a></li> <li><a href="../../../guide/topics/renderscript/reference/rs_debug.html"> <span class="en">Debugging Functions</span> </a></li> <li><a href="../../../guide/topics/renderscript/reference/rs_graphics.html"> <span class="en">Graphics Functions and Types</span> </a></li> <li><a href="../../../guide/topics/renderscript/reference/index.html"> <span class="en">Index</span> </a></li> </ul> </li> </ul> </li> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/media/index.html"> <span class="en">Media and Camera</span> </a></div> <ul> <li><a href="../../../guide/topics/media/mediaplayer.html"> <span class="en">Media Playback</span></a> </li> <li><a href="../../../guide/topics/media/mediarouter.html"> <span class="en">Media Router</span></a> </li> <li><a href="../../../guide/topics/media/mediarouteprovider.html"> <span class="en">Media Route Provider</span></a> </li> <li><a href="../../../guide/topics/media/exoplayer.html"> <span class="en">ExoPlayer</span></a> </li> <li><a href="../../../guide/appendix/media-formats.html"> <span class="en">Supported Media Formats</span></a> </li> <li><a href="../../../guide/topics/media/audio-capture.html"> <span class="en">Audio Capture</span></a> </li> <li><a href="../../../guide/topics/media/jetplayer.html"> <span class="en">JetPlayer</span></a> </li> <li><a href="../../../guide/topics/media/camera.html"> <span class="en">Camera</span></a> </li> </ul> </li><!-- end of media and camera --> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/sensors/index.html"> <span class="en">Location and Sensors</span> </a></div> <ul> <li><a href="../../../guide/topics/location/index.html"> <span class="en">Location and Maps</span> </a> <li><a href="../../../guide/topics/location/strategies.html"> <span class="en">Location Strategies</span> </a></li> <li><a href="../../../guide/topics/sensors/sensors_overview.html"> <span class="en">Sensors Overview</span> </a></li> <li><a href="../../../guide/topics/sensors/sensors_motion.html"> <span class="en">Motion Sensors</span> </a></li> <li><a href="../../../guide/topics/sensors/sensors_position.html"> <span class="en">Position Sensors</span> </a></li> <li><a href="../../../guide/topics/sensors/sensors_environment.html"> <span class="en">Environment Sensors</span> </a></li> </ul> </li><!-- end of location and sensors --> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/connectivity/index.html"> <span class="en">Connectivity</span> </a></div> <ul> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/connectivity/bluetooth.html"> <span class="en">Bluetooth</span></a> </div> <ul> <li><a href="../../../guide/topics/connectivity/bluetooth-le.html">Bluetooth Low Energy</a></li> </ul> </li> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/connectivity/nfc/index.html"> <span class="en">NFC</span></a> </div> <ul> <li><a href="../../../guide/topics/connectivity/nfc/nfc.html">NFC Basics</a></li> <li><a href="../../../guide/topics/connectivity/nfc/advanced-nfc.html">Advanced NFC</a></li> <li><a href="../../../guide/topics/connectivity/nfc/hce.html">Host-based Card Emulation</a></li> </ul> </li> <li><a href="../../../guide/topics/connectivity/wifip2p.html"> <span class="en">Wi-Fi P2P</span></a> </li> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/connectivity/usb/index.html"> <span class="en">USB</span></a> </div> <ul> <li><a href="../../../guide/topics/connectivity/usb/accessory.html">Accessory</a></li> <li><a href="../../../guide/topics/connectivity/usb/host.html">Host</a></li> </ul> </li> <li><a href="../../../guide/topics/connectivity/sip.html"> <span class="en">SIP</span> </a> </li> </ul> </li><!-- end of connectivity --> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/text/index.html"> <span class="en">Text and Input</span> </a></div> <ul> <li><a href="../../../guide/topics/text/copy-paste.html"> <span class="en">Copy and Paste</span> </a></li> <li><a href="../../../guide/topics/text/creating-input-method.html"> <span class="en">Creating an IME</span> </a></li> <li><a href="../../../guide/topics/text/spell-checker-framework.html"> <span class="en">Spelling Checker</span> </a></li> </ul> </li><!-- end of text and input --> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/data/index.html"> <span class="en">Data Storage</span> </a></div> <ul> <li><a href="../../../guide/topics/data/data-storage.html"> <span class="en">Storage Options</span> </a></li> <li><a href="../../../guide/topics/data/backup.html"> <span class="en">Data Backup</span> </a></li> <li><a href="../../../guide/topics/data/install-location.html"> <span class="en">App Install Location</span> </a></li> </ul> </li><!-- end of data storage --> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/admin/index.html"> <span class="en">Administration</span> </a></div> <ul> <li> <a href="../../../guide/topics/admin/device-admin.html"> <span class="en">Device Policies</span></a> </li> <!-- <li> <a href="../../../guide/topics/admin/keychain.html"> <span class="en">Certificate Store</span></a> </li> --> </ul> </li><!-- end of administration --> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/webapps/index.html"> <span class="en">Web Apps</span> </a></div> <ul> <li><a href="../../../guide/webapps/targeting.html"> <span class="en">Supporting Different Screens in Web Apps</span> </a></li> <li><a href="../../../guide/webapps/webview.html"> <span class="en">Building Web Apps in WebView</span> </a></li> <li><a href="../../../guide/webapps/migrating.html"> <span class="en">Migrating to WebView in Android 4.4</span> </a></li> <li><a href="../../../guide/webapps/debugging.html"> <span class="en">Debugging Web Apps</span> </a></li> <li><a href="../../../guide/webapps/best-practices.html"> <span class="en">Best Practices for Web Apps</span> </a></li> </ul> </li><!-- end of web apps --> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/practices/index.html"> <span class="en">Best Practices</span> <span class="de" style="display:none">Bewährte Verfahren</span> <span class="es" style="display:none">Prácticas recomendadas</span> <span class="fr" style="display:none">Meilleures pratiques</span> <span class="it" style="display:none">Best practice</span> <span class="ja" style="display:none">ベスト プラクティス</span> <span class="zh-cn" style="display:none">最佳实践</span> <span class="zh-tw" style="display:none">最佳實務</span> </div></a> <ul> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/practices/screens_support.html"> <span class="en">Supporting Multiple Screens</span> </a></div> <ul> <li><a href="../../../guide/practices/screens-distribution.html"> <span class="en">Distributing to Specific Screens</span> </a></li> <li><a href="../../../guide/practices/screen-compat-mode.html"> <span class="en">Screen Compatibility Mode</span> </a></li> </ul> </li> <li><a href="../../../guide/practices/tablets-and-handsets.html"> <span class="en">Supporting Tablets and Handsets</span> </a></li> <li> <a href="../../../guide/practices/verifying-apps-art.html"> <span class="en">Verifying App Behavior on ART</span> </a> </li> </ul> </li> <li class="nav-section"> <div class="nav-section-header"><a href="../../../guide/topics/security/index.html"> <span class="en">Security</span> </a></div> <ul> <li><a href="../../../guide/topics/security/security-config.html"> <span class="en">Network Security Config</span> </a></li> </ul> </li> </ul> <script type="text/javascript"> <!-- buildToggleLists(); changeNavLang(getLangPref()); //--> </script> </div> <ul id="dac-main-navigation" class="dac-nav-list dac-swap-section dac-left dac-no-anim"> <li class="dac-nav-item home"> <a class="dac-nav-link" href="../../../index.html">Home</a> <i class="dac-sprite dac-expand-more-black dac-nav-sub-slider"></i> <ul class="dac-nav-secondary about"> <li class="dac-nav-item versions"> <a class="dac-nav-link" href="../../../about/versions/marshmallow/index.html">Android</a> </li> <li class="dac-nav-item wear"> <a class="dac-nav-link" href="../../../wear/index.html">Wear</a> </li> <li class="dac-nav-item tv"> <a class="dac-nav-link" href="../../../tv/index.html">TV</a> </li> <li class="dac-nav-item auto"> <a class="dac-nav-link" href="../../../auto/index.html">Auto</a> </li> </ul> </li> <li class="dac-nav-item design"> <a class="dac-nav-link" href="../../../design/index.html" zh-tw-lang="設計" zh-cn-lang="设计" ru-lang="Проектирование" ko-lang="디자인" ja-lang="設計" es-lang="Diseñar">Design</a> </li> <li class="dac-nav-item develop"> <a class="dac-nav-link" href="../../../develop/index.html" zh-tw-lang="開發" zh-cn-lang="开发" ru-lang="Разработка" ko-lang="개발" ja-lang="開発" es-lang="Desarrollar">Develop</a> <i class="dac-sprite dac-expand-more-black dac-nav-sub-slider"></i> <ul class="dac-nav-secondary develop"> <li class="dac-nav-item training"> <a class="dac-nav-link" href="../../../training/index.html" zh-tw-lang="訓練課程" zh-cn-lang="培训" ru-lang="Курсы" ko-lang="교육" ja-lang="トレーニング" es-lang="Capacitación">Training</a> </li> <li class="dac-nav-item guide"> <a class="dac-nav-link" href="../../../guide/index.html" zh-tw-lang="API 指南" zh-cn-lang="API 指南" ru-lang="Руководства по API" ko-lang="API 가이드" ja-lang="API ガイド" es-lang="Guías de la API">API Guides</a> </li> <li class="dac-nav-item reference"> <a class="dac-nav-link" href="../../../reference/packages.html" zh-tw-lang="參考資源" zh-cn-lang="参考" ru-lang="Справочник" ko-lang="참조문서" ja-lang="リファレンス" es-lang="Referencia">Reference</a> </li> <li class="dac-nav-item tools"> <a class="dac-nav-link" href="../../../sdk/index.html" zh-tw-lang="相關工具" zh-cn-lang="工具" ru-lang="Инструменты" ko-lang="도구" ja-lang="ツール" es-lang="Herramientas">Tools</a></li> <li class="dac-nav-item google"> <a class="dac-nav-link" href="../../../google/index.html">Google Services</a> </li> </ul> </li> <li class="dac-nav-item distribute"> <a class="dac-nav-link" href="../../../distribute/googleplay/index.html" zh-tw-lang="發佈" zh-cn-lang="分发" ru-lang="Распространение" ko-lang="배포" ja-lang="配布" es-lang="Distribuir">Distribute</a> <i class="dac-sprite dac-expand-more-black dac-nav-sub-slider"></i> <ul class="dac-nav-secondary distribute"> <li class="dac-nav-item googleplay"> <a class="dac-nav-link" href="../../../distribute/googleplay/index.html">Google Play</a></li> <li class="dac-nav-item essentials"> <a class="dac-nav-link" href="../../../distribute/essentials/index.html">Essentials</a></li> <li class="dac-nav-item users"> <a class="dac-nav-link" href="../../../distribute/users/index.html">Get Users</a></li> <li class="dac-nav-item engage"> <a class="dac-nav-link" href="../../../distribute/engage/index.html">Engage & Retain</a></li> <li class="dac-nav-item monetize"> <a class="dac-nav-link" href="../../../distribute/monetize/index.html">Earn</a> </li> <li class="dac-nav-item analyze"> <a class="dac-nav-link" href="../../../distribute/analyze/index.html">Analyze</a> </li> <li class="dac-nav-item stories"> <a class="dac-nav-link" href="../../../distribute/stories/index.html">Stories</a> </li> </ul> </li> <li class="dac-nav-item preview"> <a class="dac-nav-link" href="../../../preview/index.html">Preview</a> </li> </ul> </div> </div> </nav> <!-- end navigation--> <!-- Nav Setup --> <script>$('[data-dac-nav]').dacNav();</script> <div class="wrap clearfix" id="body-content"> <div id="search-results" class="dac-search-results"> <div id="dac-search-results-history" class="dac-search-results-history"> <div class="wrap dac-search-results-history-wrap"> <div class="cols"> <div class="col-1of2 col-tablet-1of2 col-mobile-1of1"> <h2>Most visited</h2> <div class="resource-flow-layout" data-history-query="history:most/visited" data-maxresults="3" data-cardsizes="18x2"></div> </div> <div class="col-1of2 col-tablet-1of2 col-mobile-1of1"> <h2>Recently visited</h2> <div class="resource-flow-layout cols" data-history-query="history:recent" data-allow-duplicates="true" data-maxresults="3" data-cardsizes="18x2"></div> </div> </div> </div> </div> <div id="dac-search-results-content" class="dac-search-results-content"> <div class="dac-search-results-metadata wrap"> <div class="dac-search-results-for"> <h2>Results for <span id="search-results-for"></span></h2> </div> <div id="dac-search-results-hero"></div> <div class="dac-search-results-hero cols"> <div id="dac-search-results-reference" class="col-3of6 col-tablet-1of2 col-mobile-1of1"> <div class="suggest-card reference no-display"> <ul class="dac-search-results-reference"> </ul> </div> </div> <div id="dac-custom-search-results"></div> </div> </div> </div> </div> <ul class="dac-header-crumbs"> </ul> <!-- Breadcrumb Setup --> <p><script>$('.dac-nav-list').dacCurrentPage().dacCrumbs();</script></p> <h1 itemprop="name" >Creating an Input Method</h1> <div id="jd-content"> <div class="jd-descr" itemprop="articleBody"> <div id="qv-wrapper"> <div id="qv"> <h2>In This Document</h2> <ol> <li><a href="#InputMethodLifecycle">The IME Lifecycle</a></li> <li><a href="#DefiningIME">Declaring IME Components in the Manifest</a></li> <li><a href="#IMEAPI">The Input Method API</a></li> <li><a href="#IMEUI">Designing the Input Method UI</a></li> <li><a href="#SendText">Sending Text to the Application</a></li> <li><a href="#IMESubTypes">Creating an IME Subtype</a></li> <li><a href="#Switching">Switching among IME Subtypes</a></li> <li><a href="#GeneralDesign">General IME Considerations</a></li> </ol> <h2>See also</h2> <ol> <li> <a href="http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html">Onscreen Input Methods</a> </li> </ol> <h2>Sample</h2> <ol> <li><a href="https://android.googlesource.com/platform/development/+/master/samples/SoftKeyboard/"> SoftKeyboard</a> </li> </ol> </div> </div> <p> 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. After installing the desired IMEs, a user can select which one to use from the system settings, and use it across the entire system; only one IME may be enabled at a time. </p> <p> To add an IME to the Android system, you create an Android application containing a class that extends <code><a href="../../../reference/android/inputmethodservice/InputMethodService.html">InputMethodService</a></code>. 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. </p> <p>This guide covers the following:</p> <ul> <li>The IME lifecycle</li> <li>Declaring IME components in the application manifest</li> <li>The IME API</li> <li>Designing an IME UI</li> <li>Sending text from an IME to an application</li> <li>Working with IME subtypes</li> </ul> <p> If you haven't worked with IMEs before, you should read the introductory article <a href="http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html">Onscreen Input Methods</a> first. Also, the <a href="https://android.googlesource.com/platform/development/+/master/samples/SoftKeyboard/"> SoftKeyboard</a> sample app included in the SDK contains sample code that you can modify to start building your own IME. </p> <h2 id="InputMethodLifecycle">The IME Lifecycle</h2> <p> The following diagram describes the life cycle of an IME: </p> <img src="../../../resources/articles/images/inputmethod_lifecycle_image.png" alt="" height="845" id="figure1" /> <p class="img-caption"> <strong>Figure 1.</strong> The life cycle of an IME. </p> <p> The following sections describe how to implement the UI and code associated with an IME that follows this lifecycle. </p> <h2 id="DefiningIME">Declaring IME Components in the Manifest</h2> <p> 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 <code>action.view.InputMethod</code>, 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. </p> <p> The following snippet declares an IME service. It requests the permission <code><a href="../../../reference/android/Manifest.permission.html#BIND_INPUT_METHOD">BIND_INPUT_METHOD</a></code> to allow the service to connect the IME to the system, sets up an intent filter that matches the action <code>android.view.InputMethod</code>, and defines metadata for the IME: </p> <pre> <!-- 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> </pre> <p> This next snippet declares the settings activity for the IME. It has an intent filter for <code><a href="../../../reference/android/content/Intent.html#ACTION_MAIN">ACTION_MAIN</a></code> that indicates this activity is the main entry point for the IME application:</p> <pre> <!-- 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> </pre> <p> You can also provide access to the IME's settings directly from its UI. </p> <h2 id="IMEAPI">The Input Method API</h2> <p> Classes specific to IMEs are found in the <code><a href="../../../reference/android/inputmethodservice/package-summary.html">android.inputmethodservice</a></code> and <code><a href="../../../reference/android/view/inputmethod/package-summary.html">android.view.inputmethod</a></code> packages. The <code><a href="../../../reference/android/view/KeyEvent.html">KeyEvent</a></code> class is important for handling keyboard characters. </p> <p> The central part of an IME is a service component, a class that extends <code><a href="../../../reference/android/inputmethodservice/InputMethodService.html">InputMethodService</a></code>. 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 <code><a href="../../../reference/android/inputmethodservice/InputMethodService.html">InputMethodService</a></code> class provides most of the implementation for managing the state and visibility of the IME and communicating with the current input field. </p> <p> The following classes are also important: </p> <dl> <dt><code><a href="../../../reference/android/view/inputmethod/BaseInputConnection.html">BaseInputConnection</a></code></dt> <dd> Defines the communication channel from an <code><a href="../../../reference/android/view/inputmethod/InputMethod.html">InputMethod</a></code> back to the application that is receiving its input. You use it to read text around the cursor, commit text to the text box, and send raw key events to the application. Applications should extend this class rather than implementing the base interface <code><a href="../../../reference/android/view/inputmethod/InputConnection.html">InputConnection</a></code>. </dd> <dt><code><a href="../../../reference/android/inputmethodservice/KeyboardView.html">KeyboardView</a></code></dt> <dd> An extension of <code><a href="../../../reference/android/view/View.html">View</a></code> that renders a keyboard and responds to user input events. The keyboard layout is specified by an instance of <code><a href="../../../reference/android/inputmethodservice/Keyboard.html">Keyboard</a></code>, which you can define in an XML file. </dd> </dl> <h2 id="IMEUI">Designing the Input Method UI</h2> <p> There are two main visual elements for an IME: the <strong>input</strong> view and the <strong>candidates</strong> view. You only have to implement the elements that are relevant to the input method you're designing. </p> <h3 id="InputView">Input view</h3> <p> The input view is the UI where the user inputs text in the form of keyclicks, handwriting or gestures. When the IME is displayed for the first time, the system calls the <code><a href="../../../reference/android/inputmethodservice/InputMethodService.html#onCreateInputView()">onCreateInputView()</a></code> 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 <code><a href="../../../reference/android/inputmethodservice/InputMethodService.html#onCreateInputView()">onCreateInputView()</a></code> method: <pre> @Override public View onCreateInputView() { MyKeyboardView inputView = (MyKeyboardView) getLayoutInflater().inflate( R.layout.input, null); inputView.setOnKeyboardActionListener(this); inputView.setKeyboard(mLatinKeyboard); return mInputView; } </pre> <p> In this example, <code>MyKeyboardView</code> is an instance of a custom implementation of <code><a href="../../../reference/android/inputmethodservice/KeyboardView.html">KeyboardView</a></code> that renders a <code><a href="../../../reference/android/inputmethodservice/Keyboard.html">Keyboard</a></code>. If you’re building a traditional QWERTY keyboard, see the <a href="https://android.googlesource.com/platform/development/+/master/samples/SoftKeyboard/> SoftKeyboard</a> sample app for an example of how to extend the <code><a href="../../../reference/android/inputmethodservice/KeyboardView.html">KeyboardView</a></code> class. </p> <h3 id="CandidateView">Candidates view</h3> <p> 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 <code><a href="../../../reference/android/inputmethodservice/InputMethodService.html#onCreateCandidatesView()">onCreateCandidatesView()</a></code> when it's ready to display the candidates 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.</p> <p> For an example implementation that provides user suggestions, see the <a href="https://android.googlesource.com/platform/development/+/master/samples/SoftKeyboard/"> SoftKeyboard</a> sample app. </p> <h3 id="DesignConsiderations">UI design considerations</h3> <p> This section describes some specific UI design considerations for IMEs. </p> <h4>Handling multiple screen sizes</h4> <p> 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. </p> <h4>Handling different input types</h4> <p> 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 valid for the input type; that's the responsibility of the application that owns the text field. </p> <p> For example, here are screenshots of the interfaces that the Latin IME provided with the Android platform provides for text and phone number inputs: </p> <img src="../../../resources/articles/images/inputmethod_text_type_screenshot.png" alt="" height="142" id="figure2" /> <img src="../../../resources/articles/images/inputmethod_numeric_type_screenshot.png" alt="" height="120" id="figure2a" /> <p class="img-caption"> <strong>Figure 2.</strong> Latin IME input types. </p> <p> When an input field receives focus and your IME starts, the system calls <code><a href="../../../reference/android/inputmethodservice/InputMethodService.html#onStartInputView(android.view.inputmethod.EditorInfo, boolean)">onStartInputView()</a></code>, passing in an <code><a href="../../../reference/android/view/inputmethod/EditorInfo.html">EditorInfo</a></code> object that contains details about the input type and other attributes of the text field. In this object, the <code><a href="../../../reference/android/view/inputmethod/EditorInfo.html#inputType">inputType</a></code> field contains the text field's input type. </p> <p> The <code><a href="../../../reference/android/view/inputmethod/EditorInfo.html#inputType">inputType</a></code> field is an <code>int</code> that contains bit patterns for various input type settings. To test it for the text field's input type, mask it with the constant <code><a href="../../../reference/android/text/InputType.html#TYPE_MASK_CLASS">TYPE_MASK_CLASS</a></code>, like this: </p> <pre> inputType & InputType.TYPE_MASK_CLASS </pre> <p> The input type bit pattern can have one of several values, including: </p> <dl> <dt><code><a href="../../../reference/android/text/InputType.html#TYPE_CLASS_NUMBER">TYPE_CLASS_NUMBER</a></code></dt> <dd> A text field for entering numbers. As illustrated in the previous screen shot, the Latin IME displays a number pad for fields of this type. </dd> <dt><code><a href="../../../reference/android/text/InputType.html#TYPE_CLASS_DATETIME">TYPE_CLASS_DATETIME</a></code></dt> <dd> A text field for entering a date and time. </dd> <dt><code><a href="../../../reference/android/text/InputType.html#TYPE_CLASS_PHONE">TYPE_CLASS_PHONE</a></code></dt> <dd> A text field for entering telephone numbers. </dd> <dt><code><a href="../../../reference/android/text/InputType.html#TYPE_CLASS_TEXT">TYPE_CLASS_TEXT</a></code></dt> <dd> A text field for entering all supported characters. </dd> </dl> <p> These constants are described in more detail in the reference documentation for <code><a href="../../../reference/android/text/InputType.html">InputType</a></code>. </p> <p> The <code><a href="../../../reference/android/view/inputmethod/EditorInfo.html#inputType">inputType</a></code> field can contain other bits that indicate a variant of the text field type, such as: </p> <dl> <dt><code><a href="../../../reference/android/text/InputType.html#TYPE_TEXT_VARIATION_PASSWORD">TYPE_TEXT_VARIATION_PASSWORD</a></code></dt> <dd> A variant of <code><a href="../../../reference/android/text/InputType.html#TYPE_CLASS_TEXT">TYPE_CLASS_TEXT</a></code> for entering passwords. The input method will display dingbats instead of the actual text. </dd> <dt><code><a href="../../../reference/android/text/InputType.html#TYPE_TEXT_VARIATION_URI">TYPE_TEXT_VARIATION_URI</a></code></dt> <dd> A variant of <code><a href="../../../reference/android/text/InputType.html#TYPE_CLASS_TEXT">TYPE_CLASS_TEXT</a></code> for entering web URLs and other Uniform Resource Identifiers (URIs). </dd> <dt><code><a href="../../../reference/android/text/InputType.html#TYPE_TEXT_FLAG_AUTO_COMPLETE">TYPE_TEXT_FLAG_AUTO_COMPLETE</a></code></dt> <dd> A variant of <code><a href="../../../reference/android/text/InputType.html#TYPE_CLASS_TEXT">TYPE_CLASS_TEXT</a></code> for entering text that the application "auto-completes" from a dictionary, search, or other facility. </dd> </dl> <p> Remember to mask <code><a href="../../../reference/android/view/inputmethod/EditorInfo.html#inputType">inputType</a></code> with the appropriate constant when you test for these variants. The available mask constants are listed in the reference documentation for <code><a href="../../../reference/android/text/InputType.html">InputType</a></code>. </p> <p class="caution"> <strong>Caution:</strong> 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 <a href="../../../guide/practices/security.html">Designing for Security</a> guide. </p> <h2 id="SendText">Sending Text to the Application</h2> <p> 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 <code><a href="../../../reference/android/view/inputmethod/InputConnection.html">InputConnection</a></code> to deliver the text. To get this instance, call <code><a href="../../../reference/android/inputmethodservice/InputMethodService.html#getCurrentInputConnection()">InputMethodService.getCurrentInputConnection()</a></code>. </p> <h3 id="EditingCursor">Editing the text around the cursor</h3> <p> When you're handling the editing of existing text in a text field, some of the more useful methods in <code><a href="../../../reference/android/view/inputmethod/BaseInputConnection.html">BaseInputConnection</a></code> are: </p> <dl> <dt> <code><a href="../../../reference/android/view/inputmethod/BaseInputConnection.html#getTextBeforeCursor(int, int)">getTextBeforeCursor()</a></code></dt> <dd> Returns a <code><a href="../../../reference/java/lang/CharSequence.html">CharSequence</a></code> containing the number of requested characters before the current cursor position. </dd> <dt> <code><a href="../../../reference/android/view/inputmethod/BaseInputConnection.html#getTextAfterCursor(int, int)">getTextAfterCursor()</a></code> </dt> <dd> Returns a <code><a href="../../../reference/java/lang/CharSequence.html">CharSequence</a></code> containing the number of requested characters following the current cursor position. </dd> <dt> <code><a href="../../../reference/android/view/inputmethod/BaseInputConnection.html#deleteSurroundingText(int, int)">deleteSurroundingText()</a></code> </dt> <dd> Deletes the specified number of characters before and following the current cursor position. </dd> <dt> <code><a href="../../../reference/android/view/inputmethod/BaseInputConnection.html#commitText(java.lang.CharSequence, int)">commitText()</a></code> </dt> <dd> Commit a <code><a href="../../../reference/java/lang/CharSequence.html">CharSequence</a></code> to the text field and set a new cursor position. </dd> </dl> <p> For example, the following snippet shows how to replace the four characters to the left of the cursor with the text "Hello!": </p> <pre> InputConnection ic = getCurrentInputConnection(); ic.deleteSurroundingText(4, 0); ic.commitText("Hello", 1); ic.commitText("!", 1); </pre> <h3 id="ComposeThenCommit">Composing text before committing</h3> <p> 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 <code><a href="../../../reference/android/view/inputmethod/InputConnection.html#setComposingText(java.lang.CharSequence, int)">setComposingText()</a></code>. </p> <p> The following snippet shows how to show progress in a text field: </p> <pre> InputConnection ic = getCurrentInputConnection(); ic.setComposingText("Composi", 1); ... ic.setComposingText("Composin", 1); ... ic.commitText("Composing ", 1); </pre> <p> The following screenshots show how this appears to the user: </p> <img src="../../../resources/articles/images/inputmethod_composing_text_1.png" alt="" height="54" id="figure3a" /> <img src="../../../resources/articles/images/inputmethod_composing_text_2.png" alt="" height="53" id="figure3b" /> <img src="../../../resources/articles/images/inputmethod_composing_text_3.png" alt="" height="31" id="figure3c" /> <p class="img-caption"> <strong>Figure 3.</strong> Composing text before committing. </p> <h3 id="HardwareKeyEvents">Intercepting hardware key events</h3> <p> 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.</p> <p> To intercept hardware keys, override <code><a href="../../../reference/android/inputmethodservice/InputMethodService.html#onKeyDown(int, android.view.KeyEvent)">onKeyDown()</a></code> and <code><a href="../../../reference/android/inputmethodservice/InputMethodService.html#onKeyUp(int, android.view.KeyEvent)">onKeyUp()</a></code>. See the <a href="https://android.googlesource.com/platform/development/+/master/samples/SoftKeyboard/"> SoftKeyboard</a> sample app for an example. </p> <p> Remember to call the <code>super()</code> method for keys you don't want to handle yourself. </p> <h2 id="IMESubTypes">Creating an IME Subtype</h2> <p> Subtypes allow the IME to expose multiple input modes and languages supported by an IME. A subtype can represent: </p> <ul> <li>A locale such as en_US or fr_FR</li> <li>An input mode such as voice, keyboard, or handwriting</li> <li> Other input styles, forms, or properties specific to the IME, such as 10-key or qwerty keyboard layouts. </li> </ul> <p> Basically, the mode can be any text such as "keyboard", "voice", and so forth. A subtype can also expose a combination of these. </p> <p> 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. </p> <p> You define subtypes in one of the input method's XML resource files, using the <code><subtype></code> 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: </p> <pre> <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" ... /> /> </pre> <p> 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: </p> <pre> <subtype android:label="@string/label_subtype_generic" android:imeSubtypeLocale="en_US" android:icon="@drawable/icon_en_us" android:imeSubtypeMode="keyboard" /> </pre> <p> The next snippet is part of the IME's <code>strings.xml</code> file. The string resource <code>label_subtype_generic</code>, which is used by the input method UI definition to set the subtype's label, is defined as: </p> <pre> <string name="label_subtype_generic">%s</string> </pre> <p> This setting causes the subtype’s display name to match the locale setting. For example, in any English locale, the display name is “English (United States)”. </p> <h3 id="SubtypeProcessing">Choosing IME subtypes from the notification bar</h3> <p> 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: </p> <img src="../../../resources/articles/images/inputmethod_subtype_notification.png" alt="" height="85" id="figure4" /> <p class="img-caption"> <strong>Figure 4.</strong> Choosing an IME subtype from the notification bar. </p> <img src="../../../resources/articles/images/inputmethod_subtype_preferences.png" alt="" height="165" id="figure5" /> <p class="img-caption"> <strong>Figure 5.</strong> Setting subtype preferences in System Settings. </p> <h3 id="SubtypeSettings">Choosing IME subtypes from System Settings</h3> <p> A user can control how subtypes are used in the “Language & input” settings panel in the System Settings area. In the <a href="https://android.googlesource.com/platform/development/+/master/samples/SoftKeyboard/"> SoftKeyboard</a> sample app, the file <code>InputMethodSettingsFragment.java</code> contains an implementation that facilitates a subtype enabler in the IME settings. Refer to the <a href="https://android.googlesource.com/platform/development/+/master/samples/SoftKeyboard/"> SoftKeyboard</a> sample app in the Android SDK for more information about how to support Input Method Subtypes in your IME. </p> <img src="../../../resources/articles/images/inputmethod_subtype_settings.png" alt="" height="210" id="figure6" /> <p class="img-caption"> <strong>Figure 6.</strong> Choosing a language for the IME. </p> <h2 id="Switching">Switching among IME Subtypes</h2> <p>You can allow users to switch easily among multiple IME subtypes by providing a switching key, such as the globe-shaped language icon, as part of the keyboard. Doing so greatly improves the keyboard's usability, and can help avoid user frustration. To enable such switching, perform the following steps:</p> <p> <ol> <li>Declare <code>supportsSwitchingToNextInputMethod = "true"</code> in the input method's XML resource files. Your declaration should look similar to the following snippet: <pre> <input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="com.example.softkeyboard.Settings" android:icon="@drawable/ime_icon" android:supportsSwitchingToNextInputMethod="true"> </pre></li> <li>Call the <code><a href="../../../reference/android/view/inputmethod/InputMethodManager.html#shouldOfferSwitchingToNextInputMethod(android.os.IBinder)">shouldOfferSwitchingToNextInputMethod()</a></code> method.</li> <li>If the method returns true, display a switching key.</li> <li>When the user taps the switching key, call <code><a href="../../../reference/android/view/inputmethod/InputMethodManager.html#switchToNextInputMethod(android.os.IBinder, boolean)">switchToNextInputMethod()</a></code>, passing false to the second parameter. A value of false tells the system to treat all subtypes equally, regardless of what IME they belong to. Specifying true requires the system to cycle through subtypes in the current IME.</li> </ol> </p> <p class="caution"> <strong>Caution:</strong> Prior to Android 5.0 (API level 21), <code><a href="../../../reference/android/view/inputmethod/InputMethodManager.html#switchToNextInputMethod(android.os.IBinder, boolean)">switchToNextInputMethod()</a></code> is not aware of the <code>supportsSwitchingToNextInputMethod</code> attribute. If the user switches into an IME without a switching key, he or she may get stuck in that IME, unable to switch out of it easily.</p> <p> </p> <h2 id="GeneralDesign">General IME Considerations</h2> <p> Here are some other things to consider as you're implementing your IME: </p> <ul> <li> Provide a way for users to set options directly from the IME's UI. </li> <li> Because multiple IMEs may be installed on the device, provide a way for the user to switch to a different IME directly from the input method UI. </li> <li> Bring up the IME's UI quickly. Preload or load on demand any large resources so that users see the IME as soon as they tap on a text field. Cache resources and views for subsequent invocations of the input method. </li> <li> Conversely, you should release large memory allocations soon after the input method window is hidden, so that applications can have sufficient memory to run. Consider using a delayed message to release resources if the IME is in a hidden state for a few seconds. </li> <li> Make sure that users can enter as many characters as possible for the language or locale associated with the IME. Remember that users may use punctuation in passwords or user names, so your IME has to provide many different characters to allow users to enter a password and get access to the device. </li> </ul> </div> </div> <!-- end jd-content --> <div class="wrap"> <div class="dac-footer"> <div class="cols dac-footer-main"> <div class="col-1of2"> <a class="dac-footer-getnews" id="newsletter" data-modal-toggle="newsletter" href="javascript:;">Get news & tips <span class="dac-fab dac-primary"><i class="dac-sprite dac-mail"></i></span></a> </div> <div class="col-1of2 dac-footer-reachout"> <div class="dac-footer-contact"> <a class="dac-footer-contact-link" href="http://android-developers.blogspot.com/">Blog</a> <a class="dac-footer-contact-link" href="/support.html">Support</a> </div> <div class="dac-footer-social"> <a class="dac-button-social dac-youtube dac-footer-social-link" href="https://www.youtube.com/user/androiddevelopers"><i class="dac-sprite dac-youtube"></i></a> <a class="dac-button-social dac-gplus dac-footer-social-link" href="https://plus.google.com/+AndroidDevelopers"><i class="dac-sprite dac-gplus"></i></a> <a class="dac-button-social dac-twitter dac-footer-social-link" href="https://twitter.com/AndroidDev"><i class="dac-sprite dac-twitter"></i></a> </div> </div> </div> <hr class="dac-footer-separator"/> <p class="dac-footer-copyright"> Except as noted, this content is licensed under <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. For details and restrictions, see the <a href="../../../license.html">Content License</a>. </p> <p class="dac-footer-links"> <a href="/about/android.html">About Android</a> <a href="/auto/index.html">Auto</a> <a href="/tv/index.html">TV</a> <a href="/wear/index.html">Wear</a> <a href="/legal.html">Legal</a> <span id="language" class="locales"> <select name="language" onchange="changeLangPref(this.value, true)"> <option value="en" selected="selected">English</option> <option value="es">Español</option> <option value="in">Bahasa Indonesia</option> <option value="ja">日本語</option> <option value="ko">한국어</option> <option value="pt-br">Português Brasileiro</option> <option value="ru">Русский</option> <option value="vi">tiếng Việt</option> <option value="zh-cn">中文(简体)</option> <option value="zh-tw">中文(繁體)</option> </select> </span> </p> </div> </div> <!-- end footer --> <div data-modal="newsletter" data-newsletter data-swap class="dac-modal newsletter"> <div class="dac-modal-container"> <div class="dac-modal-window"> <header class="dac-modal-header"> <div class="dac-modal-header-actions"> <button class="dac-modal-header-close" data-modal-toggle></button> </div> <div class="dac-swap" data-swap-container> <section class="dac-swap-section dac-active dac-down"> <h2 class="norule dac-modal-header-title" data-t="newsletter.title"></h2> <p class="dac-modal-header-subtitle" data-t="newsletter.requiredHint"></p> </section> <section class="dac-swap-section dac-up"> <h2 class="norule dac-modal-header-title" data-t="newsletter.successTitle">Hooray!</h2> </section> </div> </header> <div class="dac-swap" data-swap-container> <section class="dac-swap-section dac-active dac-left"> <form action="https://docs.google.com/forms/d/1QgnkzbEJIDu9lMEea0mxqWrXUJu0oBCLD7ar23V0Yys/formResponse" class="dac-form" method="post" target="dac-newsletter-iframe"> <input type="hidden" name="entry.935454734" data-newsletter-language> <section class="dac-modal-content"> <fieldset class="dac-form-fieldset"> <div class="cols"> <div class="col-1of2 newsletter-leftCol"> <div class="dac-form-input-group"> <label for="newsletter-full-name" class="dac-form-floatlabel" data-t="newsletter.name">Full name</label> <input type="text" class="dac-form-input" name="entry.1357890476" id="newsletter-full-name" required> <span class="dac-form-required">*</span> </div> <div class="dac-form-input-group"> <label for="newsletter-email" class="dac-form-floatlabel" data-t="newsletter.email">Email address</label> <input type="email" class="dac-form-input" name="entry.472100832" id="newsletter-email" required> <span class="dac-form-required">*</span> </div> </div> <div class="col-1of2 newsletter-rightCol"> <div class="dac-form-input-group"> <label for="newsletter-company" class="dac-form-floatlabel" data-t="newsletter.company">Company / developer name</label> <input type="text" class="dac-form-input" name="entry.1664780309" id="newsletter-company"> </div> <div class="dac-form-input-group"> <label for="newsletter-play-store" class="dac-form-floatlabel" data-t="newsletter.appUrl">One of your Play Store app URLs</label> <input type="url" class="dac-form-input" name="entry.47013838" id="newsletter-play-store" required> <span class="dac-form-required">*</span> </div> </div> </div> </fieldset> <fieldset class="dac-form-fieldset"> <div class="cols"> <div class="col-1of2 newsletter-leftCol"> <legend class="dac-form-legend"><span data-t="newsletter.business.label">Which best describes your business:</span><span class="dac-form-required">*</span> </legend> <div class="dac-form-radio-group"> <input type="radio" value="Apps" class="dac-form-radio" name="entry.1796324055" id="newsletter-business-type-app" required> <label for="newsletter-business-type-app" class="dac-form-radio-button"></label> <label for="newsletter-business-type-app" class="dac-form-label" data-t="newsletter.business.apps">Apps</label> </div> <div class="dac-form-radio-group"> <input type="radio" value="Games" class="dac-form-radio" name="entry.1796324055" id="newsletter-business-type-games" required> <label for="newsletter-business-type-games" class="dac-form-radio-button"></label> <label for="newsletter-business-type-games" class="dac-form-label" data-t="newsletter.business.games">Games</label> </div> <div class="dac-form-radio-group"> <input type="radio" value="Apps and Games" class="dac-form-radio" name="entry.1796324055" id="newsletter-business-type-appsgames" required> <label for="newsletter-business-type-appsgames" class="dac-form-radio-button"></label> <label for="newsletter-business-type-appsgames" class="dac-form-label" data-t="newsletter.business.both">Apps & Games</label> </div> </div> <div class="col-1of2 newsletter-rightCol newsletter-checkboxes"> <div class="dac-form-radio-group"> <div class="dac-media"> <div class="dac-media-figure"> <input type="checkbox" class="dac-form-checkbox" name="entry.732309842" id="newsletter-add" required value="Add me to the mailing list for the monthly newsletter and occasional emails about development and Google Play opportunities."> <label for="newsletter-add" class="dac-form-checkbox-button"></label> </div> <div class="dac-media-body"> <label for="newsletter-add" class="dac-form-label dac-form-aside"><span data-t="newsletter.confirmMailingList"></span><span class="dac-form-required">*</span></label> </div> </div> </div> <div class="dac-form-radio-group"> <div class="dac-media"> <div class="dac-media-figure"> <input type="checkbox" class="dac-form-checkbox" name="entry.2045036090" id="newsletter-terms" required value="I acknowledge that the information provided in this form will be subject to Google's privacy policy (https://www.google.com/policies/privacy/)."> <label for="newsletter-terms" class="dac-form-checkbox-button"></label> </div> <div class="dac-media-body"> <label for="newsletter-terms" class="dac-form-label dac-form-aside"><span data-t="newsletter.privacyPolicy" data-t-html></span><span class="dac-form-required">*</span></label> </div> </div> </div> </div> </div> </fieldset> </section> <footer class="dac-modal-footer"> <div class="cols"> <div class="col-2of5"> </div> </div> <button type="submit" value="Submit" class="dac-fab dac-primary dac-large dac-modal-action"><i class="dac-sprite dac-arrow-right"></i></button> </footer> </form> </section> <section class="dac-swap-section dac-right"> <div class="dac-modal-content"> <p class="newsletter-success-message" data-t="newsletter.successDetails"></p> </div> </section> </div> </div> </div> </div> <!-- end newsletter modal --> <!-- start reset language header modal --> <div data-modal="langform" class="dac-modal" id="langform"> <div class="dac-modal-container"> <div class="dac-modal-window"> <header class="dac-modal-header"> <div class="dac-modal-header-actions"> <button class="dac-modal-header-close" data-modal-toggle></button> </div> <section class="dac-swap-section dac-active dac-down"> <h2 class="norule dac-modal-header-title"></h2> </section> </header> <section class="dac-swap-section dac-active dac-left"> <section class="dac-modal-content"> <fieldset class="dac-form-fieldset"> <div class="cols"> <div class="col-2of2 langform-leftCol"> <p id="resetLangText"></p> <p id="resetLangCta"></p> </div> </div> </fieldset> </section> <footer class="dac-modal-footer" id="langfooter"> <div class="cols"> <div class="col-2of5"> </div> </div> <button class="button dac-primary dac-modal-action lang yes" data-t="newsletter.resetLangButtonYes" data-modal-toggle></button> <button class="button dac-primary dac-modal-action lang no" data-t="newsletter.resetLangButtonNo" data-modal-toggle></button> </a> </footer> </form> </section> </div> </div> </div> <!-- end langreset modal --> </div> <!-- end body-content --> <script src="https://developer.android.com/ytblogger_lists_unified.js" defer></script> <script src="/jd_lists_unified_en.js?v=17" defer></script> <script src="/reference/lists.js?v=17" defer></script> <script src="/reference/gcm_lists.js?v=17" defer></script> <script src="/reference/gms_lists.js?v=17" defer></script> <script> // Load localized metadata. (function(lang) { if (lang === 'en') { return; } // Write it to the document so it gets evaluated before DOMContentReady. document.write('<script src="/jd_lists_unified_' + lang + '.js?v=14" defer></' + 'script>'); })(getLangPref()) </script> </body> </html>