欢迎光临
我们一直在努力

及时做APP开发实战(九)-系统级震动反馈实现

及时做APP开发实战(九)-系统级震动反馈实现

本文将详细介绍如何在HarmonyOS NEXT中实现番茄钟的系统级震动反馈,提升用户体验。

一、需求背景

1.1 功能需求

番茄钟应用需要在关键时刻提供震动反馈,提醒用户状态变化:

┌─────────────────────────────────────┐
│ 震动反馈场景 │
├─────────────────────────────────────┤
│ 番茄钟完成 → 长震动 + 模式震动 │
│ 休息开始 → 短震动提示 │
│ 休息结束 → 双击震动提醒 │
└─────────────────────────────────────┘

1.2 技术选型

HarmonyOS提供 @ohos.vibrator 模块实现震动功能:

接口说明
startVibration 触发震动
stopVibration 停止震动
VibratorStopMode 停止模式枚举

二、权限配置

2.1 添加震动权限

在 module.json5 中添加权限声明:

{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.VIBRATE",
"reason": "$string:vibrate_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
}
]
}
}

2.2 添加权限说明

在 string.json 中添加权限说明:

{
"string": [
{
"name": "vibrate_reason",
"value": "用于番茄钟计时结束时提供震动反馈提醒"
}
]
}

三、FeedbackUtil工具类实现

3.1 类结构设计

┌─────────────────────────────────────┐
│ FeedbackUtil │
├─────────────────────────────────────┤
│ – instance: FeedbackUtil │
├─────────────────────────────────────┤
│ + getInstance(): FeedbackUtil │
│ + vibrate(duration): void │
│ + vibratePattern(pattern): void │
│ + stopVibrate(): void │
│ + pomodoroComplete(): void │
│ + breakStart(): void │
│ + breakEnd(): void │
└─────────────────────────────────────┘

3.2 完整实现代码

import vibrator from '@ohos.vibrator';
import { BusinessError } from '@ohos.base';

export class FeedbackUtil {
private static instance: FeedbackUtil | null = null;

// 私有构造函数
private constructor() {}

// 获取单例
public static getInstance(): FeedbackUtil {
if (!FeedbackUtil.instance) {
FeedbackUtil.instance = new FeedbackUtil();
}
return FeedbackUtil.instance;
}

/**
* 触发震动反馈
* @param duration 震动持续时间(毫秒),默认200ms
*/

public vibrate(duration: number = 200): void {
try {
vibrator.startVibration({
type: 'time',
duration: duration
}, {
id: 0,
usage: 'alarm'
}, (error: BusinessError) => {
if (error) {
console.error(`[FeedbackUtil] 震动失败: ${error.message}`);
} else {
console.info('[FeedbackUtil] 震动反馈成功');
}
});
} catch (err) {
const e: BusinessError = err as BusinessError;
console.error(`[FeedbackUtil] 震动异常: ${e.message}`);
}
}

/**
* 触发模式震动
* @param pattern 震动模式 [静止, 震动, 静止, 震动, …]
*/

public vibratePattern(pattern: number[]): void {
try {
vibrator.startVibration({
type: 'preset',
effectId: 'haptic.clock.timer',
count: 1
}, {
id: 0,
usage: 'alarm'
}, (error: BusinessError) => {
if (error) {
console.error(`[FeedbackUtil] 模式震动失败: ${error.message}`);
}
});
} catch (err) {
const e: BusinessError = err as BusinessError;
console.error(`[FeedbackUtil] 模式震动异常: ${e.message}`);
}
}

/**
* 停止震动
*/

public stopVibrate(): void {
try {
vibrator.stopVibration(
vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_TIME,
(error: BusinessError) => {
if (error) {
console.error(`[FeedbackUtil] 停止震动失败: ${error.message}`);
}
}
);
} catch (err) {
const e: BusinessError = err as BusinessError;
console.error(`[FeedbackUtil] 停止震动异常: ${e.message}`);
}
}

/**
* 番茄钟完成反馈
* 长震动 + 特效震动
*/

public pomodoroComplete(): void {
this.vibrate(500);
setTimeout(() => {
this.vibratePattern([100, 100, 100, 100]);
}, 600);
}

/**
* 休息开始反馈
*/

public breakStart(): void {
this.vibrate(150);
}

/**
* 休息结束反馈
*/

public breakEnd(): void {
this.vibrate(100);
setTimeout(() => {
this.vibrate(100);
}, 200);
}
}

四、业务场景集成

4.1 在PomodoroPage中使用

import { FeedbackUtil } from '../utils/FeedbackUtil';

@Entry
@Component
struct PomodoroPage {
// 工具类实例
private feedbackUtil: FeedbackUtil = FeedbackUtil.getInstance();

// 计时完成
async onTimerComplete() {
this.stopTimer();
this.isRunning = false;

if (this.isBreak) {
// 休息结束
this.isBreak = false;
this.timeLeft = this.customDuration * 60;
this.feedbackUtil.breakEnd(); // 双击震动
} else {
// 番茄钟完成
this.pomodoroCount++;
// … 保存记录逻辑

this.feedbackUtil.pomodoroComplete(); // 长震动+模式震动

// 进入休息
this.timeLeft = Constants.SHORT_BREAK_DURATION * 60;
this.isBreak = true;
this.feedbackUtil.breakStart(); // 短震动
}
}
}

4.2 震动时机说明

【图1:震动反馈时机】

┌─────────────────────────────────────┐
│ 番茄钟生命周期 │
├─────────────────────────────────────┤
│ [开始专注] │
│ ↓ │
│ [专注中…] │
│ ↓ │
│ [专注完成] → pomodoroComplete() │
│ ↓ (500ms + 模式震动) │
│ [进入休息] → breakStart() │
│ ↓ (150ms震动) │
│ [休息中…] │
│ ↓ │
│ [休息结束] → breakEnd() │
│ (双击震动) │
└─────────────────────────────────────┘

五、API详解

5.1 startVibration参数

vibrator.startVibration(
effect: VibrateEffect, // 震动效果
attribute: VibrateAttribute, // 震动属性
callback: AsyncCallback<void> // 回调
)

VibrateEffect类型:

类型说明示例
time 时长震动 { type: 'time', duration: 200 }
preset 预设效果 { type: 'preset', effectId: 'haptic.clock.timer' }
file 文件震动 { type: 'file', hapticScene: 'xxx' }

VibrateAttribute属性:

{
id: 0, // 震动马达ID
usage: 'alarm' // 使用场景:alarm/notification/communication等
}

5.2 stopVibration参数

vibrator.stopVibration(
stopMode: VibratorStopMode, // 停止模式
callback: AsyncCallback<void>
)

VibratorStopMode枚举:

模式说明
VIBRATOR_STOP_MODE_TIME 停止时长震动
VIBRATOR_STOP_MODE_PRESET 停止预设震动
VIBRATOR_STOP_MODE_FILE 停止文件震动

六、最佳实践

6.1 单例模式

// ✅ 推荐:使用单例避免重复创建
private feedbackUtil: FeedbackUtil = FeedbackUtil.getInstance();

// ❌ 不推荐:每次都创建新实例
let feedbackUtil = new FeedbackUtil(); // 构造函数私有,无法直接创建

6.2 异常处理

// ✅ 推荐:捕获所有可能的异常
try {
vibrator.startVibration(effect, attribute, callback);
} catch (err) {
const e: BusinessError = err as BusinessError;
console.error(`震动异常: ${e.message}`);
}

// ❌ 不推荐:不处理异常
vibrator.startVibration(effect, attribute, callback);

6.3 权限检查

// 在使用前检查权限
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';

async checkVibratePermission(): Promise<boolean> {
const atManager = abilityAccessCtrl.createAtManager();
const grantStatus = await atManager.verifyAccessToken(
this.context.applicationInfo.accessTokenId,
'ohos.permission.VIBRATE'
);
return grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
}

七、效果测试

7.1 测试环境说明

⚠️ 重要提示:模拟器不支持震动功能,需要在真机上测试震动效果。

【图2:测试环境对比】

环境震动支持测试建议
模拟器 ❌ 不支持 用于UI和逻辑测试
真机 ✅ 支持 用于震动效果测试

7.2 测试场景

【图3:震动效果时序图】

时间轴:番茄钟完成 → 休息开始 → 休息结束

├─ [0ms] 触发 pomodoroComplete()
│ └─ 500ms长震动 ▓▓▓▓▓

├─ [600ms] 触发模式震动
│ └─ haptic.clock.timer 特效

├─ [800ms] 触发 breakStart()
│ └─ 150ms短震动 ▓▓

└─ [休息结束] 触发 breakEnd()
└─ 双击震动 ▓ ▓ (100ms × 2)

7.3 真机测试步骤

  • 连接真机:用USB连接手机到DevEco Studio
  • 运行应用:点击运行按钮,选择真机设备
  • 测试震动:
    • 启动番茄钟
    • 等待倒计时结束(可设置短时间测试)
    • 手机会震动反馈
  • 7.4 用户体验优化

    ┌─────────────────────────────────────┐
    │ 震动强度建议 │
    ├─────────────────────────────────────┤
    │ 重要提醒(完成)→ 强震动 │
    │ 状态切换(休息)→ 中等震动 │
    │ 轻量提示 → 轻震动 │
    └─────────────────────────────────────┘

    7.5 效果截图

    【图4:番茄钟完成界面】
    在这里插入图片描述

    倒计时结束,显示完成状态

    【图5:进入休息界面】
    在这里插入图片描述

    自动切换到休息模式

    八、总结

    本文实现了番茄钟的系统级震动反馈功能:

  • 权限配置:在module.json5中声明VIBRATE权限
  • 工具类封装:FeedbackUtil单例类统一管理震动逻辑
  • 场景集成:在关键时刻调用对应的震动方法
  • 异常处理:捕获所有可能的错误保证稳定性
  • 震动反馈是提升用户体验的重要手段,合理使用可以让应用更加人性化。


    赞(0)
    未经允许不得转载:171主机测评 » 及时做APP开发实战(九)-系统级震动反馈实现
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址