1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15import ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility'; 16import common from '@ohos.app.ability.common'; 17import window from '@ohos.window'; 18import inputMethod from '@ohos.inputMethod'; 19import commonEvent from '@ohos.commonEventManager'; 20import Want from '@ohos.app.ability.Want'; 21import display from '@ohos.display'; 22import { BusinessError } from '@ohos.base'; 23 24let TAG: string = '[InputMethodChooseDialog]'; 25let PACKAGE_ADDED: string = 'usual.event.PACKAGE_ADDED'; 26let PACKAGE_REMOVED: string = 'usual.event.PACKAGE_REMOVED'; 27let subscribeInfo: commonEvent.CommonEventSubscribeInfo = { 28 events: [PACKAGE_ADDED, PACKAGE_REMOVED] 29}; 30 31interface DialogRect { 32 left: number; 33 top: number; 34 width: number; 35 height: number; 36} 37 38const DISPLAY_SCALE: number = 0.35; 39const MIN_SIZE: number = 350; 40const MAX_SZIE: number = 550; 41const DIALOG_POSITION_X: number = 50; 42const DIALOG_POSITION_Y_SCALE: number = 0.5; 43 44export default class ServiceExtAbility extends ServiceExtensionAbility { 45 private extensionWin: window.Window | undefined = undefined; 46 private mContext: common.ServiceExtensionContext | undefined = undefined; 47 private windowNum: number = 0; 48 49 onCreate(want: Want): void { 50 console.log(TAG, 'onCreate'); 51 this.windowNum = 0; 52 this.mContext = this.context; 53 } 54 55 onRequest(want: Want, startId: number): void { 56 console.log(TAG, 'onRequest execute'); 57 let defaultDisplay = display.getDefaultDisplaySync(); 58 let size = defaultDisplay.width * DISPLAY_SCALE > MIN_SIZE ? defaultDisplay.width * DISPLAY_SCALE : MIN_SIZE; 59 size = size < MAX_SZIE ? size : MAX_SZIE; 60 let dialogTop = defaultDisplay.height * DIALOG_POSITION_Y_SCALE; 61 let dialogRect: DialogRect = { 62 left: DIALOG_POSITION_X, 63 top: dialogTop, 64 width: size, 65 height: size 66 }; 67 let windowConfig: window.Configuration = { 68 name: 'inputmethod Dialog', 69 windowType: window.WindowType.TYPE_FLOAT, 70 ctx: this.mContext 71 }; 72 this.getInputMethods().then(() => { 73 this.createWindow(windowConfig, dialogRect); 74 }); 75 76 commonEvent.createSubscriber(subscribeInfo, (error: BusinessError, subcriber: commonEvent.CommonEventSubscriber) => { 77 commonEvent.subscribe(subcriber, (error: BusinessError, commonEventData: commonEvent.CommonEventData) => { 78 if (error) { 79 console.log(TAG + `commonEvent subscribe error, errorCode: ${error}`); 80 return; 81 } 82 console.log(TAG + 'commonEvent:' + JSON.stringify(commonEventData?.event)); 83 if (commonEventData?.event === PACKAGE_ADDED || commonEventData?.event === PACKAGE_REMOVED) { 84 this.updateImeList(); 85 } 86 }); 87 }); 88 } 89 90 onDestroy(): void { 91 console.log(TAG + 'ServiceExtAbility destroyed'); 92 this.releaseContext(); 93 } 94 95 private async createWindow(config: window.Configuration, rect: DialogRect): Promise<void> { 96 console.log(TAG + 'createWindow execute'); 97 try { 98 if (this.windowNum > 0) { 99 this.updateImeList(); 100 return; 101 } 102 try { 103 this.extensionWin = await window.createWindow(config); 104 console.info(TAG + 'Succeeded in creating the window. Data: ' + JSON.stringify(this.extensionWin)); 105 this.extensionWin.on('windowEvent', async (data: window.WindowEventType) => { 106 console.log(TAG + 'windowEvent:' + JSON.stringify(data)); 107 if (data === window.WindowEventType.WINDOW_INACTIVE) { 108 await this.releaseContext(); 109 } 110 }); 111 await this.extensionWin.moveWindowTo(rect.left, rect.top); 112 await this.extensionWin.resize(rect.width, rect.height); 113 await this.extensionWin.setUIContent('pages/index'); 114 await this.extensionWin.showWindow(); 115 this.windowNum++; 116 console.log(TAG + 'window create successfully'); 117 } catch (exception) { 118 console.error('Failed to create the window. Cause: ' + JSON.stringify(exception)); 119 } 120 } catch { 121 console.info(TAG + 'window create failed'); 122 } 123 } 124 125 private async getInputMethods(): Promise<void> { 126 let inputMethodList: Array<inputMethod.InputMethodProperty> = []; 127 try { 128 let enableList = await inputMethod.getSetting().getInputMethods(true); 129 let disableList = await inputMethod.getSetting().getInputMethods(false); 130 inputMethodList = enableList.concat(disableList); 131 AppStorage.setOrCreate('inputMethodList', inputMethodList); 132 } catch { 133 console.log(TAG + 'getInputMethods failed'); 134 } 135 } 136 137 private async updateImeList(): Promise<void> { 138 await this.getInputMethods().then(async () => { 139 if (this.extensionWin) { 140 await this.extensionWin.setUIContent('pages/index'); 141 if (!this.extensionWin.isWindowShowing()) { 142 await this.extensionWin.showWindow(); 143 } 144 } 145 }); 146 } 147 148 public async releaseContext(): Promise<void> { 149 await this.extensionWin?.destroyWindow(); 150 await this.mContext?.terminateSelf(); 151 } 152};