请添加图片描述
请添加图片描述

AI 修仙功法 —— 鸿蒙 NEXT ArkTS 修仙主题 AI 对话应用开发全解析应用

第一章 开篇:修仙与鸿蒙的缘起

大道三千,殊途同归。当古老的修仙传说遇上现代的鸿蒙操作系统,一段全新的修炼之旅就此展开。

1.1 缘起:何为"AI 修仙"

在传统修仙小说中,修士通过吐纳天地灵气、炼化法宝、感悟大道来提升修为。而在这个万物互联的数字时代,"修仙"被赋予了全新的含义——通过 AI 技术赋能应用,让冰冷的代码拥有"灵性",让沉默的设备能够"开口说话"

本文将以一个完整的 HarmonyOS NEXT ArkTS 项目为蓝本,深入剖析如何构建一个"AI 修仙"主题的对话应用。这个项目虽然以一个 TTS(文本转语音)功能为切入点,但它的架构设计、权限管理、生命周期控制和模块封装,无一不体现着"修炼"的智慧。

1.2 修炼环境:HarmonyOS NEXT 6.1.1(API 24)

本项目基于 HarmonyOS NEXT 6.1.1 版本,对应的 SDK 版本为 6.1.0(23),采用 Stage 模型 进行开发。Stage 模型是 HarmonyOS 从 API 9 开始主推的 Ability 框架,它相较于旧的 FA(Feature Ability)模型,具有以下核心优势:

特性 传统 FA 模型 Stage 模型
组件化 强,Ability 作为独立模块
生命周期 简单但粗粒度 精细化管理
进程模型 多进程较复杂 天然支持多进程
首选项存储 需自行实现 内置 Preferences
后台任务 受限 成熟的 WorkScheduler 机制

本项目的 Stage 模型配置体现在 build-profile.json5 中:

{
  "apiType": "stageMode",
  "buildOptionSet": [
    {
      "name": "release",
      "arkOptions": {
        "obfuscation": {
          "ruleOptions": {
            "enable": false,
            "files": ["./obfuscation-rules.txt"]
          }
        }
      }
    }
  ],
  "targets": [
    { "name": "default" },
    { "name": "ohosTest" }
  ]
}

修炼要点:Stage 模型下的 apiType: "stageMode" 声明了整个应用以 Stage 方式运行,这是鸿蒙 NEXT 推荐的现代化架构风格。

1.3 功法概览:项目结构

完整的项目目录结构如下(省略构建产物和非关键文件):

s222222/
├── AppScope/
│   ├── app.json5                    # 应用级配置
│   └── resources/
│       ├── base/
│       │   ├── element/string.json  # 应用名字符串资源
│       │   └── media/               # 应用图标资源
├── entry/
│   ├── src/main/
│   │   ├── ets/
│   │   │   ├── pages/Index.ets      # 主页面(UI + 交互逻辑)
│   │   │   ├── entryability/EntryAbility.ets  # Ability 生命周期
│   │   │   ├── entrybackupability/EntryBackupAbility.ets  # 备份扩展
│   │   │   └── TTSManager.ets       # TTS 引擎管理器(核心功法)
│   │   ├── module.json5             # 模块配置(权限、入口等)
│   │   └── resources/               # 模块级资源
│   ├── build-profile.json5          # 模块构建配置
│   └── oh-package.json5             # 模块依赖声明
├── build-profile.json5              # 项目级构建配置
├── oh-package.json5                 # 项目级依赖管理
├── hvigor/
│   └── hvigor-config.json5          # 构建工具配置
└── local.properties                 # 本地环境配置

这个结构体现了鸿蒙应用的标准分层:AppScope(宗门层级)→ Module(修炼洞府)→ Ability(功法心法)。每一层各司其职,共同构成完整的应用体系。


第二章 筑基:Module 配置与权限修炼

2.1 Module 配置详解(module.json5)

module.json5 是鸿蒙应用中最关键的路引,它定义了模块的诸多核心属性。让我们逐条解析这个"修炼法门":

{
  "module": {
    "name": "entry",                    // 模块名称,唯一标识
    "type": "entry",                    // 模块类型:entry(主入口)| feature(特性模块)
    "description": "$string:module_desc",// 模块描述,引用字符串资源
    "mainElement": "EntryAbility",       // 主 Ability 入口
    "deviceTypes": ["phone"],            // 支持的设备类型
    "deliveryWithInstall": true,         // 随安装交付
    "installationFree": false,           // 是否支持免安装运行

    "pages": "$profile:main_pages",      // 页面路由配置

    "abilities": [                       // Ability 注册列表
      {
        "name": "EntryAbility",          // Ability 名称
        "srcEntry": "./ets/entryability/EntryAbility.ets",  // 源文件路径
        "description": "$string:EntryAbility_desc",
        "icon": "$media:layered_image",  // 图标(支持分层图标)
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:startIcon",  // 启动窗口图标
        "startWindowBackground": "$color:start_window_background",  // 启动背景色
        "exported": true,                // 是否可被其他应用启动
        "skills": [                      // 意图过滤器
          {
            "entities": ["entity.system.home"],
            "actions": ["ohos.want.action.home"]
          }
        ]
      }
    ],
    "extensionAbilities": [              // 扩展 Ability
      {
        "name": "EntryBackupAbility",
        "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
        "type": "backup",               // 扩展类型:备份
        "exported": false
      }
    ],
    "requestPermissions": [              // 运行时权限声明
      {
        "name": "ohos.permission.MICROPHONE",  // 麦克风权限
        "reason": "$string:permission_microphone_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "always"               // 始终可用
        }
      },
      {
        "name": "ohos.permission.INTERNET",   // 网络权限
        "reason": "$string:permission_internet_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "always"
        }
      }
    ]
  }
}

2.2 权限修炼之道

权限是鸿蒙安全体系的核心。本项目申请了两个关键权限:

2.2.1 麦克风权限(MICROPHONE)
{
  "name": "ohos.permission.MICROPHONE",
  "reason": "用于语音识别功能采集麦克风音频,进行语音转文字。"
}

虽然在当前代码中主要演示的是 TTS(文字→语音),但项目中已经预留了语音识别的能力接口。麦克风权限是用户敏感权限,需要满足以下条件:

  • module.json5 中声明
  • 在首次使用时通过弹窗征得用户同意
  • 提供清晰的权限用途说明

鸿蒙 NEXT 的权限管理采用了细粒度运行时授权机制,用户可以在"设置→应用→权限管理"中随时开关每一项权限。

2.2.2 网络权限(INTERNET)
{
  "name": "ohos.permission.INTERNET",
  "reason": "用于联网获取或发送与语音能力相关的数据。"
}

本项目使用的 TTS 引擎支持在线模式online: 1),这意味着语音合成请求需要通过互联网发送到服务端进行处理。因此网络权限是必需的。

2.3 页面路由配置

// entry/src/main/resources/base/profile/main_pages.json
{
  "src": ["pages/Index"]
}

这是页面的路由表,定义了应用有哪些页面以及它们的路由路径。当前只有一个页面 pages/Index,对应 Index.ets 组件。在 Stage 模型中,页面路由通过 $profile:main_pages 引用,实现配置与代码的解耦。


第三章 心法:EntryAbility 生命周期修炼

3.1 Ability 概述

在鸿蒙的世界里,Ability 是应用的基本组成单元,类似于 Android 的 Activity 和 iOS 的 ViewController。Stage 模型下的 UIAbility 负责管理应用窗口和页面生命周期。

3.2 完整生命周期解析

// entry/src/main/ets/entryability/EntryAbility.ets
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';

const DOMAIN = 0x0000;  // 日志域(0x0000~0xFFFF,建议业务使用0x0000)

export default class EntryAbility extends UIAbility {
  // 阶段一:创建阶段
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    try {
      // 设置颜色模式:跟随系统
      this.context.getApplicationContext()
        .setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
    } catch (err) {
      hilog.error(DOMAIN, 'testTag',
        'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
    }
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
  }

  // 阶段二:销毁阶段
  onDestroy(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
  }

  // 阶段三:窗口创建阶段(核心)
  onWindowStageCreate(windowStage: window.WindowStage): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    // 加载页面内容
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        hilog.error(DOMAIN, 'testTag',
          'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
        return;
      }
      hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
    });
  }

  // 阶段四:窗口销毁阶段
  onWindowStageDestroy(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }

  // 阶段五:切到前台
  onForeground(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
  }

  // 阶段六:切到后台
  onBackground(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
  }
}

3.3 生命周期的"修炼六境"

阶段 回调方法 类比修仙 说明
开光 onCreate 筑基成功 Ability 初次创建,初始化基础状态
融合 onWindowStageCreate 神识外放 窗口舞台就绪,加载页面内容
元婴 onForeground 元婴出窍 Ability 来到前台,开始交互
化神 onBackground 神识内敛 Ability 切到后台,释放非关键资源
渡劫 onWindowStageDestroy 肉身重塑 窗口销毁,清理窗口级资源
飞升 onDestroy 飞升上界 Ability 完全销毁,释放所有资源

重要实践:在 onCreate 中,我们设置颜色模式为 COLOR_MODE_NOT_SET(跟随系统),这体现了鸿蒙对系统一致性体验的追求——应用不应强迫用户使用某种配色方案,而应尊重系统设置。

3.4 扩展能力:备份恢复

// EntryBackupAbility.ets
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';

const DOMAIN = 0x0000;

export default class EntryBackupAbility extends BackupExtensionAbility {
  async onBackup() {
    hilog.info(DOMAIN, 'testTag', 'onBackup ok');
    await Promise.resolve();
  }

  async onRestore(bundleVersion: BundleVersion) {
    hilog.info(DOMAIN, 'testTag',
      'onRestore ok %{public}s', JSON.stringify(bundleVersion));
    await Promise.resolve();
  }
}

BackupExtensionAbility 是鸿蒙提供给应用的数据备份恢复能力。它允许应用在用户更换设备或重置设备后,将关键数据(如用户设置、对话历史)恢复到新设备上。这就像是修士的"元神备份"——即使肉身毁灭,神识仍可重生。


第四章 法宝:TTS 引擎管理器(核心功法)

4.1 功法总纲

TTSManager 是整个项目的核心,封装了鸿蒙 @kit.CoreSpeechKit 中的文本转语音引擎。它像一件精心炼制的法宝,包含了"驱动(引擎创建)→ 注灵(参数配置)→ 施法(语音播报)→ 收法(停止控制)→ 温养(资源释放)"的完整流程。

import { textToSpeech } from '@kit.CoreSpeechKit';
import { BusinessError } from '@ohos.base';

4.2 法宝淬炼:类的属性与构造函数

export class TTSManager {
  // ─── 核心法宝 ───
  private tts: textToSpeech.TextToSpeechEngine | null = null;
  
  // ─── 状态修为 ───
  private playing: boolean = false;
  private paused: boolean = false;
  private userStopped: boolean = false;
  private currentText: string = '';

  // ─── 传音符(回调) ───
  private onPlayingStateChange: (playing: boolean, paused: boolean) => void = () => {};
  private onLogChange: (log: string) => void = () => {};

  constructor(
    onPlayingStateChange?: (playing: boolean) => void,
    onLogChange?: (log: string) => void
  ) {
    if (onPlayingStateChange) {
      // 适配旧版本回调接口:只传递 playing 状态
      this.onPlayingStateChange = (playing, paused) => {
        onPlayingStateChange(playing);
      };
    }
    if (onLogChange) {
      this.onLogChange = onLogChange;
    }
    this.initTTS();  // 淬炼开始!
  }
}

设计思考:构造函数接受两个可选的回调参数,通过依赖注入的方式与 UI 层解耦。这种设计使得 TTSManager 可以在单元测试中独立运行,也便于将来替换 UI 层(如从 ArkUI 切换到 React Native)。

4.3 驱动注灵:创建 TTS 引擎

private initTTS(): void {
  const params: textToSpeech.CreateEngineParams = {
    language: 'zh-CN',  // 语言:中文普通话
    person: 0,           // 发音人:默认发音人
    online: 1            // 模式:在线合成(1=在线,0=离线)
  };

  textToSpeech.createEngine(
    params,
    (err: BusinessError, engine: textToSpeech.TextToSpeechEngine) => {
      if (err || !engine) {
        this.updateLog(`创建TTS引擎失败: ${err?.message}`);
        return;
      }
      this.tts = engine;
      this.setListener();  // 设置监听器
    }
  );
}
参数详解
参数 可选值 含义 修炼心得
language 'zh-CN', 'en-US', 'ja-JP' 合成语言 中文用 zh-CN,语速语调更自然
person 0, 1, 2 发音人编号 不同编号对应不同音色,0 通常为标准女声
online 0(离线), 1(在线) 引擎模式 在线音质更好、支持更多音色,但需要网络

修炼提醒:在线模式(online: 1)意味着应用必须拥有 ohos.permission.INTERNET 权限。如果用户拒绝授权,引擎将创建失败。在实际产品中,应当准备离线模式作为降级方案。

4.4 神识链接:设置监听器

private setListener(): void {
  if (!this.tts) return;

  const listener: textToSpeech.SpeakListener = {
    // ── 开始播报 ──
    onStart: (id, rsp) => {
      if (!this.paused) {
        this.userStopped = false;  // 正常开始,清除停止标记
      }
      this.updatePlaying(true, false);
      this.updateLog('开始播报');
    },

    // ── 播报完成 ──
    onComplete: (id, rsp) => {
      if (rsp && rsp.type === 1) {  // type=1 表示正常结束
        this.updateLog('播报完成');
        this.updatePlaying(false, false);
      }
    },

    // ── 播报停止 ──
    onStop: (id, rsp) => {
      this.updatePlaying(false, false);
    },

    // ── 音频数据回调(当前未使用) ──
    onData: (id, audio, rsp) => {
      // audio 为 AudioInputStream,可用于自定义播放
    },

    // ── 播报错误 ──
    onError: (id, code, msg) => {
      this.updateLog(`TTS错误(${code}): ${msg}`);
      this.updatePlaying(false, false);
    }
  };
  this.tts.setListener(listener);
}

状态管理剖析

userStoppedpaused 两个标志位是本法宝的精妙之处。它们区分了三种停止场景:

场景 userStopped paused 行为
用户主动停止 true false 停止播放,重置状态
用户暂停 false true 停在当前位置,可恢复
播报自然结束 false false 正常清理状态

这种设计在将来扩展暂停/恢复功能时尤为重要——我们可以通过 paused 状态判断是继续播报还是重新开始。

4.5 施法之道:speak 方法

public speak(text: string): void {
  if (!this.tts) {
    this.updateLog('TTS未就绪');
    return;
  }

  this.userStopped = false;
  this.paused = false;
  this.currentText = text;

  const filtered = this.filterText(text);  // 先净化文本
  const speakParams: textToSpeech.SpeakParams = {
    requestId: 'tts_' + Date.now()  // 唯一请求 ID
  };

  try {
    this.tts.speak(filtered, speakParams);
  } catch (e) {
    this.updateLog(`播报失败: ${JSON.stringify(e)}`);
  }
}

关键点

  1. 前置校验:如果引擎未就绪,直接返回并记录日志,避免空指针异常。
  2. 状态重置:每次新的播报都重置 userStoppedpaused,确保每次施法都是"全新开始"。
  3. 文本净化:调用 filterText 方法过滤特殊字符(见下节)。
  4. 唯一请求 IDrequestId 使用时间戳保证每次播报的唯一性,方便多播报并发场景下的追踪。
  5. 异常捕获try-catch 包围 speak 调用,防止未预期的运行时错误导致应用崩溃。

4.6 净魔咒:文本过滤

private filterText(text: string): string {
  return text
    // 移除 Emoji 表情符号(😀-🙏 区域)
    .replace(/[\u{1F600}-\u{1F64F}]/gu, '')
    // 移除 Emoji 符号(🗾-🧾 区域)
    .replace(/[\u{1F300}-\u{1F5FF}]/gu, '')
    // 移除交通符号(🚀-🏳️ 区域)
    .replace(/[\u{1F680}-\u{1F6FF}]/gu, '')
    // 移除杂项符号(☀-⛿ 区域)
    .replace(/[\u{2600}-\u{26FF}]/gu, '')
    // 移除补充符号区域
    .replace(/[\u{1F900}-\u{1F9FF}]/gu, '')
    // 移除文字表情(:-), :(, ;) 等)
    .replace(/[:;=][)(\]>DPdpO0\-]+/g, '')
    // 合并多余空白字符
    .replace(/[\s]+/g, ' ');
}

为什么需要文本净化?

TTS 引擎对特殊字符(尤其是 Emoji 和颜文字)的支持并不完善,直接传入会导致以下问题:

  • Emoji 被转语音为乱码字符
  • 颜文字中的符号可能触发引擎的误解析
  • 连续的空白字符导致语速异常

这个"净魔咒"通过 Unicode 范围匹配,精准地移除了 6 大区域的 Emoji 字符和常见的颜文字模式,确保送入引擎的文本是"纯净"的。

4.7 收法之功:停止与状态管理

public stop(): void {
  try {
    this.userStopped = true;      // 标记为用户主动停止
    this.paused = false;           // 清除暂停状态
    this.updatePlaying(false, false);
    this.tts?.stop();              // 可选链,安全调用
    this.updateLog('已停止播报');
  } catch (e) {
    this.updateLog(`停止失败: ${JSON.stringify(e)}`);
  }
}

优雅的停止

  • 使用可选链 this.tts?.stop() 而非 if (this.tts),更加简洁
  • 先更新状态再调用引擎停止,确保 UI 立即响应
  • try-catch 兜底,防止引擎内部异常传染到 UI 层

4.8 温养之道:资源释放

public shutdown(): void {
  if (this.tts) {
    try {
      this.tts.shutdown();       // 关闭引擎
    } catch (e) {
      console.error(`关闭TTS引擎失败: ${JSON.stringify(e)}`);
    }
    this.tts = null;             // 释放引用,便于 GC 回收
  }
}

修炼要义shutdown 方法必须在页面销毁时调用(对应 Index.ets 中的 aboutToDisappear 生命周期)。如果不释放 TTS 引擎,它会持续占用系统资源,导致内存泄漏和耗电增加。这就像修士在渡劫后需要闭关温养,避免"道基受损"。

4.9 法宝全貌

完整回顾 TTSManager 的核心方法与属性:

方法/属性 类别 作用 调用时机
initTTS() private 创建并初始化 TTS 引擎 构造函数中
setListener() private 绑定播报状态回调 引擎创建成功后
speak(text) public 开始播报 用户点击"朗读"按钮
stop() public 停止播报 用户点击"停止朗读"按钮
filterText(text) private 净化文本,移除特殊字符 speak() 内部
isPlaying() public 查询是否正在播报 UI 层状态绑定
isPaused() public 查询是否暂停 扩展用
getLog() public 获取最新的日志信息 调试和显示用
shutdown() public 释放引擎资源 页面销毁时

第五章 御剑:Index 主页面构建

5.1 页面布局总览

主页面 Index.ets 是整个应用的"飞剑"——它御剑飞行,串联了用户交互和 TTS 引擎。我们逐层解析这把飞剑的构造。

import { TTSManager } from '../TTSManager';

@Entry
@Component
struct Index {
  @State currentText: string = '你好,欢迎使用HarmonyOS TTS功能!';
  @State isSpeaking: boolean = false;
  @State logText: string = '';
  private ttsManager: TTSManager = new TTSManager(
    (playing) => { this.isSpeaking = playing; },
    (log) => { this.addLog('TTS', log); }
  );
  // ...
}

5.2 状态变量的"三花聚顶"

状态变量 类型 初始值 作用 类比修仙
currentText string 默认欢迎语 双向绑定 TextArea 的输入文本 丹田(存储灵气)
isSpeaking boolean false 驱动按钮文字和颜色的变化 神识(感知状态)
logText string 空字符串 显示日志信息 识海(记录历程)

@State 装饰器是 ArkTS 的响应式核心。当这些变量的值发生变化时,ArkUI 会自动重新渲染相关组件,无需手动操作 DOM。这就像修士的"天人感应"——身体状态一变化,天地灵气自然响应。

5.3 构建 UI:飞剑的七段剑诀

第一段:剑诀起手——标题
Text('TTS文本转语音演示')
  .fontSize(24)
  .fontWeight(FontWeight.Bold)
  .margin({ top: 20, bottom: 20 })

通过链式调用设置字体大小(24fp)、粗细(加粗)和边距。这是 ArkUI 组件开发的典型风格——声明式、链式、直观。

第二段:剑气凝形——文本输入区
TextArea({ placeholder: '请输入要朗读的文本', text: this.currentText })
  .height(120)
  .width('90%')
  .borderRadius(8)
  .borderColor('#CCCCCC')
  .borderWidth(1)
  .onChange((value: string) => { this.currentText = value; })
  .margin({ bottom: 20 })

TextArea 属性详解

  • placeholder:占位符文本,在输入框为空时显示
  • text:绑定 this.currentText,实现双向数据绑定
  • .onChange():监听文本变化,实时更新状态
  • 圆角、边框、宽高等样式属性

修炼心得:宽度设为 '90%' 而非固定 px,使组件自适应不同屏幕尺寸——这是响应式设计的基本功。

第三段:御剑诀——按钮行
Row() {
  Button(this.isSpeaking ? '停止朗读' : '朗读')
    .onClick(() => {
      if (this.isSpeaking) {
        this.stopSpeaking();
      } else {
        this.speakText();
      }
    })
    .backgroundColor(this.isSpeaking ? '#FF6B6B' : '#40E0D0')
    .fontColor(Color.White)
    .borderRadius(8)
    .width(120)
    .height(40)
    .margin({ right: 10 })

  Button('清空日志')
    .onClick(() => { this.logText = ''; })
    .backgroundColor('#FFA500')
    .fontColor(Color.White)
    .borderRadius(8)
    .width(120)
    .height(40)
}
.margin({ bottom: 20 })

交互设计亮点

  1. 状态驱动的按钮文字:通过三元运算符 this.isSpeaking ? '停止朗读' : '朗读' 动态切换按钮文字,实现"同一个按钮,两种功能"。
  2. 颜色标识
    • 朗读状态 → 红色(#FF6B6B),直观传达"停止"的含义
    • 空闲状态 → 青色(#40E0D0),传达"开始/就绪"的含义
    • 清空日志 → 橙色(#FFA500),传达"操作/提醒"的含义
  3. Row 容器:将两个按钮水平排列,通过 margin({ right: 10 }) 保持间距。
第四段:识海开——日志标题
Text('日志信息')
  .fontSize(16)
  .fontWeight(FontWeight.Medium)
  .alignSelf(ItemAlign.Start)
  .margin({ left: '5%', bottom: 10 })

alignSelf(ItemAlign.Start) 让文本在父容器中左对齐,覆盖父容器 Column 的默认居中对齐。

第五段:显神通——日志内容显示
Text(this.logText)
  .width('90%')
  .height(150)
  .borderRadius(8)
  .borderColor('#CCCCCC')
  .borderWidth(1)
  .padding(10)
  .fontSize(14)
  .maxLines(10)
  .textAlign(TextAlign.Start)

技术细节

  • maxLines(10):限制最多显示 10 行,防止日志过多撑满屏幕
  • textAlign(TextAlign.Start):左对齐文本
  • padding(10):内边距,让文本不紧贴边框
第六段:归元——根容器
.width('100%')
.height('100%')
.padding(20)

Column 容器占据全屏宽高,整体添加 20vp 的内边距,让内容不会贴边。

5.4 剑法招式:交互逻辑

speakText —— 朗读功法
speakText() {
  if (!this.currentText.trim()) {
    this.addLog('朗读失败', '没有可朗读的内容');
    return;
  }
  this.ttsManager.speak(this.currentText);
  this.addLog('开始朗读',
    `开始朗读文本,长度: ${this.currentText.length}字符`);
}

防御性编程:在调用 TTS 之前,先检查文本是否为空(trim() 去除首尾空白),避免空串播报。

stopSpeaking —— 停止功法
stopSpeaking() {
  if (this.isSpeaking) {
    this.ttsManager.stop();
    this.addLog('停止朗读', '已停止朗读');
  }
}

双重检查:外部有 if (this.isSpeaking),即使 UI 状态不同步,也不会误调用。

addLog —— 日志记录
addLog(tag: string, message: string) {
  const time = new Date().toLocaleTimeString();
  this.logText = `[${time}] [${tag}] ${message}\n` + this.logText;
}

设计特点

  • 每条日志包含时间戳、标签和消息
  • 新日志追加到开头(... + this.logText),最新日志始终在最上方
  • 使用 toLocaleTimeString() 获取本地时间格式

5.5 收功归元:页面销毁

aboutToDisappear() {
  this.ttsManager.shutdown();
}

aboutToDisappear 是 ArkTS 的生命周期钩子,类似于 Angular 的 ngOnDestroy 或 Vue 的 onUnmounted。在这里释放 TTS 引擎资源,防止内存泄漏。


第六章 渡劫:错误处理与边界情况

6.1 修仙路上的三大心魔

心魔一:引擎初始化失败

表现:TTS 引擎因网络问题、系统资源不足或用户拒绝权限而创建失败。

应对

textToSpeech.createEngine(params, (err, engine) => {
  if (err || !engine) {
    this.updateLog(`创建TTS引擎失败: ${err?.message}`);
    return;  // 优雅降级
  }
  // ...
});

修炼心得:通过回调中的 err 对象获取详细的错误信息(err.message),记录日志供开发者排查。用户界面则通过 addLog 展示错误,并在后续操作中通过 if (!this.tts) 检查阻止功能调用。

心魔二:空文本播报

表现:用户未输入任何内容就点击"朗读"按钮。

应对

speakText() {
  if (!this.currentText.trim()) {
    this.addLog('朗读失败', '没有可朗读的内容');
    return;
  }
  // ...
}
心魔三:引擎运行时异常

表现speak()stop() 调用时引擎内部抛出异常。

应对

try {
  this.tts.speak(filtered, speakParams);
} catch (e) {
  this.updateLog(`播报失败: ${JSON.stringify(e)}`);
}

6.2 边界情况修炼手册

场景 预期行为 代码保障
快速连击"朗读" 仅播报最新文本 每次 speak() 重置状态,覆盖前一次
播报中快速点"停止"又点"朗读" 正常停止后重新播报 stop() 同步执行后,speak() 重新开始
页面关闭时正在播报 引擎正常关闭 aboutToDisappearshutdown()
输入含大量 Emoji 的文本 自动过滤后播报 filterText() 的 Unicode 正则
网络断连后使用在线模式 引擎创建失败,记录日志 初始化回调中的错误处理
清空日志后立即查看 日志为空 this.logText = '' 直接重置状态

第七章 合体:构建配置深度解析

7.1 项目级构建配置

// build-profile.json5(项目根目录)
{
  "app": {
    "signingConfigs": [],
    "products": [
      {
        "name": "default",
        "signingConfig": "default",
        "targetSdkVersion": "6.1.0(23)",   // 目标 SDK 版本
        "compatibleSdkVersion": "6.1.0(23)",// 兼容 SDK 版本
        "runtimeOS": "HarmonyOS",
        "buildOption": {
          "strictMode": {
            "caseSensitiveCheck": true,
            "useNormalizedOHMUrl": true
          }
        }
      }
    ],
    "buildModeSet": [
      { "name": "debug" },
      { "name": "release" }
    ]
  },
  "modules": [
    {
      "name": "entry",
      "srcPath": "./
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐