鸿蒙 Flutter 开发:多模态交互与 AI 语音助手集成实战

在鸿蒙全场景智慧生态中,多模态交互是连接用户与设备的核心纽带,它整合了语音、触控、手势、视觉等多种输入方式,为用户提供自然、高效的交互体验。Flutter 凭借灵活的组件化架构和跨端渲染能力,能够快速构建多模态交互界面;而鸿蒙原生的 AI 语音引擎、手势识别能力,则为多模态交互提供了底层技术支撑。此前我们探讨了鸿蒙 Flutter 的分布式协同、原子化服务、车机适配等技术,本文将聚焦鸿蒙 Flutter 多模态交互开发AI 语音助手集成,通过 “智慧家居控制中心” 完整案例,演示如何融合语音、触控、手势三种交互方式,打造具备智能语音对话、设备手势控制的鸿蒙应用。

一、多模态交互核心原理与鸿蒙 Flutter 融合逻辑

1. 鸿蒙多模态交互核心特性

鸿蒙系统的多模态交互能力基于分布式全场景交互框架,具备三大核心特性:

  • 多输入融合:支持语音、触控、手势、人脸、声纹等多种输入方式,系统可智能识别并融合多源输入指令;
  • 跨设备协同交互:例如用手机语音指令控制智慧屏,用平板手势操作车机应用,交互指令可跨设备流转;
  • 上下文感知:结合用户位置、设备状态、使用习惯,智能理解交互意图(如用户说 “开灯”,系统自动识别当前所处房间的灯光设备);
  • 自然语言理解:内置的鸿蒙 AI 语音引擎支持中文分词、意图识别、实体提取,可直接对接第三方 NLP 服务。

2. Flutter 与多模态交互的融合逻辑

Flutter 作为前端界面框架,与鸿蒙多模态交互能力的融合遵循 “界面承载交互,原生提供能力,数据双向流转” 的核心逻辑,整体架构分为三层:

  1. 鸿蒙原生能力层:提供语音识别 / 合成、手势识别、上下文感知等核心能力,通过AIAbilityGestureService等原生服务对外暴露接口;
  2. 交互适配层:通过MethodChannelEventChannel实现 Flutter 与原生能力的通信,负责指令转换、数据序列化、异常处理,同时管理多模态交互的优先级(如语音指令优先级高于触控指令);
  3. Flutter 交互界面层:构建多模态交互入口(语音按钮、手势识别区域、触控控件),接收并展示原生层的交互结果,同时响应用户的多模态输入操作。

3. 多模态交互指令流转机制

以 “语音控制灯光” 为例,多模态交互指令的完整流转流程如下:

  1. 触发阶段:用户点击 Flutter 界面的语音按钮,或直接唤醒语音助手(如 “小艺小艺”);
  2. 采集阶段:鸿蒙原生语音引擎采集用户语音,进行降噪、端点检测处理;
  3. 识别阶段:语音数据经鸿蒙 AI 引擎转换为文本,再通过 NLP 服务解析出意图(“控制”)和实体(“客厅灯光”、“打开”);
  4. 执行阶段:原生层将解析后的指令发送至智能家居网关,控制对应设备;
  5. 反馈阶段:设备执行结果通过原生层回调至 Flutter 界面,同时语音合成引擎播放反馈语音(“客厅灯光已打开”),完成一次完整的多模态交互闭环。

二、案例:智慧家居控制中心

本案例将实现一款鸿蒙 Flutter 智慧家居控制中心,核心功能包括:

  1. 语音交互:支持语音唤醒、语音控制家电(开关、调节参数)、语音查询设备状态;
  2. 触控交互:通过 Flutter 组件实现家电设备的可视化控制(开关按钮、滑动调节亮度 / 温度);
  3. 手势交互:支持在 Flutter 界面绘制特定手势(如滑动、圆圈)快速控制常用设备;
  4. 多设备联动:控制指令同步至鸿蒙分布式设备网络,支持跨设备控制家电;
  5. 状态反馈:设备状态实时同步至 Flutter 界面,同时通过语音合成反馈执行结果。

前置条件

  1. 已配置鸿蒙 DevEco Studio 4.3 + 与 Flutter 3.24 + 环境,安装ohos_flutter_ai_adapterohos_flutter_gesture_adapter插件;
  2. 已开启鸿蒙系统的 AI 语音引擎权限,获取语音识别 / 合成的应用授权;
  3. 已接入智能家居网关(如鸿蒙智联网关),支持通过 API 控制家电设备;
  4. 已准备至少一台鸿蒙智联设备(如智能灯、智能空调)用于调试。

三、步骤 1:鸿蒙原生层多模态能力封装

鸿蒙原生层负责封装语音识别 / 合成、手势识别、智能家居控制三大核心能力,通过通信通道向 Flutter 层提供标准化接口。

1. 多模态权限配置(module.json5)

entry/src/main/module.json5中配置语音、手势、网络等所需权限:

{
  "module": {
    "reqPermissions": [
      { "name": "ohos.permission.MICROPHONE", "reason": "需要麦克风采集语音", "usedScene": { "abilities": [".MainAbility"], "when": "inuse" } },
      { "name": "ohos.permission.SPEAKER", "reason": "需要扬声器播放语音反馈", "usedScene": { "abilities": [".MainAbility"], "when": "always" } },
      { "name": "ohos.permission.INTERNET", "reason": "需要连接智能家居网关", "usedScene": { "abilities": [".MainAbility"], "when": "always" } },
      { "name": "ohos.permission.GESTURE_RECOGNITION", "reason": "需要识别屏幕手势", "usedScene": { "abilities": [".MainAbility"], "when": "inuse" } }
    ],
    "abilities": [
      {
        "name": ".MainAbility",
        "type": "page",
        "visible": true,
        "metadata": [
          {
            "name": "flutterAbility",
            "value": "true"
          }
        ]
      }
    ]
  }
}

2. 语音能力封装(ArkTS)

基于鸿蒙 AI 语音引擎,实现语音识别(语音转文字)、语音合成(文字转语音)功能:

// service/VoiceService.ts
import speech from '@ohos.speech';
import audio from '@ohos.multimedia.audio';

// 语音识别结果模型
export interface VoiceRecognitionResult {
  text: string; // 识别后的文本
  confidence: number; // 识别置信度(0-1)
}

// 语音合成参数
interface TtsParam {
  text: string;
  volume: number; // 音量(0-10)
  speed: number; // 语速(0-10)
}

export class VoiceService {
  private asrEngine: speech.AsrEngine | null = null; // 语音识别引擎
  private ttsEngine: speech.TtsEngine | null = null; // 语音合成引擎
  private audioPlayer: audio.AudioPlayer | null = null;
  private recognitionCallback?: (result: VoiceRecognitionResult) => void;

  // 初始化语音引擎
  async init() {
    try {
      // 初始化语音识别引擎
      this.asrEngine = await speech.createAsrEngine();
      this.asrEngine.on('recognitionResult', (result) => {
        this.recognitionCallback?.({
          text: result.text,
          confidence: result.confidence
        });
      });

      // 初始化语音合成引擎
      this.ttsEngine = await speech.createTtsEngine();
      this.audioPlayer = await audio.createAudioPlayer();
      console.log('语音引擎初始化成功');
    } catch (e) {
      console.error(`语音引擎初始化失败:${JSON.stringify(e)}`);
    }
  }

  // 开始语音识别
  startRecognition() {
    if (!this.asrEngine) return;
    this.asrEngine.start({
      language: speech.Language.CHINESE,
      scenario: speech.Scenario.FREE_TALK
    });
  }

  // 停止语音识别
  stopRecognition() {
    if (!this.asrEngine) return;
    this.asrEngine.stop();
  }

  // 语音合成(文字转语音)
  async speakText(param: TtsParam) {
    if (!this.ttsEngine || !this.audioPlayer) return;

    const ttsResult = await this.ttsEngine.synthesize({
      text: param.text,
      language: speech.Language.CHINESE,
      volume: param.volume,
      speed: param.speed
    });

    // 播放合成的语音
    await this.audioPlayer.setSource(ttsResult.audioData);
    await this.audioPlayer.prepare();
    await this.audioPlayer.play();
  }

  // 注册语音识别回调
  registerRecognitionCallback(callback: (result: VoiceRecognitionResult) => void) {
    this.recognitionCallback = callback;
  }

  // 释放资源
  destroy() {
    this.asrEngine?.destroy();
    this.ttsEngine?.destroy();
    this.audioPlayer?.release();
  }
}

3. 手势识别封装(ArkTS)

基于鸿蒙手势识别服务,实现屏幕手势(滑动、点击、圆圈)的识别功能:

// service/GestureService.ts
import gesture from '@ohos.gesture';

// 手势类型枚举
export enum GestureType {
  SWIPE_UP = 'swipe_up', // 向上滑动
  SWIPE_DOWN = 'swipe_down', // 向下滑动
  CIRCLE = 'circle', // 画圆圈
  DOUBLE_CLICK = 'double_click' // 双击
}

export class GestureService {
  private gestureRecognizer: gesture.GestureRecognizer | null = null;
  private gestureCallback?: (type: GestureType) => void;

  // 初始化手势识别器
  async init() {
    try {
      this.gestureRecognizer = await gesture.createGestureRecognizer({
        gestureTypes: [
          gesture.GestureType.SWIPE,
          gesture.GestureType.CIRCLE,
          gesture.GestureType.DOUBLE_CLICK
        ]
      });

      // 监听手势识别结果
      this.gestureRecognizer.on('gestureDetected', (gestureInfo) => {
        let gestureType: GestureType;
        switch (gestureInfo.type) {
          case gesture.GestureType.SWIPE:
            gestureType = gestureInfo.direction === gesture.Direction.UP ? GestureType.SWIPE_UP : GestureType.SWIPE_DOWN;
            break;
          case gesture.GestureType.CIRCLE:
            gestureType = GestureType.CIRCLE;
            break;
          case gesture.GestureType.DOUBLE_CLICK:
            gestureType = GestureType.DOUBLE_CLICK;
            break;
          default:
            return;
        }
        this.gestureCallback?.(gestureType);
      });
      console.log('手势识别器初始化成功');
    } catch (e) {
      console.error(`手势识别器初始化失败:${JSON.stringify(e)}`);
    }
  }

  // 启动手势识别
  startRecognize() {
    this.gestureRecognizer?.start();
  }

  // 停止手势识别
  stopRecognize() {
    this.gestureRecognizer?.stop();
  }

  // 注册手势回调
  registerGestureCallback(callback: (type: GestureType) => void) {
    this.gestureCallback = callback;
  }

  // 释放资源
  destroy() {
    this.gestureRecognizer?.destroy();
  }
}

4. 智能家居控制封装(ArkTS)

对接智能家居网关 API,实现设备状态查询、设备控制功能:

// service/SmartHomeService.ts
import http from '@ohos.net.http';

// 智能设备模型
export interface SmartDevice {
  deviceId: string;
  deviceName: string;
  deviceType: string; // light/air/switch
  status: boolean; // 开关状态
  value?: number; // 亮度/温度等参数
}

export class SmartHomeService {
  private httpClient: http.HttpClient | null = null;
  private gatewayUrl: string = 'http://192.168.1.100:8080/api'; // 智能家居网关地址

  constructor() {
    this.httpClient = http.createHttpClient();
  }

  // 获取所有设备列表
  async getDeviceList(): Promise<SmartDevice[]> {
    if (!this.httpClient) return [];

    try {
      const response = await this.httpClient.request(`${this.gatewayUrl}/devices`, http.RequestMethod.GET);
      const result = JSON.parse(response.result.toString());
      return result.data as SmartDevice[];
    } catch (e) {
      console.error(`获取设备列表失败:${JSON.stringify(e)}`);
      return [];
    }
  }

  // 控制设备(开关/调节参数)
  async controlDevice(deviceId: string, status: boolean, value?: number): Promise<boolean> {
    if (!this.httpClient) return false;

    try {
      const body = JSON.stringify({ deviceId, status, value });
      const response = await this.httpClient.request(`${this.gatewayUrl}/control`, http.RequestMethod.POST, {
        header: { 'Content-Type': 'application/json' },
        extraData: body
      });
      const result = JSON.parse(response.result.toString());
      return result.success;
    } catch (e) {
      console.error(`控制设备失败:${JSON.stringify(e)}`);
      return false;
    }
  }

  // 释放资源
  destroy() {
    this.httpClient?.destroy();
  }
}

5. 多模态交互核心调度封装(EntryAbility.ts)

实现多模态能力的统一调度,通过MethodChannelEventChannel与 Flutter 层通信:

// EntryAbility.ts
import Ability from '@ohos.app.ability.UIAbility';
import Window from '@ohos.window';
import { VoiceService, VoiceRecognitionResult } from './service/VoiceService';
import { GestureService, GestureType } from './service/GestureService';
import { SmartHomeService, SmartDevice } from './service/SmartHomeService';
import { MethodChannel, EventChannel } from '@ohos.flutter.engine';

export default class EntryAbility extends Ability {
  private voiceService: VoiceService = new VoiceService();
  private gestureService: GestureService = new GestureService();
  private smartHomeService: SmartHomeService = new SmartHomeService();
  private voiceEventChannel?: EventChannel;
  private gestureEventChannel?: EventChannel;
  private deviceEventChannel?: EventChannel;

  onCreate(want, launchParam) {
    // 初始化所有服务
    Promise.all([
      this.voiceService.init(),
      this.gestureService.init()
    ]).then(() => {
      console.log('多模态服务初始化成功');
      // 监听语音识别结果
      this.voiceService.registerRecognitionCallback((result) => {
        this.voiceEventChannel?.sendEvent(result);
        // 解析语音指令并控制设备
        this.parseVoiceCommand(result.text);
      });

      // 监听手势识别结果
      this.gestureService.registerGestureCallback((type) => {
        this.gestureEventChannel?.sendEvent(type);
        // 解析手势指令并控制设备
        this.parseGestureCommand(type);
      });

      // 定时同步设备状态
      setInterval(() => {
        this.syncDeviceStatus();
      }, 3000);
    });
  }

  onWindowStageCreate(windowStage: Window.WindowStage) {
    const flutterEngine = this.context.flutterEngine;
    if (flutterEngine) {
      // 1. 语音控制MethodChannel(Flutter→原生)
      new MethodChannel(flutterEngine.dartExecutor.binaryMessenger, 'com.smarthome.voice')
        .setMethodCallHandler((call, result) => {
          switch (call.method) {
            case 'startVoiceRecognition':
              this.voiceService.startRecognition();
              result.success(true);
              break;
            case 'stopVoiceRecognition':
              this.voiceService.stopRecognition();
              result.success(true);
              break;
            case 'speakText':
              const text = call.arguments['text'] as string;
              this.voiceService.speakText({ text, volume: 8, speed: 5 });
              result.success(true);
              break;
            default:
              result.notImplemented();
          }
        });

      // 2. 手势控制MethodChannel(Flutter→原生)
      new MethodChannel(flutterEngine.dartExecutor.binaryMessenger, 'com.smarthome.gesture')
        .setMethodCallHandler((call, result) => {
          switch (call.method) {
            case 'startGestureRecognition':
              this.gestureService.startRecognize();
              result.success(true);
              break;
            case 'stopGestureRecognition':
              this.gestureService.stopRecognize();
              result.success(true);
              break;
            default:
              result.notImplemented();
          }
        });

      // 3. 设备控制MethodChannel(Flutter→原生)
      new MethodChannel(flutterEngine.dartExecutor.binaryMessenger, 'com.smarthome.device')
        .setMethodCallHandler((call, result) => {
          switch (call.method) {
            case 'controlDevice':
              const deviceId = call.arguments['deviceId'] as string;
              const status = call.arguments['status'] as boolean;
              const value = call.arguments['value'] as number | undefined;
              this.smartHomeService.controlDevice(deviceId, status, value).then(success => {
                result.success(success);
              });
              break;
            default:
              result.notImplemented();
          }
        });

      // 4. 语音识别结果EventChannel(原生→Flutter)
      this.voiceEventChannel = new EventChannel(flutterEngine.dartExecutor.binaryMessenger, 'com.smarthome.voice.result');
      this.voiceEventChannel.setStreamHandler({
        onListen: (_, __) => {},
        onCancel: () => {}
      });

      // 5. 手势识别结果EventChannel(原生→Flutter)
      this.gestureEventChannel = new EventChannel(flutterEngine.dartExecutor.binaryMessenger, 'com.smarthome.gesture.result');
      this.gestureEventChannel.setStreamHandler({
        onListen: (_, __) => {},
        onCancel: () => {}
      });

      // 6. 设备状态EventChannel(原生→Flutter)
      this.deviceEventChannel = new EventChannel(flutterEngine.dartExecutor.binaryMessenger, 'com.smarthome.device.status');
      this.deviceEventChannel.setStreamHandler({
        onListen: async (_, eventSink) => {
          const devices = await this.smartHomeService.getDeviceList();
          eventSink.success(devices);
        },
        onCancel: () => {}
      });
    }

    windowStage.loadContent('flutter://entrypoint/default').then(() => {
      windowStage.getMainWindow().then(window => {
        window.setFullScreen(false);
      });
    });
  }

  // 解析语音指令
  private async parseVoiceCommand(text: string) {
    if (text.includes('打开') && text.includes('灯')) {
      const devices = await this.smartHomeService.getDeviceList();
      const light = devices.find(d => d.deviceType === 'light');
      if (light) {
        await this.smartHomeService.controlDevice(light.deviceId, true);
        this.voiceService.speakText({ text: `已为你打开${light.deviceName}`, volume: 8, speed: 5 });
      }
    } else if (text.includes('关闭') && text.includes('灯')) {
      const devices = await this.smartHomeService.getDeviceList();
      const light = devices.find(d => d.deviceType === 'light');
      if (light) {
        await this.smartHomeService.controlDevice(light.deviceId, false);
        this.voiceService.speakText({ text: `已为你关闭${light.deviceName}`, volume: 8, speed: 5 });
      }
    }
  }

  // 解析手势指令
  private async parseGestureCommand(type: GestureType) {
    const devices = await this.smartHomeService.getDeviceList();
    const light = devices.find(d => d.deviceType === 'light');
    if (!light) return;

    switch (type) {
      case GestureType.SWIPE_UP:
        await this.smartHomeService.controlDevice(light.deviceId, true, 100);
        this.voiceService.speakText({ text: '灯光已调至最亮', volume: 8, speed: 5 });
        break;
      case GestureType.SWIPE_DOWN:
        await this.smartHomeService.controlDevice(light.deviceId, true, 20);
        this.voiceService.speakText({ text: '灯光已调至最暗', volume: 8, speed: 5 });
        break;
      case GestureType.CIRCLE:
        await this.smartHomeService.controlDevice(light.deviceId, !light.status);
        this.voiceService.speakText({ text: light.status ? '灯光已关闭' : '灯光已打开', volume: 8, speed: 5 });
        break;
    }
  }

  // 同步设备状态
  private async syncDeviceStatus() {
    const devices = await this.smartHomeService.getDeviceList();
    this.deviceEventChannel?.sendEvent(devices);
  }

  onDestroy() {
    this.voiceService.destroy();
    this.gestureService.destroy();
    this.smartHomeService.destroy();
  }
}

四、步骤 2:Flutter 层多模态交互界面与业务逻辑实现

Flutter 层负责构建多模态交互入口,接收并展示原生层的交互结果,实现触控、语音、手势的一体化控制界面。

1. 多模态服务工具类封装(Dart)

封装与原生通信的接口,提供语音控制、手势控制、设备控制的简洁 API:

// lib/services/smarthome_service.dart
import 'package:flutter/services.dart';

// 语音识别结果模型
class VoiceRecognitionResult {
  final String text;
  final double confidence;

  VoiceRecognitionResult({required this.text, required this.confidence});

  factory VoiceRecognitionResult.fromJson(Map<String, dynamic> json) {
    return VoiceRecognitionResult(
      text: json['text'] as String,
      confidence: (json['confidence'] as num).toDouble(),
    );
  }
}

// 手势类型枚举
enum GestureType {
  swipeUp,
  swipeDown,
  circle,
  doubleClick,
  unknown,
}

// 智能设备模型
class SmartDevice {
  final String deviceId;
  final String deviceName;
  final String deviceType;
  final bool status;
  final int? value;

  SmartDevice({
    required this.deviceId,
    required this.deviceName,
    required this.deviceType,
    required this.status,
    this.value,
  });

  factory SmartDevice.fromJson(Map<String, dynamic> json) {
    return SmartDevice(
      deviceId: json['deviceId'] as String,
      deviceName: json['deviceName'] as String,
      deviceType: json['deviceType'] as String,
      status: json['status'] as bool,
      value: json['value'] as int?,
    );
  }
}

// 智慧家居多模态服务工具类
class SmartHomeService {
  // 通信通道
  static const _voiceChannel = MethodChannel('com.smarthome.voice');
  static const _gestureChannel = MethodChannel('com.smarthome.gesture');
  static const _deviceChannel = MethodChannel('com.smarthome.device');
  static const _voiceResultChannel = EventChannel('com.smarthome.voice.result');
  static const _gestureResultChannel = EventChannel('com.smarthome.gesture.result');
  static const _deviceStatusChannel = EventChannel('com.smarthome.device.status');

  // 语音识别相关方法
  static Future<bool> startVoiceRecognition() async {
    return await _voiceChannel.invokeMethod('startVoiceRecognition');
  }

  static Future<bool> stopVoiceRecognition() async {
    return await _voiceChannel.invokeMethod('stopVoiceRecognition');
  }

  static Future<bool> speakText(String text) async {
    return await _voiceChannel.invokeMethod('speakText', {'text': text});
  }

  // 手势识别相关方法
  static Future<bool> startGestureRecognition() async {
    return await _gestureChannel.invokeMethod('startGestureRecognition');
  }

  static Future<bool> stopGestureRecognition() async {
    return await _gestureChannel.invokeMethod('stopGestureRecognition');
  }

  // 设备控制相关方法
  static Future<bool> controlDevice(String deviceId, bool status, [int? value]) async {
    return await _deviceChannel.invokeMethod('controlDevice', {
      'deviceId': deviceId,
      'status': status,
      'value': value,
    });
  }

  // 监听语音识别结果
  static Stream<VoiceRecognitionResult> get voiceResultStream {
    return _voiceResultChannel.receiveBroadcastStream().map((data) {
      return VoiceRecognitionResult.fromJson(Map<String, dynamic>.from(data as Map));
    });
  }

  // 监听手势识别结果
  static Stream<GestureType> get gestureResultStream {
    return _gestureResultChannel.receiveBroadcastStream().map((data) {
      switch (data as String) {
        case 'swipe_up':
          return GestureType.swipeUp;
        case 'swipe_down':
          return GestureType.swipeDown;
        case 'circle':
          return GestureType.circle;
        case 'double_click':
          return GestureType.doubleClick;
        default:
          return GestureType.unknown;
      }
    });
  }

  // 监听设备状态变化
  static Stream<List<SmartDevice>> get deviceStatusStream {
    return _deviceStatusChannel.receiveBroadcastStream().map((data) {
      final List<dynamic> list = data as List;
      return list.map((e) => SmartDevice.fromJson(Map<String, dynamic>.from(e as Map))).toList();
    });
  }
}

2. 多模态交互主界面实现(Dart)

构建集成语音按钮、手势识别区域、设备控制卡片的一体化界面,支持三种交互方式控制智能家居:

// lib/main.dart
import 'package:flutter/material.dart';
import 'services/smarthome_service.dart';

void main() {
  runApp(const SmartHomeApp());
}

class SmartHomeApp extends StatelessWidget {
  const SmartHomeApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '鸿蒙Flutter智慧家居控制中心',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: const SmartHomeControlPage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class SmartHomeControlPage extends StatefulWidget {
  const SmartHomeControlPage({super.key});

  @override
  State<SmartHomeControlPage> createState() => _SmartHomeControlPageState();
}

class _SmartHomeControlPageState extends State<SmartHomeControlPage> {
  List<SmartDevice> _deviceList = [];
  String _voiceText = '点击麦克风开始语音控制';
  String _gestureText = '在下方区域绘制手势';
  bool _isVoiceListening = false;
  bool _isGestureListening = true;

  @override
  void initState() {
    super.initState();
    // 监听设备状态
    SmartHomeService.deviceStatusStream.listen((devices) {
      setState(() => _deviceList = devices);
    });

    // 监听语音识别结果
    SmartHomeService.voiceResultStream.listen((result) {
      setState(() {
        _voiceText = result.text;
        _isVoiceListening = false;
      });
    });

    // 监听手势识别结果
    SmartHomeService.gestureResultStream.listen((type) {
      setState(() {
        switch (type) {
          case GestureType.swipeUp:
            _gestureText = '手势:向上滑动';
            break;
          case GestureType.swipeDown:
            _gestureText = '手势:向下滑动';
            break;
          case GestureType.circle:
            _gestureText = '手势:画圆圈';
            break;
          case GestureType.doubleClick:
            _gestureText = '手势:双击';
            break;
          default:
            _gestureText = '未知手势';
        }
      });
    });

    // 启动手势识别
    SmartHomeService.startGestureRecognition();
  }

  // 切换语音识别状态
  void _toggleVoiceRecognition() async {
    if (_isVoiceListening) {
      await SmartHomeService.stopVoiceRecognition();
      setState(() => _isVoiceListening = false);
    } else {
      await SmartHomeService.startVoiceRecognition();
      setState(() {
        _isVoiceListening = true;
        _voiceText = '正在倾听...';
      });
    }
  }

  // 切换手势识别状态
  void _toggleGestureRecognition() async {
    _isGestureListening = !_isGestureListening;
    setState(() {
      _gestureText = _isGestureListening ? '在下方区域绘制手势' : '手势识别已关闭';
    });

    if (_isGestureListening) {
      await SmartHomeService.startGestureRecognition();
    } else {
      await SmartHomeService.stopGestureRecognition();
    }
  }

  // 控制设备开关
  void _controlDevice(SmartDevice device) async {
    await SmartHomeService.controlDevice(device.deviceId, !device.status);
    await SmartHomeService.speakText('${device.deviceName}已${!device.status ? '打开' : '关闭'}');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('智慧家居控制中心'),
        centerTitle: true,
      ),
      body: Column(
        children: [
          // 语音控制区域
          Container(
            margin: const EdgeInsets.all(16),
            padding: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              border: Border.all(color: Colors.blue),
              borderRadius: BorderRadius.circular(12),
            ),
            child: Column(
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    const Text('语音控制', style: TextStyle(fontSize: 18)),
                    IconButton(
                      icon: Icon(
                        _isVoiceListening ? Icons.mic : Icons.mic_none,
                        size: 32,
                        color: _isVoiceListening ? Colors.red : Colors.blue,
                      ),
                      onPressed: _toggleVoiceRecognition,
                    ),
                  ],
                ),
                const SizedBox(height: 8),
                Text(_voiceText, style: const TextStyle(fontSize: 16)),
              ],
            ),
          ),

          // 设备控制卡片列表
          Expanded(
            child: _deviceList.isEmpty
                ? const Center(child: Text('暂无设备在线'))
                : GridView.builder(
                    padding: const EdgeInsets.symmetric(horizontal: 16),
                    gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 2,
                      childAspectRatio: 1.2,
                      crossAxisSpacing: 16,
                      mainAxisSpacing: 16,
                    ),
                    itemCount: _deviceList.length,
                    itemBuilder: (context, index) {
                      final device = _deviceList[index];
                      return Card(
                        elevation: 4,
                        child: InkWell(
                          onTap: () => _controlDevice(device),
                          child: Padding(
                            padding: const EdgeInsets.all(16),
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: [
                                Icon(
                                  device.deviceType == 'light' ? Icons.lightbulb : Icons.ac_unit,
                                  size: 48,
                                  color: device.status ? Colors.yellow : Colors.grey,
                                ),
                                const SizedBox(height: 12),
                                Text(
                                  device.deviceName,
                                  style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                                ),
                                const SizedBox(height: 8),
                                Text(
                                  device.status ? '已开启' : '已关闭',
                                  style: TextStyle(
                                    color: device.status ? Colors.green : Colors.red,
                                    fontSize: 16,
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ),
                      );
                    },
                  ),
          ),

          // 手势识别区域
          Container(
            margin: const EdgeInsets.all(16),
            padding: const EdgeInsets.all(16),
            height: 120,
            decoration: BoxDecoration(
              color: Colors.grey[100],
              border: Border.all(color: Colors.blue),
              borderRadius: BorderRadius.circular(12),
            ),
            child: Column(
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    const Text('手势控制', style: TextStyle(fontSize: 18)),
                    Switch(
                      value: _isGestureListening,
                      onChanged: (value) => _toggleGestureRecognition(),
                    ),
                  ],
                ),
                const SizedBox(height: 8),
                Text(_gestureText, style: const TextStyle(fontSize: 16)),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

五、多模态交互核心优化与体验提升

1. 交互优先级优化

  • 语音指令优先:当语音识别与触控操作同时触发时,优先执行语音指令,并暂停触控响应,避免指令冲突;
  • 手势指令防抖:添加 300ms 防抖处理,防止误触手势被识别为有效指令;
  • 设备状态反馈实时性:通过定时轮询 + 事件回调结合的方式,确保设备状态同步延迟≤300ms。

2. 语音交互体验优化

  • 语音唤醒词定制:支持用户自定义语音唤醒词(如 “回家模式”),一键触发多设备联动;
  • 离线语音识别:集成鸿蒙离线语音包,无网络时仍可识别常用指令(如 “开灯”、“关灯”);
  • 语音合成音色选择:支持切换不同音色(男声 / 女声 / 童声),提升反馈体验。

3. 手势交互体验优化

  • 手势自定义:允许用户自定义手势与设备指令的映射关系(如画 “√” 代表打开空调);
  • 手势轨迹可视化:在 Flutter 界面实时显示用户绘制的手势轨迹,增强交互反馈;
  • 手势识别容错:支持一定程度的手势轨迹偏差,提升识别成功率。

六、扩展场景与进阶建议

  1. 多模态融合交互:实现 “语音 + 手势” 组合指令(如语音说 “调节灯光”+ 手势滑动调节亮度);
  2. 用户意图理解优化:接入鸿蒙 NLP 服务,提升长句、复杂指令的解析能力(如 “打开客厅的灯并将亮度调至 50%”);
  3. 跨设备交互流转:支持在手机上触发语音指令,在智慧屏上显示执行结果,实现交互跨设备流转;
  4. 个性化场景模式:支持创建 “起床模式”“睡眠模式” 等场景,一键触发多设备联动;
  5. 声纹识别认证:集成鸿蒙声纹识别能力,实现个性化指令(如 “我的空调” 仅识别主人语音)。

七、总结

本文通过智慧家居控制中心案例,完整演示了鸿蒙 Flutter 多模态交互开发与 AI 语音助手集成的流程。核心在于将鸿蒙原生的语音、手势识别能力作为底层支撑,通过通信通道与 Flutter 界面深度融合,实现了 “语音 + 触控 + 手势” 三位一体的多模态交互体验。

在鸿蒙全场景生态中,多模态交互是提升用户体验的关键技术,而 Flutter 作为跨端开发框架,能够快速适配不同设备的交互界面。开发者可基于本文思路,进一步探索智能车载、智慧办公、智慧医疗等更多多模态交互场景,打造符合鸿蒙生态标准的高品质应用。

欢迎大家加入[开源鸿蒙跨平台开发者社区](https://openharmonycrossplatform.csdn.net),一起共建开源鸿蒙跨平台生态。

Logo

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

更多推荐