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