1# Vibrator Development (ArkTS) 2 3 4## When to Use 5 6You can set different vibration effects as needed, for example, customizing the vibration intensity, frequency, and duration for button touches, alarm clocks, and incoming calls. 7 8For details about the APIs, see [Vibrator](../../reference/apis-sensor-service-kit/js-apis-vibrator.md). 9 10 11## Available APIs 12 13| Name | Description | 14| ------------------------------------------------------------ |-----------------------------------------------------------------------------| 15| startVibration(effect: VibrateEffect, attribute: VibrateAttribute): Promise<void> | Starts vibration with the specified effect and attribute. This API uses a promise to return the result. | 16| startVibration(effect: VibrateEffect, attribute: VibrateAttribute, callback: AsyncCallback<void>): void | Starts vibration with the specified effect and attribute. This API uses an asynchronous callback to return the result. | 17| stopVibration(stopMode: VibratorStopMode): Promise<void> | Stops vibration in the specified mode. This API uses a promise to return the result. | 18| stopVibration(stopMode: VibratorStopMode, callback: AsyncCallback<void>): void | Stops vibration in the specified mode. This API uses an asynchronous callback to return the result. | 19| stopVibration(): Promise<void> | Stops vibration in all modes. This API uses a promise to return the result. | 20| stopVibration(param?: VibratorInfoParam): Promise<void> | Stops vibration based on the specified vibrator parameters. This API uses a promise to return the result. | 21| stopVibration(callback: AsyncCallback<void>): void | Stops vibration in all modes. This API uses an asynchronous callback to return the result. | 22| isSupportEffect(effectId: string): Promise<boolean> | Checks whether an effect ID is supported. This API uses a promise to return the result. The return value **true** means that the effect ID is supported, and **false** means the opposite. | 23| isSupportEffect(effectId: string, callback: AsyncCallback<boolean>): void | Checks whether an effect ID is supported. This API uses an asynchronous callback to return the result. The return value **true** means that the effect ID is supported, and **false** means the opposite. | 24| getEffectInfoSync(effectId: string, param?: VibratorInfoParam): EffectInfo | Checks whether the effect specified by the input **effectId** is supported. The **param** parameter can be used to specify a specific vibrator. You can check the **isEffectSupported** field in the returned **EffectInfo** object to determine whether the effect is supported.| 25| getVibratorInfoSync(param?: VibratorInfoParam): Array<VibratorInfo> | Queries the vibrator list of one or all devices. The returned **VibratorInfo** object includes the following information: device ID, vibrator ID, device name, support for HD vibration, and local device flag. | 26| on(type: 'vibratorStateChange', callback: Callback<VibratorStatusEvent>): void | Enables listening for vibrator status changes. The **VibratorStatusEvent** parameter includes the following information: event timestamp, device ID, number of vibrators, and online/offline status. | 27| off(type: 'vibratorStateChange', callback?: Callback<VibratorStatusEvent>): void | Disables listening for vibrator status changes. | 28 29 30## Vibration Effect Description 31 32Currently, three types of vibration effects are supported. 33 34| Name | Description | 35| ------------ | ------------------------------------------------------------ | 36| Fixed-Duration Vibration| Only a fixed duration is passed in, and the device vibrates based on the default intensity and frequency. For details about the vibration effect, see [VibrateTime](../../reference/apis-sensor-service-kit/js-apis-vibrator.md#vibratetime9).| 37| Preset Vibration | Certain [vibration effects are preset](../../reference/apis-sensor-service-kit/js-apis-vibrator.md#effectid) for fixed scenes. For example, the effect "haptic.clock.timer" is preset to provide feedback when a user adjusts the timer. For details about the vibration effect, see [VibratePreset](../../reference/apis-sensor-service-kit/js-apis-vibrator.md#vibratepreset9).| 38| Custom Vibration | Custom vibration enables you to design vibration effects by customizing a vibration configuration file and orchestrating vibration forms based on the corresponding rules. For details about the vibration effect, see [VibrateFromFile](../../reference/apis-sensor-service-kit/js-apis-vibrator.md#vibratefromfile10).| 39 40The custom vibration configuration file is in JSON format. An example file is as follows: 41 42```json 43{ 44 "MetaData": { 45 "Create": "2023-01-09", 46 "Description": "a haptic case", 47 "Version": 1.0, 48 "ChannelNumber": 1 49 }, 50 "Channels": [ 51 { 52 "Parameters": { 53 "Index": 0 54 }, 55 "Pattern": [ 56 { 57 "Event": { 58 "Type": "transient", 59 "StartTime": 0, 60 "Parameters": { 61 "Frequency": 31, 62 "Intensity": 100 63 } 64 } 65 }, 66 { 67 "Event": { 68 "Type": "continuous", 69 "StartTime": 40, 70 "Duration": 54, 71 "Parameters": { 72 "Frequency": 30, 73 "Intensity": 38, 74 "Curve": [ 75 { 76 "Time": 0, 77 "Frequency": 0, 78 "Intensity": 0 79 }, 80 { 81 "Time": 1, 82 "Frequency": 15, 83 "Intensity": 0.5 84 }, 85 { 86 "Time": 40, 87 "Frequency": -8, 88 "Intensity": 1.0 89 }, 90 { 91 "Time": 54, 92 "Frequency": 0, 93 "Intensity": 0 94 } 95 ] 96 } 97 } 98 } 99 ] 100 } 101 ] 102} 103``` 104 105This JSON file contains three attributes: **MetaData**, **Channels**, and **Parameters**. 1061. **MetaData** contains information about the file header. You can add the following attributes under **MetaData**. 107 108 | Name | Mandatory| Description | 109 | ------------- | ------ | --------------------------------------------- | 110 | Version | Yes | Version number of the file format, which is forward compatible. Currently, only version 1.0 is supported.| 111 | ChannelNumber | Yes | Number of channels for vibration. A maximum of two channels are supported. | 112 | Create | No | Time when the file was created. | 113 | Description | No | Additional information such as the vibration effect and creation information. | 114 1152. **Channels** provides information about the vibration channel. 116 117 It is a JSON array that holds information about each channel. It contains two attributes: **Parameters** and **Pattern**. 118 119 | Name | Mandatory| Description | 120 | ---------- | ------ | ------------------------------------------------------------ | 121 | Parameters | Yes | Channel parameters. Among them, **Index** indicates the channel ID. The value **0** indicates both channels, **1** indicates the left channel, and **2** indicates the right channel.| 122 | Pattern | No | Vibration sequence. | 123 124 **Pattern** is a JSON array that holds the vibration events. Under it, **Event** indicates a vibration event, which can be either of the following types: 125 126 | Vibration Type | Description | 127 | ---------- | ---------------------------------------------- | 128 | transient | Short vibration. | 129 | continuous | Long vibration.| 130 131 A vibration event contains the following attributes: 132 133 | Name | Mandatory| Description | 134 | --------- | ------ | ------------------------------------------------------------ | 135 | Type | Yes | Type of the vibration event, which can be **transient** or **continuous**. | 136 | StartTime | Yes | Vibration start time. The value range is [0, 1800000], in ms. | 137 | Duration | Yes | Vibration duration. This parameter is valid only when **Type** is set to **continuous**. The value range is [0, 5000], in ms.| 138 1393. **Parameters** provides the following parameters related to the vibration event and is mandatory. 140 141 | Name | Mandatory| Description | 142 | --------- | ------ | ------------------------------------------------------------ | 143 | Intensity | Yes | Vibration intensity. The value range is [0, 100]. | 144 | Frequency | Yes | Vibration frequency. The value range is [0, 100]. | 145 | Curve | No | Vibration curve. This parameter is valid only when **Type** is set to **continuous**. It is a JSON array that holds 4 to 16 adjustment points. Each adjustment point must contain the following attributes:<br>**Time**: offset relative to the event start time. The value ranges from 0 to the vibration duration.<br>**Intensity**: gain relative to the vibration intensity. The value range is [0, 1]. This value multiplied by the vibration intensity is the adjusted intensity at the corresponding time point.<br>**Frequency**: change relative to the vibration frequency. The value range is [-100, 100]. This value plus the vibration frequency is the adjusted frequency at the corresponding time point.| 146 147The following requirements must be met: 148 149| Item| Description | 150| -------- | ------------------------ | 151| Number of vibration events| No more than 128| 152| Length of the vibration configuration file| Not greater than 64 KB| 153 154 155## How to Develop 156 1571. Before using the vibrator on a device, you must declare the **ohos.permission.VIBRATE** permission. For details, see [Declaring Permissions](../../security/AccessToken/declare-permissions.md). 158 1592. Query vibrator information. 160 161 Scenario 1: Query information about all vibrators. 162 163 ```ts 164 import { vibrator } from '@kit.SensorServiceKit'; 165 import { BusinessError } from '@kit.BasicServicesKit'; 166 167 try { 168 const vibratorInfoList: vibrator.VibratorInfo[] = vibrator.getVibratorInfoSync(); 169 console.log(`vibratorInfoList: ${JSON.stringify(vibratorInfoList)}`); 170 } catch (error) { 171 let e: BusinessError = error as BusinessError; 172 console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`); 173 } 174 ``` 175 176 Scenario 2: Query information about one or more vibrators of the specified device. 177 178 ```ts 179 import { vibrator } from '@kit.SensorServiceKit'; 180 import { BusinessError } from '@kit.BasicServicesKit'; 181 182 try { 183 const vibratorParam: vibrator.VibratorInfoParam = { 184 deviceId: 1 // The device ID must be the one that actually exists. 185 } 186 const vibratorInfoList: vibrator.VibratorInfo[] = vibrator.getVibratorInfoSync(vibratorParam); 187 console.log(`vibratorInfoList: ${JSON.stringify(vibratorInfoList)}`); 188 } catch (error) { 189 let e: BusinessError = error as BusinessError; 190 console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`); 191 } 192 ``` 193 1943. Start vibration with the specified effect and attribute. 195 196 Scenario 1: Trigger vibration with the specified duration. 197 198 ```ts 199 import { vibrator } from '@kit.SensorServiceKit'; 200 import { BusinessError } from '@kit.BasicServicesKit'; 201 202 try { 203 // Start vibration. 204 vibrator.startVibration({ 205 type: 'time', 206 duration: 1000, 207 }, { 208 id: 0, 209 usage: 'alarm' 210 }, (error: BusinessError) => { 211 if (error) { 212 console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`); 213 return; 214 } 215 console.info('Succeed in starting vibration'); 216 }); 217 } catch (err) { 218 let e: BusinessError = err as BusinessError; 219 console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`); 220 } 221 ``` 222 223 Scenario 2: Trigger vibration with a preset effect. You can check whether the preset effect is supported before calling **startVibration()**. 224 225 ```ts 226 import { vibrator } from '@kit.SensorServiceKit'; 227 import { BusinessError } from '@kit.BasicServicesKit'; 228 229 try { 230 // Check whether 'haptic.effect.soft' is supported. 231 vibrator.isSupportEffect('haptic.effect.soft', (err: BusinessError, state: boolean) => { 232 if (err) { 233 console.error(`Failed to query effect. Code: ${err.code}, message: ${err.message}`); 234 return; 235 } 236 console.info('Succeed in querying effect'); 237 if (state) { 238 try { 239 // Start vibration. 240 vibrator.startVibration({ 241 type: 'preset', 242 effectId: 'haptic.effect.soft', 243 count: 1, 244 intensity: 50, 245 }, { 246 usage: 'unknown' 247 }, (error: BusinessError) => { 248 if (error) { 249 console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`); 250 } else { 251 console.info('Succeed in starting vibration'); 252 } 253 }); 254 } catch (error) { 255 let e: BusinessError = error as BusinessError; 256 console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`); 257 } 258 } 259 }) 260 } catch (error) { 261 let e: BusinessError = error as BusinessError; 262 console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`); 263 } 264 ``` 265 266 Scenario 3: Trigger vibration according to a custom vibration configuration file. 267 268 ```ts 269 import { vibrator } from '@kit.SensorServiceKit'; 270 import { resourceManager } from '@kit.LocalizationKit'; 271 import { BusinessError } from '@kit.BasicServicesKit'; 272 273 const fileName: string = 'xxx.json'; 274 275 @Entry 276 @Component 277 struct Index { 278 uiContext = this.getUIContext(); 279 280 build() { 281 Row() { 282 Column() { 283 Button('alarm-file') 284 .onClick(() => { 285 // Obtain the file descriptor of the vibration configuration file. 286 let rawFd: resourceManager.RawFileDescriptor | undefined = this.uiContext.getHostContext()?.resourceManager.getRawFdSync(fileName); 287 if (rawFd != undefined) { 288 // Start vibration. 289 try { 290 vibrator.startVibration({ 291 type: "file", 292 hapticFd: { fd: rawFd.fd, offset: rawFd.offset, length: rawFd.length } 293 }, { 294 id: 0, 295 usage: 'alarm' // The switch control is subject to the selected type. 296 }, (error: BusinessError) => { 297 if (error) { 298 console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`); 299 return; 300 } 301 console.info('Succeed in starting vibration'); 302 }); 303 } catch (err) { 304 let e: BusinessError = err as BusinessError; 305 console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`); 306 } 307 } 308 // Close the file descriptor of the vibration configuration file. 309 this.uiContext.getHostContext()?.resourceManager.closeRawFdSync(fileName); 310 }) 311 } 312 .width('100%') 313 } 314 .height('100%') 315 } 316 } 317 ``` 318 3194. Stop vibration. 320 321 Method 1: Stop vibration in the specified mode. This method is invalid for custom vibration. 322 323 Stop fixed-duration vibration. 324 325 ```ts 326 import { vibrator } from '@kit.SensorServiceKit'; 327 import { BusinessError } from '@kit.BasicServicesKit'; 328 329 try { 330 // Stop vibration in VIBRATOR_STOP_MODE_TIME mode. 331 vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_TIME, (error: BusinessError) => { 332 if (error) { 333 console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`); 334 return; 335 } 336 console.info('Succeed in stopping vibration'); 337 }) 338 } catch (err) { 339 let e: BusinessError = err as BusinessError; 340 console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`); 341 } 342 ``` 343 344 Stop preset vibration. 345 346 ```ts 347 import { vibrator } from '@kit.SensorServiceKit'; 348 import { BusinessError } from '@kit.BasicServicesKit'; 349 350 try { 351 // Stop vibration in VIBRATOR_STOP_MODE_PRESET mode. 352 vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_PRESET, (error: BusinessError) => { 353 if (error) { 354 console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`); 355 return; 356 } 357 console.info('Succeed in stopping vibration'); 358 }) 359 } catch (err) { 360 let e: BusinessError = err as BusinessError; 361 console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`); 362 } 363 ``` 364 365 Method 2: Stop vibration in all modes, including custom vibration. 366 367 ```ts 368 import { vibrator } from '@kit.SensorServiceKit'; 369 import { BusinessError } from '@kit.BasicServicesKit'; 370 371 try { 372 // Stop vibration in all modes. 373 vibrator.stopVibration((error: BusinessError) => { 374 if (error) { 375 console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`); 376 return; 377 } 378 console.info('Succeed in stopping vibration'); 379 }) 380 } catch (error) { 381 let e: BusinessError = error as BusinessError; 382 console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`); 383 } 384 ``` 385 386 Method 3: Stop vibration of the specified device. 387 388 ```ts 389 import { vibrator } from '@kit.SensorServiceKit'; 390 import { BusinessError } from '@kit.BasicServicesKit'; 391 392 const vibratorInfoParam: vibrator.VibratorInfoParam = { 393 deviceId: 1 // The device ID must be the one that actually exists. 394 } 395 try { 396 vibrator.stopVibration(vibratorInfoParam).then(() => { 397 console.info('Succeed in stopping vibration'); 398 }, (error: BusinessError) => { 399 console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`); 400 }); 401 } catch (error) { 402 let e: BusinessError = error as BusinessError; 403 console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`); 404 } 405 ``` 406 407 4085. Enable listening for vibrator status changes. 409 410 Enable listening. 411 ```ts 412 import { vibrator } from '@kit.SensorServiceKit'; 413 import { BusinessError } from '@kit.BasicServicesKit'; 414 415 // Callback 416 const vibratorStateChangeCallback = (data: vibrator.VibratorStatusEvent) => { 417 console.log('vibrator state callback info:', JSON.stringify(data)); 418 } 419 420 try { 421 // Subscribe to vibratorStateChange events. 422 vibrator.on('vibratorStateChange', vibratorStateChangeCallback); 423 } catch (error) { 424 let e: BusinessError = error as BusinessError; 425 console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`); 426 } 427 ``` 428 429 Disable listening. The specified callback must be the same as that passed to the **on** API. 430 ```ts 431 import { vibrator } from '@kit.SensorServiceKit'; 432 import { BusinessError } from '@kit.BasicServicesKit'; 433 434 // Callback 435 const vibratorStateChangeCallback = (data: vibrator.VibratorStatusEvent) => { 436 console.log('vibrator state callback info:', JSON.stringify(data)); 437 } 438 try { 439 // Unsubscribe from specified vibratorStateChange events. 440 vibrator.off('vibratorStateChange', vibratorStateChangeCallback); 441 // Unsubscribe from all vibratorStateChange events. 442 // vibrator.off('vibratorStateChange'); 443 } catch (error) { 444 let e: BusinessError = error as BusinessError; 445 console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`); 446 } 447 ``` 448