Android平台使用VIA创建语音交互应用

科技   2024-09-23 17:37   浙江  

Android平台使用VIA创建语音交互应用

概述

在 Android 平台上开发一款语音助手应用需要整合多种技术,包括语音识别(ASR)、文字转语音(TTS)、以及热词检测(Hotword Detection)。这些技术共同构成了语音助手应用的核心交互方式,使用户能够通过语音命令与设备进行无缝交流。

首先,语音识别(ASR, Automatic Speech Recognition) 是语音助手的基础功能,它将用户的语音转换为文本输入。在 Android 中,语音识别功能可以通过 AOSP 提供的 SpeechRecognizer API 来实现。开发者可以使用该 API 捕捉用户的语音输入,并将其转换为结构化的数据,进而执行相应的命令。ASR 是一个关键的组件,能够理解自然语言并执行复杂指令。

接着,文字转语音(TTS, Text-to-Speech) 则提供了语音助手回应用户的方式。通过 TextToSpeech 类,应用可以将生成的文本以语音形式输出,支持多种语言和个性化设置。TTS 技术用于语音助手提供反馈,播报信息或执行通知,使交互更加人性化和直观。

VoiceInteractor 是 Android 提供的一个接口,用于处理复杂的语音交互请求。它允许应用程序与用户进行更自然的对话,例如多轮交互、确认、选择等操作。通过 VoiceInteractor,开发者可以实现更加智能和复杂的语音命令处理,例如在用户语音输入后提供进一步的选项或请求确认,提升语音助手的交互能力。

此外,热词检测(Hotword Detection) 是语音助手的重要功能之一。热词检测允许设备通过指定的唤醒词(如“Hey Google”)启动语音助手,即使设备处于待机状态。通过 Android 的 HotwordDetector 或其他硬件支持,应用可以始终在线监听用户的唤醒词,实现即时交互。这使得语音助手能够在不显著增加电量消耗的情况下,随时为用户提供服务。

通过结合语音识别、文字转语音和热词检测,Android 语音助手能够实现完整的语音交互流程,为用户提供更自然流畅的使用体验。在构建这类应用时,开发者需要灵活运用 Android 提供的 API 和框架,并确保高效的资源管理与用户隐私的保护。

术语

在本指南中涉及以下术语:

  • • 辅助数据:启动语音交互会话后,系统可以截取当前屏幕和视图的内容,并将这些信息传递给会话。应用可以通过实现 Activity#onProvideAssistData() 和 Activity#onProvideAssistContent() 方法提供更多细节。

  • • 按住开始讲话 (PTT):指实体的语音控制按钮,Auto通常位于方向盘等设备上,手机设备通常会复用电源键或者音量按键,用户按下后可以进行语音指令。

  • • RecognitionService (RS):由应用通过 SpeechRecognizer API 使用的语音识别服务。VIA 必须包含 VoiceInteractionService 和 RecognitionService

  • • 点按后说话 (TTT):软件的语音控制按钮,通常位于系统界面中。在 Android 中,也称为“辅助手势”。

  • • VoiceInteractionService:VIA 开发者实现的轻量级系统服务。系统服务会在设备启动时绑定选定服务,并使其始终处于运行状态。

  • • VoiceInteractionSession (VIS):封装用户交互逻辑的类,显示语音交互状态,并处理 VoiceInteractor 请求,还能接收辅助数据和屏幕截图。

  • • VoiceInteractionSessionService (VSS):VIA 中用于处理语音交互会话的服务。系统在用户语音交互期间会绑定此服务,所有会话逻辑均由 VoiceSession 类实现。系统仅保证此服务在单个用户会话期间活跃。

  • • 语音交互应用 (VIA):提供语音控制功能的 Android 应用,通常称为“助理”。通过在应用清单中声明 VoiceInteractionService 进行标识。系统中每次只能有一个默认的 VIA 应用,它会接收按住开始讲话 (PTT) 和点按后说话 (TTT) 事件,并与系统服务绑定。

职责

下表介绍基于AOSP语音识别框架各方在 Android 设备中的职责划分。

角色责任描述
设备制造商 (OEM)构建与 AOSP 兼容的设备系统。
实现音频输入输出功能,可选择性地添加 DSP 进行启动指令检测支持。
为语音交互服务授予系统特权。
遵守与应用设置屏幕访问权限相关的 VoiceInteractionService 要求。
AOSP定义并优化 VoiceInteractionService 及相关 API。
为 VIA 开发者提供 API 文档、示例代码及其他支持材料。
提供包含要求和建议的用户体验设计指南。
应用开发者实现 VoiceInteractionService API、RecognitionService API 和 NotificationListenerService API。
提供可自定义的用户界面,以便 OEM 能根据不同设备设计进行调整。

该职责分工确保设备、系统服务和应用之间的紧密集成,从而为 Android 通用设备中的语音交互提供更优质的用户体验。

功能要求

一个完整的语音助手App应包含以下功能点:

  • • [Must] 响应由系统处理的语音交互触发器(如按住讲话按钮 PTT、点击讲话按钮 TTT)。

  • • [Must] 直观地显示触发器的状态和进度(例如正在监听、处理或执行)。

  • • [Must] 通过语音或提示音反馈用户请求的理解与处理结果。

  • • [Must] 作为其他应用的语音识别服务提供程序(参见 SpeechRecognizer API)。

  • • [Need] 响应设备启动指令的语音触发。

  • • [Option] 显示“设置”界面,允许用户配置 VIA(如权限管理、启动指令配置、登录等)。

  • • [Option] 处理辅助数据(例如 Intent#ACTION_ASSIST 提供的内容)。

  • • [Option] 支持在锁屏状态下进行语音交互操作。

组件构成

大体上讲,语音交互应用会与以下操作方进行交互:

  • • VoiceInteractionManagerService:该系统服务负责管理默认的语音交互应用(VIA),并将其功能扩展至系统的其他部分。

  • • RecognitionService:为系统中的其他应用提供语音识别功能的服务。

  • • SoundTrigger:用于管理启动指令,VIA 可通过 AlwaysOnHotwordDetector 使用该功能。

  • • MediaRecorder:用于访问音频输入,执行启动指令检测(当 CPU 参与时)和语音识别任务。

  • • PhoneWindowManager/CarInputService:这些服务负责将按住讲话按钮 (PTT) 路由至 VIA,以处理关键事件,此外还承担其他职责。

  • • User:用户通过触发器(PTT、TTT、启动指令)或语音控制面板界面与 VIA 进行交互。

  • • CarService、Notifications、Media、Telephony、ContactsProvider:这些系统服务和应用由 VoiceInteractionSession 用于执行用户的语音指令。

激活与关闭

安装到设备的语音助手默认是不激活的,需要通过默认应用设置来激活或关闭

作者使用的荣耀X50的设备,基于Android13, 设置默认语音助手的步骤设置> 应用> 默认应用> 辅助应用和语音输入> 辅助应用。选择你想要使用的助手应用。

设置完成后,会有屏幕文字及截图权限设置界面,如上图所示。

激活后,Yoyo助理就可以使用了,短按键电源键就你能启动交互界面,后面想要切换其他助手应用,如科大讯飞、天猫精灵等也通过这里设置,如果想要关闭助手功能,可以设置为, 这样所有助手应用进程都会退出。

选定的 VIA 会通过两种方式提供给系统:

  1. 1. 作为 RolesManager 系统服务的一部分提供

  2. 2. 由 VoiceInteractionManagerService 通过 AssistUtils 内部 API 提供。可以使用 RolesManager 和角色名称 android.app.role.ASSISTANT 来获取候选 VIA 列表。

启动会话

启动会话也就是触发语音输入及识别的过程,这里可通过3种方式启动语音交互:

1. 启动指令触发 Android 提供 AlwaysOnHotwordDetector 作为硬件 DSP 之上的一种抽象。这提供了一种便捷的方式,供您将 VoiceInteractionService 与语音模型关联起来,从而实现始终开启的低功耗语音识别。这是最常见、最广为人知的交互流程,在此流程中,用户会请求与语音应用 (VA) 进行交互,以发起新的对话。以这种方式启动的语音会话使用 SHOW_SOURCE_ASSIST_GESTURE flag 进行标识。AlwaysOnHotwordDetector 依赖于启动指令注册、SoundTrigger HAL 和硬件支持。这些可能不是在所有设备上都有。在这种情况下,如果需要支持启动指令检测,这些应用可能需要使用原生库来捕获并处理音频输入流。Android框架提供了HotwordDetectionService来使用原生库方式实现热词唤醒,我们可以在HotwordDetectionService#onDetect方法中实现相关唤醒处理流程。当VoiceInteractionService启动后,我们便可以在该服务下创建HotwordDetector 启动热词探测,对于有DSP芯片支持的设备,我们使用createAlwaysOnHotwordDetector系列接口,对于不支持DSP芯片的设备,我们使用createHotwordDetector,使用AudioRecoder提供的音频数据进行热词识别, 热词探测还要结合KeyphraseModelManager相关接口完成工作。

VoiceInteractionService启动后启动热词探测服务示例代码

```java
package com.android.test.voiceinteraction;

import android.content.Intent;
import android.service.voice.AlwaysOnHotwordDetector;
import android.service.voice.VoiceInteractionService;
import android.util.Log;

import java.util.Locale;

public class MainInteractionService extends VoiceInteractionService {
    private static final String TAG = "MainInteractionService";
    private AlwaysOnHotwordDetector mHotwordDetector;

    // Callback to handle hotword detection events
    private final AlwaysOnHotwordDetector.Callback mHotwordCallback = new AlwaysOnHotwordDetector.Callback() {
        @Override
        public void onAvailabilityChanged(int status) {
            Log.i(TAG, "Hotword availability changed: " + status);
            handleHotwordAvailability(status);
        }

        @Override
        public void onDetected(AlwaysOnHotwordDetector.EventPayload eventPayload) {
            Log.i(TAG, "Hotword detected");
        }

        @Override
        public void onError() {
            Log.i(TAG, "Hotword detection error");
        }

       .......
    };

    @Override
    public void onReady() {
        super.onReady();
        Log.i(TAG, "Service ready. Initializing Hotword Detector.");

        // Create Hotword Detector with specified keyphrase and locale
        mHotwordDetector = createAlwaysOnHotwordDetector(
                "Hello There", Locale.forLanguageTag("en-US"), mHotwordCallback);
    }

    // Handle the hotword availability status
    private void handleHotwordAvailability(int availability) {
        switch (availability) {
           .......
            case AlwaysOnHotwordDetector.STATE_KEYPHRASE_UNENROLLED:
                Log.i(TAG, "Keyphrase not enrolled, prompting for enrollment");
                Intent enrollIntent = mHotwordDetector.createEnrollIntent();
                startActivity(enrollIntent);  // Start enrollment activity
                break;
            case AlwaysOnHotwordDetector.STATE_KEYPHRASE_ENROLLED:
                Log.i(TAG, "Keyphrase enrolled, starting recognition");
                if (mHotwordDetector.startRecognition(AlwaysOnHotwordDetector.RECOGNITION_FLAG_NONE)) {
                    Log.i(TAG, "Hotword recognition started successfully");
                } else {
                    Log.i(TAG, "Failed to start hotword recognition");
                }
                break;
        }
    }
}

代码说明:

  1. 1. 初始化AlwaysOnHotwordDetector:在onReady()中,通过createAlwaysOnHotwordDetector()创建热词探测器,指定了关键字(“Hello There”)和语言(英语)。

  2. 2. 热词探测回调:定义了回调mHotwordCallback来处理热词可用性、探测事件和错误。

  3. 3. 热词可用性处理handleHotwordAvailability()根据探测器的状态执行不同的操作,比如提示用户进行关键字注册或启动热词识别。

  4. 4. 启动识别:当关键字已注册时,尝试启动热词识别并记录结果。

对于使用HotwordDetectionService方式实现的热词探测,特别适用于通过第三方热词探测库实现的助手应用,我们可以在HotwordDetectionService中启动识别引擎,如果热词被识别到,然后通过回调onDetect方法传递过来的Callback将探测结果回调给客户端, 然后客户端便可以启动后续的识别流程。

2. PTT 触发

这适用于长按或短按硬件按钮。在 AAOS 中,PTT 由 CarInputService 处理。在默认实现中,此服务会处理通过车载 HAL 收到的输入事件,并在语音交互这一特殊情境中对关键事件采用以下逻辑:

  • • 短按 PTT 事件 (KeyEvent.KEYCODE_VOICE_ASSIST) 将被定向到 VoiceInteractionManagerService,以启动新的语音会话。

  • • 长按 PTT 事件将首先传递到投射接收器(如 Android Auto 或 CarPlay),然后再传递到已通过蓝牙连接的设备,最后传递到本地 VIA 应用。按照此流程启动的会话使用 SHOW_SOURCE_PUSH_TO_TALK 进行标识。

    PPT触发会话流程

3. “点按后说话”触发(或软件按钮) 这种方式是Android手机、平板等手持设备上常用的触发方式,比如当我使用语音搜索时,我需要先通过按钮触发一个输入交互窗口,然后说话,说完话后系统就开始开始执行语义理解、关键字搜索等后续流程。

权限及分发

权限及分发问题

在开发三方语音助手(VIA)时,权限管理和分发机制至关重要。

  1. 1. 权限管理

  • • 用户无法直接授予特许权限,OEM需将需要的APK预加载到系统映像中,并在构建中明确授予这些权限。

  • • 在 Android.bp 文件中设置依赖项,并在 vendor/…/data/etc/car/ 文件夹中添加特权许可名单。

android_app {
  ...
  required: ["privapp_allowlist_com.example.myvoicecontrol"],
  ...
}
prebuilt_etc {
  name: "privapp_allowlist_com.example.myvoicecontrol",
  sub_dir: "permissions",
  src: "com.example.myvoicecontrol.xml",
  filename_from_src: true,
}
  • • 部分危险权限可预先授予默认的 VoiceInteractionService,而非默认VIA需在首次使用时请求权限。具体权限可在 DefaultPermissionGrantPolicy.java 中查看。可以使用 default-permissions.xml 配置文件来预先授予权限,但需遵循Android兼容性定义文档(CDD)第9节的相关限制。

  1. 1. 分发机制

  • • 预安装的VIA必须位于 /product/priv-apps 或 /vendor/priv-apps 分区。

  • • vendor 分区的应用可能无法访问某些系统API,更新可通过OTA或应用商店进行。

有效管理权限和分发机制能够确保三方语音助手在Android设备上的稳定性和可靠性。

推荐阅读

Android语音识别框架与语音交互概览

在 Android 上实现语音命令识别:详细指南

如何打造车机语音交互:Google Voice Interaction 给你答案

Android 标准语音识别框架:SpeechRecognizer 的封装、调用和原理

直面原理:5 张图彻底了解 Android TextToSpeech 机制

虎哥Lovedroid
Android技术达人 近10年一线开发经验 关注并分享Android、Kotlin新技术,新框架 多年Android底层框架修改经验,对Framework、Server、Binder等架构有深入理解
 最新文章