1# InputMethodExtensionAbility 2 3## When to Use 4[InputMethodExtensionAbility](../reference/apis-ime-kit/js-apis-inputmethod-extension-ability.md), inherited from [ExtensionAbility](extensionability-overview.md), is used for developing input method applications. 5 6The entire lifecycle of the [InputMethodExtensionAbility](../reference/apis-ime-kit/js-apis-inputmethod-extension-ability.md) instance and the owning ExtensionAbility process is scheduled and managed by the input method framework. The input method framework provides the [InputMethodExtensionAbility](../reference/apis-ime-kit/js-apis-inputmethod-extension-ability.md) base class. Derive this base class to implement initialization and resource clearing. 7 8[InputMethodExtensionAbility](../reference/apis-ime-kit/js-apis-inputmethod-extension-ability.md) provides related capabilities through [InputMethodExtensionContext](../reference/apis-ime-kit/js-apis-inputmethod-extension-context.md). 9 10 11## Implementing an Input Method Application 12 13[InputMethodExtensionAbility](../reference/apis-ime-kit/js-apis-inputmethod-extension-ability.md) provides the **onCreate()** and **onDestroy()** callbacks, as described below. Override them as required. 14 15- **onCreate()** 16 17 This callback is triggered when a service is created for the first time. You can perform initialization operations, for example, registering a common event listener. 18 19 > **NOTE** 20 > 21 > If a service has been created, starting it again does not trigger the **onCreate()** callback. 22 23- **onDestroy()** 24 25 This callback is triggered when the service is no longer used and the instance is ready for destruction. You can clear resources in this callback, for example, deregister the listener. 26 27 28## How to Develop 29 30To implement an input method application, manually create an InputMethodExtensionAbility component in DevEco Studio. The procedure is as follows: 31 321. In the **ets** directory of the target module, right-click and choose **New > Directory** to create a directory named **InputMethodExtensionAbility**. 33 342. Right-click the **InputMethodExtensionAbility** directory, choose **New** > **File**, and create four files: **KeyboardController.ts**, **InputMethodService.ts**, **Index.ets**, and **KeyboardKeyData.ts**. The file directory is as follows: 35 36``` 37/src/main/ 38├── ets/InputMethodExtensionAbility 39│ └──model/KeyboardController.ts # Shows the keyboard. 40│ └──InputMethodService.ts # Customizes a class that inherits from InputMethodExtensionAbility and add the required lifecycle callbacks. 41│ └──pages 42│ └── Index.ets # Draws the keyboard and adds the input and deletion features. 43│ └── KeyboardKeyData.ts # Defines keyboard attributes. 44├── resources/base/profile/main_pages.json 45``` 46 47## File Introduction 48 491. **InputMethodService.ts** file: 50 51 In the **InputMethodService.ts** file, add the dependency package for importing InputMethodExtensionAbility. Customize a class that inherits from InputMethodExtensionAbility and add the required lifecycle callbacks. 52 53 ```ts 54 import Want from '@ohos.app.ability.Want'; 55 import InputMethodExtensionAbility from '@ohos.InputMethodExtensionAbility'; 56 import keyboardController from './model/KeyboardController' 57 58 export default class InputDemoService extends InputMethodExtensionAbility { 59 60 onCreate(want: Want): void { 61 keyboardController.onCreate(this.context); // Initialize the window and register an event listener for the input method framework. 62 } 63 64 onDestroy(): void { 65 console.log("onDestroy."); 66 keyboardController.onDestroy(); // Destroy the window and deregister the event listener. 67 } 68 } 69 ``` 70 712. **KeyboardController.ts** file: 72 73 ```ts 74 import common from '@ohos.app.ability.common'; 75 import display from '@ohos.display'; 76 import inputMethodEngine from '@ohos.inputMethodEngine'; 77 import InputMethodExtensionContext from '@ohos.InputMethodExtensionContext'; 78 79 // Call the getInputMethodAbility API to obtain an instance, and then call the other APIs of the input method framework based on the instance. 80 const inputMethodAbility: inputMethodEngine.InputMethodAbility = inputMethodEngine.getInputMethodAbility(); 81 82 export class KeyboardController { 83 private mContext: InputMethodExtensionContext | undefined = undefined; // Save the context attribute in InputMethodExtensionAbility. 84 private panel: inputMethodEngine.Panel | undefined = undefined; 85 private textInputClient: inputMethodEngine.InputClient | undefined = undefined; 86 private keyboardController: inputMethodEngine.KeyboardController | undefined = undefined; 87 88 constructor() { 89 } 90 91 public onCreate(context: InputMethodExtensionContext): void 92 { 93 this.mContext = context; 94 this.initWindow(); // Initialize the window. 95 this.registerListener(); // Register an event listener for the input method framework. 96 } 97 98 public onDestroy(): void // Destroy the instance. 99 { 100 this.unRegisterListener(); // Deregister the event listener. 101 if(this.panel) { // Destroy the window. 102 this.panel.hide(); 103 inputMethodAbility.destroyPanel(this.panel); 104 } 105 if(this.mContext) { 106 this.mContext.destroy(); 107 } 108 } 109 110 public insertText(text: string): void { 111 if(this.textInputClient) { 112 this.textInputClient.insertText(text); 113 } 114 } 115 116 public deleteForward(length: number): void { 117 if(this.textInputClient) { 118 this.textInputClient.deleteForward(length); 119 } 120 } 121 122 private initWindow(): void // Initialize the window. 123 { 124 if(this.mContext === undefined) { 125 return; 126 } 127 let dis = display.getDefaultDisplaySync(); 128 let dWidth = dis.width; 129 let dHeight = dis.height; 130 let keyHeightRate = 0.47; 131 let keyHeight = dHeight * keyHeightRate; 132 let nonBarPosition = dHeight - keyHeight; 133 let panelInfo: inputMethodEngine.PanelInfo = { 134 type: inputMethodEngine.PanelType.SOFT_KEYBOARD, 135 flag: inputMethodEngine.PanelFlag.FLG_FIXED 136 }; 137 inputMethodAbility.createPanel(this.mContext, panelInfo).then(async (inputPanel: inputMethodEngine.Panel) => { 138 this.panel = inputPanel; 139 if(this.panel) { 140 await this.panel.resize(dWidth, keyHeight); 141 await this.panel.moveTo(0, nonBarPosition); 142 await this.panel.setUiContent('inputmethodextability/pages/Index'); 143 } 144 }); 145 } 146 147 private registerListener(): void 148 { 149 this.registerInputListener(); // Register an event listener for the input method framework service. 150 ... 151 // Register a listener for keyboard hiding. 152 } 153 154 private registerInputListener(): void { // Register a listener for the enabling and disabling events of the input method framework service. 155 inputMethodAbility.on('inputStart', (kbController, textInputClient) => { 156 this.textInputClient = textInputClient; // This is an input method client instance, based on which you can call the APIs that the input method framework provides for the input method. 157 this.keyboardController = kbController; 158 }) 159 inputMethodAbility.on('inputStop', () => { 160 this.onDestroy (); // Destroy the KeyboardController instance. 161 }); 162 } 163 164 private unRegisterListener(): void 165 { 166 inputMethodAbility.off('inputStart'); 167 inputMethodAbility.off('inputStop', () => {}); 168 } 169 } 170 171 const keyboardController = new KeyboardController(); 172 173 export default keyboardController; 174 ``` 175 1763. **KeyboardKeyData.ts** file: 177 178 In this file you can define the content displayed on the soft keyboard. 179 180 ```ts 181 export interface sourceListType { 182 content: string, 183 } 184 185 export let numberSourceListData: sourceListType[] = [ 186 { 187 content: '1' 188 }, 189 { 190 content: '2' 191 }, 192 { 193 content: '3' 194 }, 195 { 196 content: '4' 197 }, 198 { 199 content: '5' 200 }, 201 { 202 content: '6' 203 }, 204 { 205 content: '7' 206 }, 207 { 208 content: '8' 209 }, 210 { 211 content: '9' 212 }, 213 { 214 content: '0' 215 } 216 ] 217 ``` 218 2194. **Index.ets** file: 220 221 This file describes the functions of keys. For example, the number keys print numbers in the text box, and the delete key deletes what's entered. 222 223 Add the path to this file to the **src** field in the **resources/base/profile/main_pages.json** file. 224 225 ```ets 226 import { numberSourceListData, sourceListType } from './keyboardKeyData'; 227 import keyboardController from '../InputMethodExtensionAbility/model/KeyboardController'; 228 229 @Component 230 struct keyItem { 231 private keyValue: sourceListType = numberSourceListData[0]; 232 @State keyBgc: string = "#fff" 233 @State keyFontColor: string = "#000" 234 235 build() { 236 Column() { 237 Flex({ direction: FlexDirection.Column, 238 alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 239 Text(this.keyValue.content).fontSize(20).fontColor(this.keyFontColor) 240 } 241 } 242 .backgroundColor(this.keyBgc) 243 .borderRadius(6) 244 .width("8%") 245 .height("65%") 246 .onClick(() => { 247 keyboardController.insertText(this.keyValue.content); 248 }) 249 } 250 } 251 252 // Component used for deletion. 253 @Component 254 export struct deleteItem { 255 @State keyBgc: string = "#fff" 256 @State keyFontColor: string = "#000" 257 258 build() { 259 Column() { 260 Flex({ direction: FlexDirection.Column, 261 alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 262 Text("Delete").fontSize(20).fontColor(this.keyFontColor) 263 } 264 } 265 .backgroundColor(this.keyBgc) 266 .width("13%") 267 .borderRadius(6) 268 .onClick(() => { 269 keyboardController.deleteForward(1); 270 }) 271 } 272 } 273 274 // Numeric keyboard 275 @Component 276 struct numberMenu { 277 private numberList: sourceListType[] = numberSourceListData; 278 279 build() { 280 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceEvenly }) { 281 Flex({ justifyContent: FlexAlign.SpaceBetween }) { 282 ForEach(this.numberList, (item: sourceListType) => {// First row on the numeric keyboard 283 keyItem({ keyValue: item }) 284 }, (item: sourceListType) => item.content); 285 } 286 .padding({ top: "2%" }) 287 .width("96%") 288 .height("25%") 289 290 Flex({ justifyContent: FlexAlign.SpaceBetween }) { 291 deleteItem() 292 } 293 .width("96%") 294 .height("25%") 295 } 296 } 297 } 298 299 @Entry 300 @Component 301 struct Index { 302 private numberList: sourceListType[] = numberSourceListData 303 304 build() { 305 Stack() { 306 Flex({ 307 direction: FlexDirection.Column, 308 alignItems: ItemAlign.Center, 309 justifyContent: FlexAlign.End 310 }) { 311 Flex({ 312 direction: FlexDirection.Column, 313 alignItems: ItemAlign.Center, 314 justifyContent: FlexAlign.SpaceBetween 315 }) { 316 numberMenu({ 317 numberList: this.numberList 318 }) 319 } 320 .align(Alignment.End) 321 .width("100%") 322 .height("75%") 323 } 324 .height("100%").align(Alignment.End).backgroundColor("#cdd0d7") 325 } 326 .position({ x: 0, y: 0 }).zIndex(99999) 327 } 328 } 329 ``` 330 3315. Register the InputMethodExtensionAbility in the [module.json5 file](../quick-start/module-configuration-file.md) corresponding to the **Module** project. Set **type** to **"inputMethod"** and **srcEntry** to the code path of the InputMethodExtensionAbility component. 332 333 ```json 334 { 335 "module": { 336 ... 337 "extensionAbilities": [ 338 { 339 "description": "inputMethod", 340 "icon": "$media:icon", 341 "name": "InputMethodExtAbility", 342 "srcEntry": "./ets/InputMethodExtensionAbility/InputMethodService.ts", 343 "type": "inputMethod", 344 "exported": true, 345 } 346 ] 347 } 348 } 349 ``` 350 351## Verification 352 3531. Run the hdc command to display the dialog box for switching between input methods: **hdc shell aa start ability -a InputMethod -b com.ohos.inputmethodchoosedialog** 354 3552. In the dialog box for switching between input methods, switch the input method to the demo application. 356 3573. When you touch any edit box, the demo application should start. 358 359## Constraints 360 361To protect the InputMethodExtensionAbility against abuse, the invoking of APIs in the modules listed below is restricted in the InputMethodExtensionAbility. 362 363> **NOTE** 364> 365> - If a restricted module is imported, no error is reported during compilation, but an incorrect value (**undefined**) is returned during running, which renders the imported module ineffective. 366> - Currently, access to the [@ohos.multimedia.audio (Audio Management)](../reference/apis-audio-kit/js-apis-audio.md) module is allowed, but subject to the following rules: 367> - Users who deny the recording permission should still be allowed to use the non-voice-input features of the input method application. 368> - Recording-related services are allowed only when the InputMethodExtensionAbility is in the foreground. For example, perform recording only when the soft keyboard is in the foreground and the user is proactively using the voice input method; stop recording when the application is switched to the background. 369> - Applications will be subject to increasingly stringent measures against violations with the preceding rules, and any violation may result in service exceptions. 370 371**Module list:** 372 373- [@ohos.ability.featureAbility (FeatureAbility)](../reference/apis-ability-kit/js-apis-ability-featureAbility.md) 374- [@ohos.ability.particleAbility (ParticleAbility)](../reference/apis-ability-kit/js-apis-ability-particleAbility.md) 375- [@ohos.account.distributedAccount (Distributed Account Management)](../reference/apis-basic-services-kit/js-apis-distributed-account.md) 376- [@ohos.backgroundTaskManager (Background Task Management)](../reference/apis-backgroundtasks-kit/js-apis-backgroundTaskManager.md) 377- [@ohos.bluetooth (Bluetooth)](../reference/apis-connectivity-kit/js-apis-bluetooth.md) 378- [@ohos.bluetoothManager (Bluetooth)](../reference/apis-connectivity-kit/js-apis-bluetoothManager.md) 379- [@ohos.connectedTag (Active Tags)](../reference/apis-connectivity-kit/js-apis-connectedTag.md) 380- [@ohos.geolocation (Geolocation)](../reference/apis-location-kit/js-apis-geolocation.md) 381- [@ohos.geoLocationManager (Geolocation Manager)](../reference/apis-location-kit/js-apis-geoLocationManager.md) 382- [@ohos.nfc.cardEmulation (Standard NFC Card Emulation)](../reference/apis-connectivity-kit/js-apis-cardEmulation.md) 383- [@ohos.nfc.controller (Standard NFC)](../reference/apis-connectivity-kit/js-apis-nfcController.md) 384- [@ohos.nfc.tag (Standard NFC Tags)](../reference/apis-connectivity-kit/js-apis-nfcTag.md) 385- [@ohos.reminderAgent (reminderAgent)](../reference/apis-backgroundtasks-kit/js-apis-reminderAgent.md) 386- [@ohos.reminderAgentManager (Agent-Powered Reminders)](../reference/apis-backgroundtasks-kit/js-apis-reminderAgentManager.md) 387- [@ohos.sensor (Sensor)](../reference/apis-sensor-service-kit/js-apis-sensor.md) 388- [@ohos.telephony.call (Call)](../reference/apis-telephony-kit/js-apis-call.md) 389- [@ohos.telephony.data (Cellular Data)](../reference/apis-telephony-kit/js-apis-telephony-data.md) 390- [@ohos.telephony.observer (observer)](../reference/apis-telephony-kit/js-apis-observer.md) 391- [@ohos.telephony.radio (Network Search)](../reference/apis-telephony-kit/js-apis-radio.md) 392- [@ohos.telephony.sim (SIM Management)](../reference/apis-telephony-kit/js-apis-sim.md) 393- [@ohos.telephony.sms (SMS)](../reference/apis-telephony-kit/js-apis-sms.md) 394- [@ohos.telephony.call (Call) (System API)](../reference/apis-telephony-kit/js-apis-call-sys.md) 395- [@ohos.telephony.data (Cellular Data) (System API)](../reference/apis-telephony-kit/js-apis-telephony-data-sys.md) 396- [@ohos.telephony.observer (Observer) (System API)](../reference/apis-telephony-kit/js-apis-observer-sys.md) 397- [@ohos.telephony.radio (Radio) (System API)](../reference/apis-telephony-kit/js-apis-radio-sys.md) 398- [@ohos.telephony.sim (SIM Management) (System API)](../reference/apis-telephony-kit/js-apis-sim-sys.md) 399- [@ohos.telephony.sms (SMS) (System API)](../reference/apis-telephony-kit/js-apis-sms-sys.md) 400- [@ohos.wallpaper (Wallpaper)](../reference/apis-basic-services-kit/js-apis-wallpaper.md) 401- [@ohos.wifiext (WLAN Extension)](../reference/apis-connectivity-kit/js-apis-wifiext.md) 402- [@ohos.wifiManager (WLAN)](../reference/apis-connectivity-kit/js-apis-wifiManager.md) 403- [@ohos.wifiManagerExt (WLAN Extension)](../reference/apis-connectivity-kit/js-apis-wifiManagerExt.md) 404- [@system.geolocation (Geolocation)](../reference/apis-location-kit/js-apis-system-location.md) 405- [nfctech (Standard NFC Technologies)](../reference/apis-connectivity-kit/js-apis-nfctech.md) 406- [tagSession (Standard NFC Tag Session)](../reference/apis-connectivity-kit/js-apis-tagSession.md) 407 408<!--no_check--> 409 410 411