一、通知系统开发全面解析
1. 通知权限与基础配置
在 module.json5
中声明通知和语音相关权限:
{"module": {"requestPermissions": [{"name": "ohos.permission.NOTIFICATION_CONTROLLER","reason": "$string:notification_permission_reason","usedScene": {"abilities": ["MainAbility"],"when": "always"}},{"name": "ohos.permission.MICROPHONE","reason": "$string:microphone_permission_reason","usedScene": {"abilities": ["MainAbility"],"when": "always"}},{"name": "ohos.permission.VIBRATE","reason": "$string:vibrate_permission_reason","usedScene": {"abilities": ["MainAbility"],"when": "always"}}]}
}
2. 通知通道(NotificationSlot)创建
创建不同类型的通知通道以适应不同场景:
import notificationManager from '@ohos.notificationManager';
import { BusinessError } from '@ohos.base';class NotificationService {// 初始化通知通道async initializeNotificationSlots(): Promise<void> {try {// 1. 紧急警报通道(高优先级)const emergencySlot: notificationManager.NotificationSlot = {id: 'emergency_slot',name: '紧急警报',type: notificationManager.SlotType.ALARM,level: notificationManager.SlotLevel.LEVEL_HIGH,vibrationEnabled: true,vibrationValues: [1000, 1000, 1000], // 震动模式soundEnabled: true,sound: 'system://alarm_alert.mp3', // 系统警报音bypassDnd: true, // 绕过免打扰模式description: '重要安全警报和紧急通知'};await notificationManager.addSlot(emergencySlot);// 2. 消息通知通道(中等优先级)const messageSlot: notificationManager.NotificationSlot = {id: 'message_slot',name: '消息通知',type: notificationManager.SlotType.SOCIAL_COMMUNICATION,level: notificationManager.SlotLevel.LEVEL_DEFAULT,vibrationEnabled: true,vibrationValues: [500, 500], // 短震动soundEnabled: true,sound: 'system://message_alert.mp3',bypassDnd: false,description: '聊天消息和社交通知'};await notificationManager.addSlot(messageSlot);// 3. 普通通知通道(低优先级)const normalSlot: notificationManager.NotificationSlot = {id: 'normal_slot',name: '普通通知',type: notificationManager.SlotType.OTHER_TYPES,level: notificationManager.SlotLevel.LEVEL_LOW,vibrationEnabled: false,soundEnabled: false,bypassDnd: false,description: '一般应用通知和状态更新'};await notificationManager.addSlot(normalSlot);console.info('所有通知通道初始化成功');} catch (error) {console.error(`通知通道初始化失败: ${(error as BusinessError).message}`);}}
}
3. 发送不同类型通知
实现多种场景的通知发送功能:
class NotificationSender {private notificationId: number = 0;// 发送基本文本通知async sendBasicNotification(title: string, content: string, slotId: string = 'normal_slot'): Promise<boolean> {try {const notificationRequest: notificationManager.NotificationRequest = {id: this.notificationId++,slotId: slotId,content: {contentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,normal: {title: title,text: content,additionalText: '来自我的应用'}},deliveryTime: Date.now(), // 立即发送autoDeletedTime: Date.now() + 3600000, // 1小时后自动删除tapDismissed: true // 点击后消失};await notificationManager.publish(notificationRequest);console.info(`通知发送成功: ${title}`);return true;} catch (error) {console.error(`通知发送失败: ${(error as BusinessError).message}`);return false;}}// 发送带动作按钮的通知async sendActionableNotification(title: string,content: string,actions: notificationManager.NotificationActionButton[]): Promise<boolean> {try {const notificationRequest: notificationManager.NotificationRequest = {id: this.notificationId++,slotId: 'message_slot',content: {contentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,normal: {title: title,text: content}},actionButtons: actions,// 设置点击意图(跳转到特定页面)intent: {bundleName: 'com.example.myapp',abilityName: 'DetailAbility',parameters: { notificationId: this.notificationId.toString() }}};await notificationManager.publish(notificationRequest);return true;} catch (error) {console.error(`可操作通知发送失败: ${(error as BusinessError).message}`);return false;}}// 发送进度通知(用于下载、上传等场景)async sendProgressNotification(title: string,progress: number,maxProgress: number = 100): Promise<void> {try {const notificationRequest: notificationManager.NotificationRequest = {id: 1001, // 固定ID用于更新同一通知slotId: 'normal_slot',content: {contentType: notificationManager.ContentType.NOTIFICATION_CONTENT_PROGRESS,progress: {title: title,progressValue: progress,progressMaxValue: maxProgress,statusText: `${progress}% 完成`}},isOngoing: true // 进行中通知,不会被轻易清除};await notificationManager.publish(notificationRequest);// 完成后更新为完成状态if (progress >= maxProgress) {setTimeout(async () => {await this.sendBasicNotification(title, '任务已完成', 'normal_slot');await notificationManager.cancel(1001);}, 2000);}} catch (error) {console.error(`进度通知发送失败: ${(error as BusinessError).message}`);}}
}
4. 通知管理与交互处理
实现通知的生命周期管理和用户交互处理:
@Component
struct NotificationHandler {@State activeNotifications: notificationManager.NotificationRequest[] = [];private notificationListener: notificationManager.NotificationSubscriber | null = null;aboutToAppear() {this.setupNotificationListener();}// 设置通知监听器private setupNotificationListener(): void {try {this.notificationListener = {onNotificationPublished: (notification: notificationManager.NotificationRequest) => {console.info('通知已发布:', notification.id);this.updateActiveNotifications();},onNotificationCancelled: (id: number, slotId: string, reason: number) => {console.info(`通知已取消: ${id}, 原因: ${reason}`);this.updateActiveNotifications();},onNotificationUpdated: (notification: notificationManager.NotificationRequest) => {console.info('通知已更新:', notification.id);this.updateActiveNotifications();}};notificationManager.subscribe(this.notificationListener);} catch (error) {console.error(`通知监听器设置失败: ${(error as BusinessError).message}`);}}// 更新活动通知列表private async updateActiveNotifications(): Promise<void> {try {this.activeNotifications = await notificationManager.getActiveNotifications();} catch (error) {console.error(`获取活动通知失败: ${(error as BusinessError).message}`);}}// 处理通知点击事件handleNotificationClick(notificationId: number): void {console.info(`通知被点击: ${notificationId}`);// 根据通知ID执行相应操作switch (notificationId) {case 1001:router.push({ url: 'pages/DownloadPage' });break;case 1002:router.push({ url: 'pages/MessageDetail' });break;default:router.push({ url: 'pages/NotificationCenter' });}}aboutToDisappear() {if (this.notificationListener) {notificationManager.unsubscribe(this.notificationListener);}}build() {// 通知处理UI组件}
}
二、语音识别(ASR)开发实战
1. 语音识别服务初始化
配置和初始化语音识别功能:
import speechRecognizer from '@ohos.speechRecognizer';
import { BusinessError } from '@ohos.base';class SpeechRecognitionService {private recognizer: speechRecognizer.SpeechRecognizer | null = null;@State isListening: boolean = false;@State recognitionResult: string = '';@State confidence: number = 0;// 初始化语音识别器async initializeRecognizer(): Promise<boolean> {try {this.recognizer = speechRecognizer.createSpeechRecognizer();// 设置识别参数const config: speechRecognizer.RecognizerConfig = {language: 'zh-CN', // 中文普通话country: 'CN',punctuation: true, // 启用标点符号mode: speechRecognizer.RecognizeMode.FREE_FORM, // 自由格式识别audioSource: speechRecognizer.AudioSource.MICROPHONE // 麦克风输入};await this.recognizer.setConfig(config);// 设置识别结果回调this.recognizer.on('result', (result: speechRecognizer.RecognizerResult) => {this.recognitionResult = result.text;this.confidence = result.confidence;console.info(`识别结果: ${result.text}, 置信度: ${result.confidence}`);});// 设置错误回调this.recognizer.on('error', (error: BusinessError) => {console.error(`语音识别错误: ${error.message}`);this.isListening = false;});console.info('语音识别器初始化成功');return true;} catch (error) {console.error(`语音识别器初始化失败: ${(error as BusinessError).message}`);return false;}}// 开始语音识别async startRecognition(): Promise<void> {if (!this.recognizer) {await this.initializeRecognizer();}try {await this.recognizer.start();this.isListening = true;console.info('语音识别开始');} catch (error) {console.error(`启动语音识别失败: ${(error as BusinessError).message}`);}}// 停止语音识别async stopRecognition(): Promise<void> {if (this.recognizer && this.isListening) {try {await this.recognizer.stop();this.isListening = false;console.info('语音识别停止');} catch (error) {console.error(`停止语音识别失败: ${(error as BusinessError).message}`);}}}// 销毁识别器async destroyRecognizer(): Promise<void> {if (this.recognizer) {await this.stopRecognition();this.recognizer.destroy();this.recognizer = null;}}
}
2. 实时语音识别组件
创建支持实时语音识别的UI组件:
@Component
struct VoiceRecognitionComponent {private speechService: SpeechRecognitionService = new SpeechRecognitionService();@State recognizedText: string = '点击麦克风开始说话...';@State isRecording: boolean = false;@State confidenceLevel: number = 0;aboutToAppear() {this.speechService.initializeRecognizer();}// 切换录音状态async toggleRecording(): Promise<void> {if (this.isRecording) {await this.speechService.stopRecognition();this.isRecording = false;} else {await this.speechService.startRecognition();this.isRecording = true;// 监听识别结果this.speechService.onResult((result: string, confidence: number) => {this.recognizedText = result;this.confidenceLevel = confidence;});}}build() {Column() {// 语音波形动画if (this.isRecording) {VoiceWaveAnimation().height(80).margin({ bottom: 20 })}// 识别结果展示Text(this.recognizedText).fontSize(18).textAlign(TextAlign.Center).margin({ bottom: 16 }).minHeight(100).width('90%')// 置信度指示器if (this.confidenceLevel > 0) {Text(`置信度: ${(this.confidenceLevel * 100).toFixed(1)}%`).fontSize(14).fontColor('#666').margin({ bottom: 20 })}// 录音按钮Button(this.isRecording ? '停止录音' : '开始语音识别').width(200).height(60).backgroundColor(this.isRecording ? '#FF5252' : '#2196F3').onClick(() => {this.toggleRecording();}).margin({ bottom: 30 })// 语音指令示例if (!this.isRecording) {Column() {Text('试试说:').fontSize(16).fontWeight(FontWeight.Bold).margin({ bottom: 8 })Text('• "打开设置"').fontSize(14).opacity(0.7)Text('• "发送消息给张三"').fontSize(14).opacity(0.7)Text('• "今天天气怎么样"').fontSize(14).opacity(0.7)}.padding(16).backgroundColor('#F5F5F5').borderRadius(12)}}.width('100%').height('100%').padding(20).alignItems(HorizontalAlign.Center)}
}
三、语音合成(TTS)开发实战
1. 语音合成服务配置
实现文本到语音的转换功能:
import textToSpeech from '@ohos.textToSpeech';
import { BusinessError } from '@ohos.base';class TextToSpeechService {private ttsEngine: textToSpeech.TtsEngine | null = null;@State isSpeaking: boolean = false;@State availableVoices: textToSpeech.VoiceInfo[] = [];@State currentVoice: string = '';// 初始化TTS引擎async initializeTts(): Promise<boolean> {try {this.ttsEngine = textToSpeech.createTtsEngine();// 获取可用语音列表this.availableVoices = await this.ttsEngine.getVoices();this.currentVoice = this.availableVoices[0]?.voiceId || '';// 设置TTS参数const ttsConfig: textToSpeech.TtsConfig = {voiceId: this.currentVoice, // 默认语音speed: 1.0, // 语速 (0.5-2.0)pitch: 1.0, // 音调 (0.5-2.0)volume: 0.8, // 音量 (0.0-1.0)audioStreamType: textToSpeech.AudioStreamType.STREAM_MUSIC};await this.ttsEngine.setConfig(ttsConfig);console.info('TTS引擎初始化成功');return true;} catch (error) {console.error(`TTS引擎初始化失败: ${(error as BusinessError).message}`);return false;}}// 播放语音async speak(text: string, config?: textToSpeech.TtsConfig): Promise<void> {if (!this.ttsEngine) {await this.initializeTts();}try {if (config) {await this.ttsEngine.setConfig(config);}this.isSpeaking = true;await this.ttsEngine.speak(text);// 监听播放完成this.ttsEngine.on('finish', () => {this.isSpeaking = false;console.info('语音播放完成');});// 监听错误事件this.ttsEngine.on('error', (error: BusinessError) => {this.isSpeaking = false;console.error(`语音播放错误: ${error.message}`);});} catch (error) {console.error(`语音播放失败: ${(error as BusinessError).message}`);}}// 停止播放async stop(): Promise<void> {if (this.ttsEngine && this.isSpeaking) {try {await this.ttsEngine.stop();this.isSpeaking = false;} catch (error) {console.error(`停止语音播放失败: ${(error as BusinessError).message}`);}}}// 暂停播放async pause(): Promise<void> {if (this.ttsEngine && this.isSpeaking) {try {await this.ttsEngine.pause();this.isSpeaking = false;} catch (error) {console.error(`暂停语音播放失败: ${(error as BusinessError).message}`);}}}// 恢复播放async resume(): Promise<void> {if (this.ttsEngine && !this.isSpeaking) {try {await this.ttsEngine.resume();this.isSpeaking = true;} catch (error) {console.error(`恢复语音播放失败: ${(error as BusinessError).message}`);}}}
}
2. 语音朗读组件
创建支持多种语音设置的朗读组件:
@Component
struct TextToSpeechComponent {private ttsService: TextToSpeechService = new TextToSpeechService();@State textToRead: string = '';@State isPlaying: boolean = false;@State speechSpeed: number = 1.0;@State speechPitch: number = 1.0;@State selectedVoice: string = '';aboutToAppear() {this.ttsService.initializeTts();}// 朗读文本async readText(): Promise<void> {if (this.textToRead.trim() === '') {prompt.showToast({ message: '请输入要朗读的文本' });return;}const config: textToSpeech.TtsConfig = {voiceId: this.selectedVoice || undefined,speed: this.speechSpeed,pitch: this.speechPitch,volume: 0.8};if (this.isPlaying) {await this.ttsService.stop();this.isPlaying = false;} else {await this.ttsService.speak(this.textToRead, config);this.isPlaying = true;}}build() {Column() {// 文本输入区域TextArea({ text: this.textToRead, placeholder: '输入要朗读的文本...' }).height(150).width('90%').margin({ bottom: 20 }).onChange((value: string) => {this.textToRead = value;})// 语音设置Column() {Text('语音设置').fontSize(16).fontWeight(FontWeight.Bold).margin({ bottom: 12 })// 语速调节Row() {Text('语速:').width(80)Slider({ value: this.speechSpeed, min: 0.5, max: 2.0, step: 0.1 }).layoutWeight(1).onChange((value: number) => {this.speechSpeed = value;})Text(this.speechSpeed.toFixed(1)).width(40)}.margin({ bottom: 12 })// 音调调节Row() {Text('音调:').width(80)Slider({ value: this.speechPitch, min: 0.5, max: 2.0, step: 0.1 }).layoutWeight(1).onChange((value: number) => {this.speechPitch = value;})Text(this.speechPitch.toFixed(1)).width(40)}.margin({ bottom: 12 })}.width('90%').padding(16).backgroundColor('#F8F9FA').borderRadius(12).margin({ bottom: 20 })// 控制按钮Button(this.isPlaying ? '停止朗读' : '开始朗读').width(200).height(50).backgroundColor(this.isPlaying ? '#FF5252' : '#4CAF50').onClick(() => {this.readText();}).margin({ bottom: 20 })// 状态指示if (this.isPlaying) {LoadingIndicator().size({ width: 30, height: 30 }).margin({ bottom: 10 })Text('朗读中...').fontSize(14).fontColor('#666')}}.width('100%').height('100%').padding(20).alignItems(HorizontalAlign.Center)}
}
四、通知与语音的协同应用
1. 语音播报通知内容
实现收到通知后自动语音播报的功能:
class NotificationVoiceReader {private ttsService: TextToSpeechService;private notificationService: NotificationService;constructor() {this.ttsService = new TextToSpeechService();this.notificationService = new NotificationService();this.setupNotificationListener();}// 设置通知监听器private setupNotificationListener(): void {notificationManager.subscribe({onNotificationPublished: async (notification: notificationManager.NotificationRequest) => {// 只播报高优先级通知if (notification.slotId === 'emergency_slot' || notification.slotId === 'message_slot') {const title = notification.content.normal?.title || '';const text = notification.content.normal?.text || '';await this.readNotification(title, text);}}});}// 朗读通知内容private async readNotification(title: string, content: string): Promise<void> {const fullText = `收到新通知: ${title}. ${content}`;await this.ttsService.speak(fullText, {speed: 1.0,pitch: 1.1, // 稍高音调以提高可听性volume: 0.9});}// 语音控制通知管理async handleVoiceCommand(command: string): Promise<void> {const lowerCommand = command.toLowerCase();if (lowerCommand.includes('阅读通知')) {await this.readAllNotifications();} else if (lowerCommand.includes('清除通知')) {await notificationManager.cancelAll();await this.ttsService.speak('已清除所有通知');} else if (lowerCommand.includes('打开通知中心')) {router.push({ url: 'pages/NotificationCenter' });}}// 朗读所有未读通知private async readAllNotifications(): Promise<void> {try {const notifications = await notificationManager.getActiveNotifications();if (notifications.length === 0) {await this.ttsService.speak('没有未读通知');return;}await this.ttsService.speak(`您有${notifications.length}条未读通知`);for (const notification of notifications) {const title = notification.content.normal?.title || '';const text = notification.content.normal?.text || '';await this.readNotification(title, text);await new Promise(resolve => setTimeout(resolve, 1000)); // 暂停1秒}} catch (error) {console.error(`朗读通知失败: ${(error as BusinessError).message}`);}}
}
2. 语音助手集成示例
创建完整的语音助手组件,集成通知和语音能力:
@Component
struct VoiceAssistant {private speechRecognition: SpeechRecognitionService = new SpeechRecognitionService();private ttsService: TextToSpeechService = new TextToSpeechService();private notificationReader: NotificationVoiceReader = new NotificationVoiceReader();@State isAssistantActive: boolean = false;@State commandHistory: string[] = [];aboutToAppear() {this.initializeServices();}// 初始化服务async initializeServices(): Promise<void> {await this.speechRecognition.initializeRecognizer();await this.ttsService.initializeTts();// 设置语音识别回调this.speechRecognition.onResult((result: string, confidence: number) => {if (confidence > 0.7) { // 置信度阈值this.processVoiceCommand(result);this.commandHistory = [result, ...this.commandHistory.slice(0, 9)]; // 保留最近10条}});}// 处理语音指令private async processVoiceCommand(command: string): Promise<void> {console.info(`处理语音指令: ${command}`);if (command.includes('通知') || command.includes('消息')) {await this.notificationReader.handleVoiceCommand(command);} else if (command.includes('时间')) {const now = new Date();const timeText = `现在时间是${now.getHours()}点${now.getMinutes()}分`;await this.ttsService.speak(timeText);} else if (command.includes('天气')) {await this.ttsService.speak('正在查询天气信息...');// 这里可以集成天气API} else {await this.ttsService.speak(`已执行命令: ${command}`);}}// 切换助手状态async toggleAssistant(): Promise<void> {if (this.isAssistantActive) {await this.speechRecognition.stopRecognition();await this.ttsService.stop();this.isAssistantActive = false;} else {await this.speechRecognition.startRecognition();await this.ttsService.speak('语音助手已启动,请说出您的指令');this.isAssistantActive = true;}}build() {Column() {// 助手状态显示Text(this.isAssistantActive ? '语音助手运行中...' : '点击启动语音助手').fontSize(18).fontWeight(FontWeight.Bold).margin({ bottom: 20 })// 主控制按钮Button(this.isAssistantActive ? '停止助手' : '启动语音助手').width(250).height(60).backgroundColor(this.isAssistantActive ? '#FF5252' : '#2196F3').onClick(() => {this.toggleAssistant();}).margin({ bottom: 30 })// 指令历史if (this.commandHistory.length > 0) {Column() {Text('最近指令').fontSize(16).fontWeight(FontWeight.Bold).margin({ bottom: 12 })ForEach(this.commandHistory, (command: string) => {Text(`• ${command}`).fontSize(14).textAlign(TextAlign.Start).width('90%').margin({ bottom: 8 })})}.width('90%').padding(16).backgroundColor('#F8F9FA').borderRadius(12)}// 快速指令示例Column() {Text('试试说:').fontSize(16).fontWeight(FontWeight.Bold).margin({ bottom: 8 })Text('• "阅读我的通知"').fontSize(14).opacity(0.7)Text('• "现在几点了"').fontSize(14).opacity(0.7)Text('• "清除所有通知"').fontSize(14).opacity(0.7)}.margin({ top: 20 })}.width('100%').height('100%').padding(20).alignItems(HorizontalAlign.Center)}
}
⚡ 五、性能优化与最佳实践
1. 资源管理与性能优化
语音服务资源管理:
class ResourceOptimizer {private static activeTtsInstances: number = 0;private static readonly MAX_TTS_INSTANCES: number = 3;// 智能TTS实例管理static async getTtsInstance(): Promise<textToSpeech.TtsEngine> {if (this.activeTtsInstances >= this.MAX_TTS_INSTANCES) {throw new Error('达到TTS实例数量限制');}const tts = textToSpeech.createTtsEngine();this.activeTtsInstances++;// 设置销毁钩子tts.on('destroy', () => {this.activeTtsInstances--;});return tts;}// 语音识别资源优化static optimizeRecognitionConfig(): speechRecognizer.RecognizerConfig {return {language: 'zh-CN',mode: speechRecognizer.RecognizeMode.FREE_FORM,audioSource: speechRecognizer.AudioSource.MICROPHONE,bufferSize: 8192, // 优化缓冲区大小sampleRate: 16000, // 适当采样率encoding: speechRecognizer.AudioEncoding.ENCODING_PCM_16BIT};}
}
2. 电量与网络优化
后台服务优化策略:
class PowerOptimization {// 低电量模式检测static isLowPowerMode(): boolean {const batteryLevel = deviceInfo.getBatteryLevel();return batteryLevel < 20;}// 自适应语音质量static getAdaptiveTtsConfig(): textToSpeech.TtsConfig {const isLowPower = this.isLowPowerMode();return {speed: isLowPower ? 1.2 : 1.0, // 低电量时稍快语速pitch: 1.0,volume: 0.8,audioStreamType: isLowPower ? textToSpeech.AudioStreamType.STREAM_VOICE_CALL : // 低功耗模式textToSpeech.AudioStreamType.STREAM_MUSIC // 正常模式};}// 网络状态感知的通知发送static async sendNetworkAwareNotification(notification: notificationManager.NotificationRequest): Promise<void> {const networkType = network.getNetworkType();// 在移动网络下优化通知内容if (networkType === network.NetworkType.NETWORK_MOBILE) {// 简化通知内容,减少数据使用if (notification.content.normal) {notification.content.normal.text = notification.content.normal.text.substring(0, 100) + '...';}}await notificationManager.publish(notification);}
}
通过掌握这些通知和语音开发技术,你可以在HarmonyOS应用中创建智能、高效的人机交互体验,从基本的消息推送到复杂的语音交互,全面提升应用的用户体验。
需要参加鸿蒙认证的请点击 鸿蒙认证链接