Desarrollo de apps

Para implementar una aplicación de interacción de voz (VIA), debes completar estos pasos:

  1. Crea un esqueleto mediante el VIA.
  2. Implementa un flujo de configuración o acceso (opcional).
  3. Implementa una pantalla de configuración (opcional).
  4. Declara los permisos necesarios en el archivo de manifiesto.
  5. Implementa una IU de placa de voz.
  6. Implementar el reconocimiento de voz (debe incluir la implementación de la API de RecognitionService).
  7. Implementa una declaración (de forma opcional, puedes implementar la API de TextToSpeech).
  8. Implementar la entrega de comandos Ver este contenido en Cómo entregar comandos.

En las siguientes secciones, se describe cómo completar cada paso mencionado anteriormente.

Crea un esqueleto mediante VIA

Manifiestos

Una app se detecta como una con interacción de voz cuando se cumple lo siguiente: incluido en el manifiesto:

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myvoicecontrol">
    ...

  <application ... >
    <service android:name=".MyInteractionService"
        android:label="@string/app_name"
        android:permission="android.permission.BIND_VOICE_INTERACTION"
        android:process=":interactor">
      <meta-data
          android:name="android.voice_interaction"
          android:resource="@xml/interaction_service" />
      <intent-filter>
        <action android:name=
          "android.service.voice.VoiceInteractionService" />
      </intent-filter>
    </service>
  </application>
</manifest>

En este ejemplo:

  • Los VIA deben exponer un servicio que extienda VoiceInteractionService, con un filtro de intents para la acción VoiceInteractionService.SERVICE_INTERFACE ("android.service.voice.VoiceInteractionService")
  • Este servicio debe tener el permiso de firma del sistema BIND_VOICE_INTERACTION.
  • Este servicio debe incluir un archivo de metadatos android.voice_interaction contenga lo siguiente:

    res/xml/interaction_service.xml

    <voice-interaction-service
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:sessionService=
          "com.example.MyInteractionSessionService"
        android:recognitionService=
          "com.example.MyRecognitionService"
        android:settingsActivity=
          "com.example.MySettingsActivity"
        android:supportsAssist="true"
        android:supportsLaunchVoiceAssistFromKeyguard="true"
        android:supportsLocalInteraction="true" />
    

Para obtener detalles sobre cada campo, consulta R.styleable#VoiceInteractionService. Dado que todas las VIA también son servicios de reconocimiento de voz, también debe incluye lo siguiente en tu manifiesto:

AndroidManifest.xml

<manifest ...>
  <uses-permission android:name="android.permission.RECORD_AUDIO"/>
  <application ...>
    ...
    <service android:name=".RecognitionService" ...>
      <intent-filter>
        <action android:name="android.speech.RecognitionService" />
        <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
      <meta-data
        android:name="android.speech"
        android:resource="@xml/recognition_service" />
    </service>
  </application>
</manifest>

Los servicios de reconocimiento de voz también requieren los siguientes metadatos:

res/xml/recognition_service.xml

<recognition-service
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:settingsActivity="com.example.MyRecognizerSettingsActivity" />

VoiceInteractionService, VoiceInteractionSessionService y VoiceInteractionSession

En el siguiente diagrama, se muestra el ciclo de vida de cada una de estas entidades:

Lifecycles

Figura 1: Lifecycles

Como se indicó antes, VoiceInteractionService es el punto de entrada a un VIA. Las responsabilidades principales de este servicio son las siguientes:

  • Inicializa cualquier proceso que se deba mantener en ejecución por el tiempo que esta VIA es la activa. Por ejemplo, la detección de palabras clave.
  • Informa las acciones de voz compatibles (consulta Presionar para leer del Asistente de voz).
  • Permite iniciar sesiones de interacción por voz desde la pantalla de bloqueo (bloqueo de teclado).

En su forma más sencilla, una implementación de VoiceInteractionService se vería así:

public class MyVoiceInteractionService extends VoiceInteractionService {
    private static final List<String> SUPPORTED_VOICE_ACTIONS =
        Arrays.asList(
            CarVoiceInteractionSession.VOICE_ACTION_READ_NOTIFICATION,
            CarVoiceInteractionSession.VOICE_ACTION_REPLY_NOTIFICATION,
            CarVoiceInteractionSession.VOICE_ACTION_HANDLE_EXCEPTION
    );

    @Override
    public void onReady() {
        super.onReady();
        // TODO: Setup hotword detector
    }

    @NonNull
    @Override
    public Set<String> onGetSupportedVoiceActions(
            @NonNull Set<String> voiceActions) {
        Set<String> result = new HashSet<>(voiceActions);
        result.retainAll(SUPPORTED_VOICE_ACTIONS);
        return result;
    }
    ...
}

La implementación de VoiceInteractionService#onGetSupportedVoiceActions() es necesario para manejar Presionar para leer de Asistente de voz El sistema usa un VoiceInteractionSessionService para crear y interactuar con una VoiceInteractionSession. Solo tiene una responsabilidad, iniciar sesiones nuevas cuando se solicite.

public class MyVoiceInteractionSessionService extends VoiceInteractionSessionService {
    @Override
    public VoiceInteractionSession onNewSession(Bundle args) {
        return new MyVoiceInteractionSession(this);
    }
}

Por último, en una VoiceInteractionSession es donde la mayor parte del trabajo se realizaría. Una única instancia de sesión puede reutilizarse para completar varias interacciones del usuario. En AAOS, existe un CarVoiceInteractionSession auxiliar, para implementar algunas de las funcionalidades únicas de la industria automotriz.

public class MyVoiceInteractionSession extends CarVoiceInteractionSession {

    public InteractionSession(Context context) {
        super(context);
    }

    @Override
    protected void onShow(String action, Bundle args, int showFlags) {
        closeSystemDialogs();
        // TODO: Unhide UI and update UI state
        // TODO: Start processing audio input
    }
    ...
}

VoiceInteractionSession tiene un gran conjunto de métodos de devolución de llamada que son que se explican en las siguientes secciones. consulta la documentación de VoiceInteractionSession para obtener una lista completa.

Implementar un flujo de configuración/acceso

Pueden realizarse la configuración y el acceso:

  • Durante la integración del dispositivo (asistente de configuración).
  • Durante el cambio de servicio de interacción por voz (Configuración).
  • Cuando se selecciona la app por primera vez,

Para obtener detalles sobre la experiencia del usuario recomendada y la orientación visual, consulta Asistentes precargados: Guía de UX.

Configuración durante el cambio del servicio de voz

Siempre es posible que el usuario seleccione un VIA que no ha sido configurado. Esto puede suceder por los siguientes motivos:

  • El usuario omitió el asistente de configuración por completo o la voz de configuración de interacción.
  • El usuario seleccionó un VIA diferente del que se configuró durante el dispositivo. durante el proceso de incorporación.

En cualquier caso, un VoiceInteractionService tiene varias formas de incentivar al usuario para completar la configuración:

  • Recordatorio de notificación.
  • Es la respuesta de voz automática cuando el usuario intenta usarla.

Nota: No se recomienda presentar un flujo de configuración mediante VIA. sin una solicitud explícita del usuario. Esto significa que las VIA deben evitar automáticamente mostrar contenido en el HU durante el inicio del dispositivo o como resultado de un cambio de usuario desbloquear.

Recordatorio de notificación

Una notificación de recordatorio es una forma no invasiva de indicar la necesidad de la configuración. y brindarles a los usuarios una indicación visual para navegar a la configuración del Asistente de tu flujo de trabajo.

Recordatorio de notificación

Figura 2: Recordatorio de notificación

Este flujo funcionaría de la siguiente manera:

Flujo de recordatorios de notificaciones

Figura 3: Flujo de recordatorios de notificaciones

Respuesta de voz

Este es el flujo más simple de implementar, iniciar una declaración en Una devolución de llamada VoiceInteractionSession#onShow(), en la que se le explica al usuario debe realizarse y, luego, preguntarles (si se permite la configuración dado el estado de restricción de UX) si desea iniciar el flujo de configuración. Si no es posible realizar la configuración en ese momento, explica lo siguiente: en tu situación actual.

Configurar en el primer uso

Siempre es posible que el usuario active un VIA que no ha sido configurado. En esos casos:

  1. Informa verbalmente al usuario sobre esta situación (por ejemplo, "Para trabajar correctamente, Necesitamos que completes algunos pasos ... ").
  2. Si el motor de restricciones de UX lo permite (consulta UX_RESTRICTIONS_NO_SETUP), pregúntale al usuario si quiere iniciar la y, luego, abre la pantalla de Configuración del VIA.
  3. De lo contrario (por ejemplo, si el usuario está conduciendo), deja una notificación para que el usuario haz clic en la opción cuando sea seguro hacerlo.

Cómo crear pantallas de configuración de interacción de voz

Las pantallas de acceso y configuración deben desarrollarse como actividades habituales. Consulta la lineamientos visuales y de UX para el desarrollo de IU en Asistentes precargados: Guía de UX.

Lineamientos generales:

  • Las Innovaciones deben permitir a los usuarios interrumpir y reanudar la configuración en cualquier momento.
  • No se debe permitir la configuración si la restricción UX_RESTRICTIONS_NO_SETUP está activa. Para obtener más información, consulta Lineamientos sobre distracción del conductor.
  • Las pantallas de configuración deben coincidir con el sistema de diseño de cada vehículo. Pantalla general el diseño, los iconos, los colores y otros aspectos deben ser coherentes con el resto de la interfaz de usuario. Consulta Personalización para conocer los detalles.

Cómo implementar una pantalla de configuración

Integración de la configuración

Figura 4: Integración de la configuración

Las pantallas de configuración son actividades habituales de Android. Si se implementa, su punto de entrada se debe declarar en el res/xml/interaction_service.xml como parte del VIA manifiestos (consulta Manifiestos). La sección Configuración es un buen lugar para continuar con la configuración y el acceso (si el usuario no la completó o bien, ofrece la opción de salir o cambiar de usuario, de ser necesario. Similar a la configuración pantallas descritas anteriormente, estas pantallas deben:

  • Ofrecer la opción de volver a la pantalla anterior en la pila de pantallas (por ejemplo, a la Configuración del vehículo).
  • No se permite mientras se conduce. Para obtener más información, consulta los Lineamientos sobre distracciones del conductor.
  • Haz coincidir cada sistema de diseño de vehículo. Para obtener más información, consulta Personalización.

Declara los permisos necesarios en el archivo de manifiesto

Los permisos que se requieren en un VIA se pueden dividir en tres categorías:

  • Permisos de firma del sistema. Estos son permisos Solo se otorga a APK preinstalados y firmados por el sistema. Los usuarios no pueden otorgar estos permisos, solo los OEM pueden otorgarlos cuando compilan las imágenes del sistema. Para obtener más información sobre cómo obtener permisos de firma, consulta Cómo otorgar permisos privilegiados del sistema.
  • Permisos peligrosos. Estos son los permisos que un usuario debe otorgar con el diálogo PermissionsController. Los OEM pueden otorgar previamente algunos de estos permisos para el VoiceInteractionService predeterminado. Sin embargo, como esta configuración pueden cambiar de un dispositivo a otro, las apps deberían poder solicitar estas permisos cuando sea necesario.
  • Otros permisos. Estos son todos los demás permisos que no requieren la intervención del usuario. Estos permisos se otorgan automáticamente por el sistema.

Dado lo anterior, la siguiente sección se enfoca solo en solicitar permisos peligrosos. Solo se deben solicitar permisos mientras el usuario esté en las pantallas de acceso o configuración.

Si la aplicación no tiene los permisos necesarios para funcionar, el de flujo recomendado es utilizar una expresión oral para explicarle la situación al usuario y una notificación para proporcionar una indicación visual que el usuario puede usar para vuelve a las pantallas de configuración de VIA. Para obtener más información, consulta 1. Recordatorio de notificación.

Solicita permisos como parte de la pantalla de configuración

Los permisos peligrosos se solicitan con el método normal ActivityCompat#requestPermission() (o equivalente). Para obtener detalles sobre cómo solicitar permisos, consulta Solicita permisos de la app.

Solicita permisos

Figura 5: Solicita permisos

Permiso de objeto de escucha de notificaciones

Para implementar el flujo del TTR, los VAI deben designarse como objeto de escucha de notificaciones. Este no es un permiso propiamente dicho, predeterminada que permite que el sistema envíe notificaciones a objetos de escucha. Para saber si se otorgó acceso a esta información a la VIA, haz lo siguiente: las apps pueden hacer lo siguiente:

Si este acceso no se otorga previamente, el VIA debe dirigir al usuario al Sección de acceso a notificaciones de la configuración del vehículo, con una combinación de declaraciones y notificaciones. Puedes usar el siguiente código para abrir la sección correspondiente de la App de Configuración:

private void requestNotificationListenerAccess() {
    Intent intent = new Intent(Settings
        .ACTION_NOTIFICATION_LISTENER_SETTINGS);
    intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
    startActivity(intent);
}

Cómo implementar una IU de placa de voz

Cuando un objeto VoiceInteractionSession recibe una devolución de llamada onShow(), ocurre lo siguiente: puede presentar una IU de placa de voz. Para conocer los lineamientos visuales y de UX sobre la implementación de placas de voz,consulta Asistentes precargados: Guía de UX.

Cómo visualizar la placa de voz

Figura 6: Cómo visualizar la placa de voz

Hay dos opciones para implementar esta IU:

  • Anular VoiceInteractionSession#onCreateContentView()
  • Cómo iniciar una actividad con VoiceInteractionSession#startAssistantActivity()

Cómo usar onCreateContentView()

Esta es la forma predeterminada de presentar una placa de voz. El VoiceInteractionSession crea una ventana y administra su ciclo de vida durante el tiempo que una voz la sesión está activa. Las apps deben anular VoiceInteractionSession#onCreateContentView() y devolverá una vista que se adjunta a esa ventana en cuanto la sesión se crear. Inicialmente, esta vista debería ser invisible. Cuando comienza una interacción de voz, esta vista debería mostrarse el VoiceInteractionSession#onShow() y, luego, invisible de nuevo el VoiceInteractionSession#onHide().

public class MyVoiceInteractionSession extends CarVoiceInteractionSession {
    private View mVoicePlate;
    …

    @Override
    public View onCreateContentView() {
        mVoicePlate = inflater.inflate(R.layout.voice_plate, null);
        …
   }

    @Override
    protected void onShow(String action, Bundle args, int showFlags) {
        // TODO: Update UI state to "listening"
        mVoicePlate.setVisibility(View.VISIBLE);
    }

    @Override
    public void onHide() {
        mVoicePlate.setVisibility(View.GONE);
    }
    …
}

Cuando uses este método, te recomendamos ajustar VoiceInteractionSession#onComputeInsets(). para tener en cuenta las regiones oscuras de la IU.

Cómo usar startAssistantActivity()

En este caso, VoiceInteractionSession delegará el control de la voz IU de placa a una actividad normal. Cuando se usa esta opción, se muestra un VoiceInteractionSession implementación debe inhabilitar la creación de su ventana de contenido predeterminada (consulta Cómo usar onCreateContentView()) en onPrepareShow() devolución de llamada. A las VoiceInteractionSession#onShow(), se iniciará la sesión con la voz actividad de la placa con VoiceInteractionSession#startAssistantActivity(). Esta inicia la IU con la configuración de la ventana y las marcas de actividad adecuadas.

public class MyVoiceInteractionSession extends CarVoiceInteractionSession {
    …

    @Override
    public void onPrepareShow(Bundle args, int showFlags) {
        super.onPrepareShow(args, showFlags);
        setUiEnabled(false);
    }

    @Override
    protected void onShow(String action, Bundle args, int showFlags) {
        closeSystemDialogs();
        Intent intent = new Intent(getContext(), VoicePlateActivity.class);
        intent.putExtra(VoicePlateActivity.EXTRA_ACTION, action);
        intent.putExtra(VoicePlateActivity.EXTRA_ARGS, args);
        startAssistantActivity(intent);
    }

    …
}

Para mantener una comunicación entre esta actividad y el VoiceInteractionSession, un conjunto de intents internos o vinculación de servicios como en los productos necesarios. Por ejemplo, cuando se invoca VoiceInteractionSession#onHide(), el debe poder pasar esta solicitud a la actividad.

Importante. En Automotive, solo se admiten las anotaciones especiales actividades o actividades enumeradas en la "lista de actividades permitidas" de UXR se pueden mostrar mientras conducir. Esto se aplica a las actividades iniciadas con VoiceInteractionSession#startAssistantActivity(). Recuerda anota tu actividad con <meta-data android:name="distractionOptimized" android:value="true"/> o incluye esto Actividad en la clave systemActivityWhitelist de /packages/services/Car/service/res/values/config.xml . Para obtener más información, consulta Controlador Lineamientos de distracción

Implementa el reconocimiento de voz

En esta sección, aprenderás a implementar el reconocimiento de voz mediante la detección y el reconocimiento de palabras clave. Una palabra clave es una palabra de activación que se usa para iniciar una búsqueda nueva o acción por voz. Por ejemplo, "Hey Google" o "Hey Google".

Detección de palabra clave de DSP

Android proporciona acceso a un detector de palabras clave siempre activo a nivel de la DSP los medios de AlwaysOnHotwordDetector. de implementar la detección de palabras clave con una CPU baja. El uso de esta función está se divide en dos partes:

  • Creación de la instancia de un AlwaysOnHotwordDetector.
  • Inscripción de un modelo de sonido de detección de palabras clave.

La implementación de VoiceInteractionService puede crear un detector de palabras clave mediante VoiceInteractionService#createAlwaysOnHotwordDetector(), pasando la frase clave y la configuración regional que desean usar para la detección. Como resultado, el La app recibe un onAvailabilityChanged() Es la devolución de llamada con uno de los siguientes valores posibles:

  • STATE_HARDWARE_UNAVAILABLE La función de DSP no está disponible en la dispositivo. En este caso, se usa la detección de palabras clave de software.
  • STATE_HARDWARE_UNSUPPORTED La compatibilidad con DSP no está disponible en general, pero La DSP no admite la combinación determinada de frase clave y configuración regional. La app puede optar por usar Detección de palabra clave de software.
  • STATE_HARDWARE_ENROLLED La detección de palabras activas está lista y se puede iniciar llamando al método startRecognition().
  • STATE_HARDWARE_UNENROLLED Un modelo de sonido para la frase clave solicitada no es disponible, pero es posible inscribirse.

La inscripción de modelos de sonido de detección de palabras clave se puede realizar con IVoiceInteractionManagerService#updateKeyphraseSoundModel(). Se pueden registrar varios modelos en el sistema a la vez, pero solo uno está asociado con un AlwaysOnHotwordDetector. La detección de palabras clave de DSP podría no estar disponible en todos los dispositivos. A través de desarrolladores debes verificar las capacidades del hardware con getDspModuleProperties() . Para ver un ejemplo de código que muestra cómo inscribir modelos de sonido, consulta VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java. Consulta la sección Captura simultánea para obtener información sobre reconocimiento simultáneo de palabras clave.

Detección de palabra clave de software

Como se indicó anteriormente, la detección de palabras clave de DSP puede no estar disponible en todos dispositivos (por ejemplo, Android Emulator no ofrece emulación de DSP). En este caso, el reconocimiento de voz mediante software es la única alternativa. Para evitar interferir en que podrían necesitar acceso al micrófono, los VIA deben acceder a la entrada de audio usando lo siguiente:

Ambas constantes son @hide y están disponibles solo para apps empaquetadas.

Cómo administrar la entrada de audio y el reconocimiento de voz

La entrada de audio se implementará con la clase MediaRecorder. Para obtener más información sobre cómo usar esta API, consulta el archivo MediaRecorder Descripción general. También se espera que los servicios de interacción por voz estén RecognitionService implementaciones de clase. Cualquier aplicación del sistema que requiera el reconocimiento de voz utiliza el para acceder a esta función. Para realizar el reconocimiento de voz y tener acceso al micrófono, las VIA debe contener android.permission.RECORD_AUDIO. Apps que acceden a un RecognitionService se espera que la implementación también tenga este permiso.

Antes de Android 10, el acceso al micrófono se otorgaba a una sola app por vez tiempo (a excepción de la detección de palabras clave, ver arriba). A partir de Android 10, se puede compartir el acceso al micrófono. Para obtener más información, consulta Uso compartido Entrada de audio

Acceder a la salida de audio

Cuando el VIA está listo para dar respuestas verbales, es importante sigue este conjunto de lineamientos: