1# AccessibilityExtensionAbility 2 3Accessibility Kit provides accessibility extension capabilities based on AccessibilityExtensionAbility in the ExtensionAbility framework. You can develop your accessibility extension services by applying the AccessibilityExtensionAbility template. 4 5## Creating an Accessibility Extension Service 6 7You can create an accessibility extension service by creating a project from scratch or adding the service to an existing project. Only one accessibility extension service can be created for a project. 8This example creates an accessibility extension service that implements the following functions: 9When the accessibility function is enabled, a right-then-down gesture obtains all nodes on the current screen, and a following left-then-down gesture obtains all nodes. 10 11### Creating a Project 12 13To create an independent accessibility extension service, create a project in the stage model of API version 9 or later in DevEco Studio. 14 15### Creating an AccessibilityExtAbility.ets File 16 17In the **ets** folder of a project, add the **AccessibilityExtAbility** folder and then create the **AccessibilityExtAbility.ets** file in the folder. You can implement some callbacks in the file to add service processing logic. 18 19```ts 20import { AccessibilityExtensionAbility, AccessibilityEvent } from '@kit.AccessibilityKit'; 21import AccessibilityManager from './AccessibilityManager'; 22 23class AccessibilityExtAbility extends AccessibilityExtensionAbility { 24 onConnect() { 25 console.info(`AccessibilityExtAbility onConnect`); 26 // Initialize the service logic. 27 AccessibilityManager.getInstance().onStart(this.context); 28 } 29 30 onDisconnect() { 31 console.info(`AccessibilityExtAbility onDisconnect`); 32 // Reclaim resources and exit the service logic. 33 AccessibilityManager.getInstance().onStop(); 34 } 35 36 onAccessibilityEvent(accessibilityEvent: AccessibilityEvent) { 37 console.info(`AccessibilityExtAbility onAccessibilityEvent: ${JSON.stringify(accessibilityEvent)}`); 38 // Process the service logic based on the event information. 39 AccessibilityManager.getInstance().onEvent(accessibilityEvent); 40 } 41} 42 43export default AccessibilityExtAbility; 44``` 45 46The APIs defined in the file are as follows. 47 48| Name| Description| 49| ---- | ---- | 50| onConnect(): void | Called when a connection with the extension service is set up.| 51| onDisconnect(): void | Called when the connection with the extension service is severed.| 52| onAccessibilityEvent(event: AccessibilityEvent): void | Called when an accessibility event occurs| 53 54Create the **AccessibilityManager.ets** file for storing the service logic code. 55```ts 56import { 57 AccessibilityElement, 58 AccessibilityEvent, 59 AccessibilityExtensionContext, 60 ElementAttributeKeys 61} from '@kit.AccessibilityKit'; 62 63interface Rect { 64 left: number, 65 top: number, 66 width: number, 67 height: number, 68} 69 70// Attribute information to be queried 71let wantedAttribute: ElementAttributeKeys[] = ['bundleName', 'text', 'description', 'windowId']; 72type attributeValues = string | number | boolean | AccessibilityElement | AccessibilityElement[] | string[] | Rect; 73 74export default class AccessibilityManager { 75 private static instance: AccessibilityManager; 76 accessibleContext?: AccessibilityExtensionContext; 77 currentPageElementArray: Array<AccessibilityElement> | null = null; 78 79 static getInstance(): AccessibilityManager { 80 if (!AccessibilityManager.instance) { 81 AccessibilityManager.instance = new AccessibilityManager(); 82 } 83 return AccessibilityManager.instance; 84 } 85 86 onStart(context: AccessibilityExtensionContext) { 87 console.info(`AccessibilityManager onStart`); 88 this.accessibleContext = context; 89 } 90 91 onStop() { 92 console.info(`AccessibilityManager onStop`); 93 this.accessibleContext = undefined; 94 } 95 96 onEvent(accessibilityEvent: AccessibilityEvent): void { 97 console.info(`AccessibilityManager onEvent`); 98 switch (accessibilityEvent.eventType) { 99 case 'rightThenDown': 100 // Obtain all nodes on the current screen. 101 this.getCurrentPageAllElement(); 102 break; 103 case 'leftThenDown': 104 // Obtain all nodes. 105 this.printAllElementInfo(); 106 break; 107 default: 108 break; 109 } 110 } 111 112 async getCurrentPageAllElement(): Promise<void> { 113 console.info(`AccessibilityManager getCurrentPageAllElement`); 114 let rootElement: AccessibilityElement; 115 if(!this.accessibleContext){ 116 console.error(`AccessibilityManager accessibleContext undefined`); 117 return; 118 } 119 try { 120 rootElement = await this.accessibleContext?.getWindowRootElement(); 121 this.currentPageElementArray = await this.getAttributeValue(rootElement, 'children') as AccessibilityElement[]; 122 } catch (error) { 123 console.error(`AccessibilityExtAbility Failed to getWindowRootElement. Cause:${JSON.stringify(error)}`); 124 } 125 } 126 127 async getElementWantedInfo(accessibilityElement: AccessibilityElement, wantedAttribute: ElementAttributeKeys[]): 128 Promise<string | null> { 129 console.info(`AccessibilityUtils getElementAllInfo`); 130 if (accessibilityElement === null) { 131 console.error(`AccessibilityUtils accessibilityElement is null`); 132 return null; 133 } 134 135 let info = ''; 136 let value: attributeValues | null; 137 for (let name of wantedAttribute) { 138 value = await this.getAttributeValue(accessibilityElement, name); 139 info = info.concat(name + ': ' + value + ' '); 140 } 141 return info; 142 } 143 144 async getAttributeValue(accessibilityElement: AccessibilityElement, key: ElementAttributeKeys): 145 Promise<attributeValues | null> { 146 console.info(`AccessibilityUtils getAttributeValue`); 147 let value: attributeValues; 148 let keys = await accessibilityElement.attributeNames(); 149 let isExit = false; 150 for (let keyString of keys) { 151 if (key == keyString) { 152 isExit = true; 153 } 154 } 155 if (isExit) { 156 try { 157 value = await accessibilityElement.attributeValue(key); 158 return value; 159 } catch (error) { 160 console.error(`AccessibilityUtils Failed to get attributeValue of ${key} . Cause: ${JSON.stringify(error)}`); 161 } 162 } 163 return null; 164 } 165 166 async printAllElementInfo(): Promise<void> { 167 console.info(`AccessibilityManager printAllElementInfo`); 168 if (this.currentPageElementArray === null || this.currentPageElementArray.length === 0) { 169 console.error(`AccessibilityManager currentPageElementArray is null`); 170 return; 171 } 172 let info: string | null = null; 173 for (let index = 0; index < this.currentPageElementArray.length; index++) { 174 info = await this.getElementWantedInfo(this.currentPageElementArray[index], wantedAttribute); 175 console.info(`AccessibilityManager element information: ${info}`); 176 } 177 } 178} 179``` 180 181## Processing an Accessibility Event 182 183You can process the service logic for accessibility events through the **onAccessibilityEvent()** API. For details about the events, see [AccessibilityEvent](../reference/apis-accessibility-kit/js-apis-application-accessibilityExtensionAbility.md#accessibilityevent). In this example, the **rightThenDown** gesture is used. 184 185```ts 186onAccessibilityEvent(accessibilityEvent: AccessibilityEvent) { 187 console.info('AccessibilityExtAbility onAccessibilityEvent: ' + JSON.stringify(accessibilityEvent)); 188 if (accessibilityEvent.eventType === 'rightThenDown') { 189 console.info('AccessibilityExtAbility onAccessibilityEvent: rightThenDown'); 190 // TODO: Develop custom logic. 191 } 192} 193``` 194For an accessibility event, you can use the APIs of the [AccessibilityExtensionContext](../reference/apis-accessibility-kit/js-apis-inner-application-accessibilityExtensionContext.md) module to configure the concerned information, obtain root information, and inject gestures. 195 196You can also process physical key events in the accessibility extension service. For details, see [onKeyEvent](../reference/apis-accessibility-kit/js-apis-application-accessibilityExtensionAbility.md#accessibilityextensionabilityonkeyevent). 197 198## Declaring the Capabilities of Accessibility Extension Service 199 200After developing the custom logic for an accessibility extension service, you must add the configuration information of the service to the corresponding module-level **module.json5** file in the project directory. 201 202The **srcEntry** tag indicates the path to the **extensionAbility**. 203The **label** tag indicates the name of the **extensionAbility** displayed in the list of installed extension services. 204The **description** tag indicates the help information about the **extensionAbility** displayed on the details page of the installed extension service. 205Make sure the value of the **type** tag is fixed at **accessibility**. Otherwise, the connection to the service will fail. 206 207```json 208"extensionAbilities": [ 209 { 210 "name": "AccessibilityExtAbility", 211 "srcEntry": "./ets/AccessibilityExtAbility/AccessibilityExtAbility.ets", 212 "label": "$string:MainAbility_label", 213 "description": "$string:MainAbility_desc", 214 "type": "accessibility", 215 "metadata": [ 216 { 217 "name": "ohos.accessibleability", 218 "resource": "$profile:accessibility_config" 219 } 220 ] 221 } 222] 223``` 224In addition, **accessibility_config** is the specific configuration of the accessibility extension service. You need to create the **accessibility_config.json** file in **resources/base/profile/** and declare the [capability type](../reference/apis-accessibility-kit/js-apis-accessibility.md#capability) of the accessibility extension service in the file. In this example, the following declaration is required: 225```json 226{ 227 "accessibilityCapabilities": [ 228 "retrieve", 229 "gesture", 230 "touchGuide" 231 ] 232} 233``` 234## Enabling a Custom Accessibility Extension Service 235 236You can enable or disable a custom accessibility extension service through the device settings. 237 2381. From the device settings screen, access the list of installed extended services under accessibility. If an extended service is not installed, it is grayed out, and "No service" is displayed. 239 2402. Locate the target extension service, and toggle on or off the switch to enable or disable it. 241 2423. If you opt to enable a service, a security reminder is displayed. Wait until the countdown ends and then select the check box indicating that you are aware of and willing to assume the listed risks. After that, you can toggle off the switch to the extended service. 243