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(callback: AsyncCallback<void>): void     | Stops vibration in all modes. This API uses an asynchronous callback to return the result.              |
21| isSupportEffect(effectId: string): Promise<boolean>    | Checks whether an effect ID is supported. This API uses a promise to return the result. 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.|
22| isSupportEffect(effectId: string, callback: AsyncCallback<boolean>): void | Checks whether an effect ID is supported. This API uses an asynchronous callback to return the result. 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.|
23
24
25## Vibration Effect Description
26
27Currently, three types of vibration effects are supported.
28
29| Name        | Description                                                        |
30| ------------ | ------------------------------------------------------------ |
31| 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).|
32| 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).|
33| 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).|
34
35The custom vibration configuration file is in JSON format. An example file is as follows:
36
37```json
38{
39    "MetaData": {
40        "Create": "2023-01-09",
41        "Description": "a haptic case",
42        "Version": 1.0,
43        "ChannelNumber": 1
44    },
45    "Channels": [
46        {
47            "Parameters": {
48                "Index": 0
49            },
50            "Pattern": [
51                {
52                    "Event": {
53                        "Type": "transient",
54                        "StartTime": 0,
55                        "Parameters": {
56                            "Frequency": 31,
57                            "Intensity": 100
58                        }
59                    }
60                },
61                {
62                    "Event": {
63                        "Type": "continuous",
64                        "StartTime": 40,
65                        "Duration": 54,
66                        "Parameters": {
67                            "Frequency": 30,
68                            "Intensity": 38,
69                            "Curve": [
70                                {
71                                    "Time": 0,
72                                    "Frequency": 0,
73                                    "Intensity": 0
74                                },
75                                {
76                                    "Time": 1,
77                                    "Frequency": 15,
78                                    "Intensity": 0.5
79                                },
80                                {
81                                    "Time": 40,
82                                    "Frequency": -8,
83                                    "Intensity": 1.0
84                                },
85                                {
86                                    "Time": 54,
87                                    "Frequency": 0,
88                                    "Intensity": 0
89                                }
90                            ]
91                        }
92                    }
93                }
94            ]
95        }
96    ]
97}
98```
99
100This JSON file contains two attributes: **MetaData** and **Channels**.
1011. **MetaData** contains information about the file header. You can add the following attributes under **MetaData**.
102
103     | Name         | Mandatory| Description                                         |
104     | ------------- | ------ | --------------------------------------------- |
105     | Version       | Yes    | Version number of the file format, which is forward compatible. Currently, only version 1.0 is supported.|
106     | ChannelNumber | Yes    | Number of channels for vibration. A maximum of two channels are supported.   |
107     | Create        | No    | Time when the file was created.                         |
108     | Description   | No    | Additional information such as the vibration effect and creation information.         |
109
1102. **Channels** provides information about the vibration channel.
111
112     It is a JSON array that holds information about each channel. It contains two attributes: **Parameters** and **Pattern**.
113
114     | Name      | Mandatory| Description                                                        |
115     | ---------- | ------ | ------------------------------------------------------------ |
116     | 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.|
117     | Pattern    | No    | Vibration sequence.                                              |
118
119     **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:
120
121     | Vibration Type  | Description                                          |
122     | ---------- | ---------------------------------------------- |
123     | transient  | Short vibration.                        |
124     | continuous | Long vibration.|
125
126     A vibration event contains the following attributes:
127
128     | Name     | Mandatory| Description                                                        |
129     | --------- | ------ | ------------------------------------------------------------ |
130     | Type      | Yes    | Type of the vibration event, which can be **transient** or **continuous**.                |
131     | StartTime | Yes    | Vibration start time. The value range is [0, 1800000], in ms.           |
132     | Duration  | Yes    | Vibration duration. This parameter is valid only when **Type** is set to **continuous**. The value range is [0, 5000], in ms.|
133
1343. **Parameters** provides the following parameters related to the vibration event and is mandatory.
135
136     | Name     | Mandatory| Description                                                        |
137     | --------- | ------ | ------------------------------------------------------------ |
138     | Intensity | Yes    | Vibration intensity. The value range is [0, 100].                          |
139     | Frequency | Yes    | Vibration frequency. The value range is [0, 100].                          |
140     | 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.|
141
142The following requirements must be met:
143
144| Item| Description                |
145| -------- | ------------------------ |
146| Number of vibration events| No more than 128|
147| Length of the vibration configuration file| Not greater than 64 KB|
148
149
150## How to Develop
151
1521. 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).
153
1542. Start vibration with the specified effect and attribute.
155
156   Scenario 1: Trigger vibration with the specified duration.
157
158   ```ts
159   import { vibrator } from '@kit.SensorServiceKit';
160   import { BusinessError } from '@kit.BasicServicesKit';
161
162   try {
163     // Start vibration.
164     vibrator.startVibration({
165       type: 'time',
166       duration: 1000,
167     }, {
168       id: 0,
169       usage: 'alarm'
170     }, (error: BusinessError) => {
171       if (error) {
172         console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`);
173         return;
174       }
175       console.info('Succeed in starting vibration');
176     });
177   } catch (err) {
178     let e: BusinessError = err as BusinessError;
179     console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
180   }
181   ```
182
183   Scenario 2: Trigger vibration with a preset effect. You can check whether the preset effect is supported before calling **startVibration()**.
184
185   ```ts
186   import { vibrator } from '@kit.SensorServiceKit';
187   import { BusinessError } from '@kit.BasicServicesKit';
188
189   try {
190     // Check whether 'haptic.effect.soft' is supported.
191     vibrator.isSupportEffect('haptic.effect.soft', (err: BusinessError, state: boolean) => {
192       if (err) {
193         console.error(`Failed to query effect. Code: ${err.code}, message: ${err.message}`);
194         return;
195       }
196       console.info('Succeed in querying effect');
197       if (state) {
198         try {
199           // Start vibration.
200           vibrator.startVibration({
201             type: 'preset',
202             effectId: 'haptic.effect.soft',
203             count: 1,
204             intensity: 50,
205           }, {
206             usage: 'unknown'
207           }, (error: BusinessError) => {
208             if (error) {
209               console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`);
210             } else {
211               console.info('Succeed in starting vibration');
212             }
213           });
214         } catch (error) {
215           let e: BusinessError = error as BusinessError;
216           console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
217         }
218       }
219     })
220   } catch (error) {
221     let e: BusinessError = error as BusinessError;
222     console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
223   }
224   ```
225
226   Scenario 3: Trigger vibration according to a custom vibration configuration file.
227
228   ```ts
229   import { vibrator } from '@kit.SensorServiceKit';
230   import { resourceManager } from '@kit.LocalizationKit';
231   import { BusinessError } from '@kit.BasicServicesKit';
232
233   const fileName: string = 'xxx.json';
234
235   // Obtain the file descriptor of the vibration configuration file.
236   let rawFd: resourceManager.RawFileDescriptor = getContext().resourceManager.getRawFdSync(fileName);
237
238   // Start vibration.
239   try {
240     vibrator.startVibration({
241       type: "file",
242       hapticFd: { fd: rawFd.fd, offset: rawFd.offset, length: rawFd.length }
243     }, {
244       id: 0,
245       usage: 'alarm'
246     }, (error: BusinessError) => {
247       if (error) {
248         console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`);
249         return;
250       }
251       console.info('Succeed in starting vibration');
252     });
253   } catch (err) {
254     let e: BusinessError = err as BusinessError;
255     console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
256   }
257
258   // Close the file descriptor of the vibration configuration file.
259   getContext().resourceManager.closeRawFdSync(fileName);
260   ```
261
2623. Stop vibration.
263
264   Method 1: Stop vibration in the specified mode. This method is invalid for custom vibration.
265
266   ​	Stop fixed-duration vibration.
267
268   ```ts
269   import { vibrator } from '@kit.SensorServiceKit';
270   import { BusinessError } from '@kit.BasicServicesKit';
271
272   try {
273     // Stop vibration in VIBRATOR_STOP_MODE_TIME mode.
274     vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_TIME, (error: BusinessError) => {
275       if (error) {
276         console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`);
277         return;
278       }
279       console.info('Succeed in stopping vibration');
280     })
281   } catch (err) {
282     let e: BusinessError = err as BusinessError;
283     console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
284   }
285   ```
286
287   ​	Stop preset vibration.
288
289   ```ts
290   import { vibrator } from '@kit.SensorServiceKit';
291   import { BusinessError } from '@kit.BasicServicesKit';
292
293   try {
294     // Stop vibration in VIBRATOR_STOP_MODE_PRESET mode.
295     vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_PRESET, (error: BusinessError) => {
296       if (error) {
297         console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`);
298         return;
299       }
300       console.info('Succeed in stopping vibration');
301     })
302   } catch (err) {
303     let e: BusinessError = err as BusinessError;
304     console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
305   }
306   ```
307
308   Method 2: Stop vibration in all modes, including custom vibration.
309
310   ```ts
311   import { vibrator } from '@kit.SensorServiceKit';
312   import { BusinessError } from '@kit.BasicServicesKit';
313
314   try {
315     // Stop vibration in all modes.
316     vibrator.stopVibration((error: BusinessError) => {
317       if (error) {
318         console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`);
319         return;
320       }
321       console.info('Succeed in stopping vibration');
322     })
323   } catch (error) {
324     let e: BusinessError = error as BusinessError;
325     console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
326   }
327   ```
328
329
330## Samples
331
332The following sample is provided to help you better understand how to develop vibrators:
333
334- [Vibrator (ArkTS, API version 9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/DeviceManagement/Vibrator/BasicVibration)
335
336- [CustomHaptic (ArkTS, Full SDK, API version 10)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/DeviceManagement/Vibrator/CustomHaptic)
337