一、问题背景:
应用在强提醒场景下,一般会有马达振动的效果,提示用户注意力的关注。
比如消息提醒,扫码提示,删除键确认提示等。
针对高定制化或者固定的振动方式,我们需要有不同的方案实现,马达振动效果。
二、解决方案:
鸿蒙针对振动效果的实现,有多种方案,目前分为振动和音振协同两种方式。
单纯的只是振动,又分为三种方式:
- 系统定制的振动方式,例如闹钟
- 非系统定制,自定义振动配置json文件的方式
- 线性马达振动,只需要设置时间和强度(最简单的调用方式)
音振协同一般用于,音效播放和振动同时的场景,例如扫码。
1.首先需要配置振动权限,该权限是系统权限,只需要配置后,默认就会被授权。
ohos.permission.VIBRATE
2.之后根据需要实现不同的马达振动效果,方案调用详情参见下方代码示例的注释。
三、DEMO示例:
import vibrator from '@ohos.vibrator';
import { BusinessError } from '@ohos.base';
import { resourceManager } from '@kit.LocalizationKit';
/**
* 振动管理类
* 需要权限: ohos.permission.VIBRATE
*/
export class HapticMgr {
private TAG: string = 'HapticMgr';
private static mHapticMgr: HapticMgr | undefined = undefined;
public static Ins(): HapticMgr{
if(!HapticMgr.mHapticMgr){
HapticMgr.mHapticMgr = new HapticMgr();
}
return HapticMgr.mHapticMgr;
}
/**
* 按照指定持续时间触发马达振动
*/
public timeVibration(){
try {
// 触发马达振动
vibrator.startVibration({
type: 'time',
duration: 1000,
}, {
id: 0,
usage: 'alarm'
}, (error: BusinessError) => {
if (error) {
console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`);
return;
}
console.info('Succeed in starting vibration');
});
} catch (err) {
let e: BusinessError = err as BusinessError;
console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
}
}
/**
* 按照预置振动效果触发马达振动,可先查询振动效果是否被支持,再调用振动接口
*/
public typeVibration(){
try {
// 查询是否支持'haptic.clock.timer'
vibrator.isSupportEffect('haptic.clock.timer', (err: BusinessError, state: boolean) => {
if (err) {
console.error(`Failed to query effect. Code: ${err.code}, message: ${err.message}`);
return;
}
console.info('Succeed in querying effect');
if (state) {
try {
// 触发马达振动
vibrator.startVibration({
type: 'preset',
effectId: 'haptic.clock.timer',
count: 1,
}, {
usage: 'unknown'
}, (error: BusinessError) => {
if (error) {
console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`);
} else {
console.info('Succeed in starting vibration');
}
});
} catch (error) {
let e: BusinessError = error as BusinessError;
console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
}
}
})
} catch (error) {
let e: BusinessError = error as BusinessError;
console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
}
}
public fileVibration(){
const fileName: string = 'vibration.json';
// 获取文件资源描述符
let rawFd: resourceManager.RawFileDescriptor = getContext().resourceManager.getRawFdSync(fileName);
// 触发马达振动
try {
vibrator.startVibration({
type: "file",
hapticFd: { fd: rawFd.fd, offset: rawFd.offset, length: rawFd.length }
}, {
id: 0,
usage: 'alarm'
}, (error: BusinessError) => {
if (error) {
console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`);
return;
}
console.info('Succeed in starting vibration');
});
} catch (err) {
let e: BusinessError = err as BusinessError;
console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
}
// 关闭文件资源描述符
getContext().resourceManager.closeRawFdSync(fileName);
}
/**
* 按照指定模式停止对应的马达振动,自定义振动不支持此类停止方式
*/
public stopVibrationByType(){
// 停止固定时长振动
try {
// 按照VIBRATOR_STOP_MODE_TIME模式停止振动
vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_TIME, (error: BusinessError) => {
if (error) {
console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`);
return;
}
console.info('Succeed in stopping vibration');
})
} catch (err) {
let e: BusinessError = err as BusinessError;
console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
}
// 停止预置振动:
try {
// 按照VIBRATOR_STOP_MODE_PRESET模式停止振动
vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_PRESET, (error: BusinessError) => {
if (error) {
console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`);
return;
}
console.info('Succeed in stopping vibration');
})
} catch (err) {
let e: BusinessError = err as BusinessError;
console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
}
}
/**
* 停止所有模式的马达振动,包括自定义振动:
*/
public stopVibration(){
try {
// 停止所有模式的马达振动
vibrator.stopVibration((error: BusinessError) => {
if (error) {
console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`);
return;
}
console.info('Succeed in stopping vibration');
})
} catch (error) {
let e: BusinessError = error as BusinessError;
console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
}
}
}
振动配置文件:
{
"MetaData": {
"Create": "2023-01-09",
"Description": "a haptic case",
"Version": 1.0,
"ChannelNumber": 1
},
"Channels": [
{
"Parameters": {
"Index": 0
},
"Pattern": [
{
"Event": {
"Type": "transient",
"StartTime": 0,
"Parameters": {
"Frequency": 31,
"Intensity": 100
}
}
},
{
"Event": {
"Type": "continuous",
"StartTime": 40,
"Duration": 54,
"Parameters": {
"Frequency": 30,
"Intensity": 38,
"Curve": [
{
"Time": 0,
"Frequency": 0,
"Intensity": 0
},
{
"Time": 1,
"Frequency": 15,
"Intensity": 0.5
},
{
"Time": 40,
"Frequency": -8,
"Intensity": 1.0
},
{
"Time": 54,
"Frequency": 0,
"Intensity": 0
}
]
}
}
}
]
}
]
}