Développement d'application

Pour implémenter une application d'interaction vocale (VIA), procédez comme suit :

  1. Créez un squelette VIA.
  2. ( facultatif ) Implémentez un flux de configuration/connexion.
  3. ( facultatif ) Implémentez un écran Paramètres.
  4. Déclarez les autorisations requises dans le fichier manifeste.
  5. Implémentez une interface utilisateur de plaque vocale.
  6. Implémenter la reconnaissance vocale (doit inclure la mise en œuvre de l'API RecognitionService).
  7. Implémentez l'énoncé (vous pouvez éventuellement implémenter l'API TextToSpeech).
  8. Implémenter l’exécution des commandes. Consultez ce contenu dans Exécution des commandes .

Les sections suivantes décrivent comment effectuer chaque étape mentionnée ci-dessus.

Créer un squelette VIA

Manifestes

Une application est détectée comme une application avec interaction vocale lorsque les éléments suivants sont inclus dans le manifeste :

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>

Dans cet exemple :

  • Les VIA doivent exposer un service qui étend VoiceInteractionService , avec un filtre d'intention pour l'action VoiceInteractionService.SERVICE_INTERFACE ("android.service.voice.VoiceInteractionService") .
  • Ce service doit détenir l'autorisation de signature système BIND_VOICE_INTERACTION .
  • Ce service doit inclure un fichier de métadonnées android.voice_interaction contenant les éléments suivants :

    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" />
    

Pour plus de détails sur chaque champ, consultez R.styleable#VoiceInteractionService . Étant donné que tous les VIA sont également des services de reconnaissance vocale, vous devez également inclure les éléments suivants dans votre manifeste :

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>

Les services de reconnaissance vocale nécessitent également les métadonnées suivantes :

res/xml/recognition_service.xml

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

VoiceInteractionService, VoiceInteractionSessionService et VoiceInteractionSession

Le diagramme suivant illustre le cycle de vie de chacune de ces entités :

Des cycles de vie

Figure 1. Cycles de vie

Comme indiqué précédemment, VoiceInteractionService est le point d'entrée d'un VIA. Les principales responsabilités de ce service sont :

  • Initialisez tous les processus qui doivent continuer à s'exécuter aussi longtemps que ce VIA est actif. Par exemple, la détection de mots clés.
  • Signale les actions vocales prises en charge (voir Voice Assistant Tap-to-Read ).
  • Lancez des sessions d'interaction vocale depuis l'écran de verrouillage (keyguard).

Dans sa forme la plus simple, une implémentation de VoiceInteractionService ressemblerait à ceci :

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;
    }
    ...
}

L’implémentation de VoiceInteractionService#onGetSupportedVoiceActions() est requise pour gérer Voice Assistant Tap-to-Read . Un VoiceInteractionSessionService est utilisé par le système pour créer et interagir avec un VoiceInteractionSession . Il n'a qu'une seule responsabilité, démarrer de nouvelles sessions sur demande.

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

Enfin, une VoiceInteractionSession est l'endroit où la plupart du travail serait effectué. Une seule instance de session peut être réutilisée pour effectuer plusieurs interactions utilisateur. Dans AAOS, un assistant CarVoiceInteractionSession existe, aidant à implémenter certaines des fonctionnalités uniques de l'automobile.

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 dispose d'un large ensemble de méthodes de rappel qui sont expliquées dans les sections suivantes. consultez la documentation de VoiceInteractionSession pour une liste complète.

Implémenter un flux de configuration/connexion

La configuration et la connexion peuvent avoir lieu :

  • Lors de l'intégration de l'appareil (Assistant de configuration).
  • Lors de l'échange de services d'interaction vocale (Paramètres).
  • Au premier lancement lorsque l'application est sélectionnée.

Pour plus de détails sur l'expérience utilisateur recommandée et les conseils visuels, voir Assistants préchargés : conseils UX .

Configuration lors de l'échange de service vocal

Il est toujours possible pour l'utilisateur de sélectionner un VIA qui n'a pas été correctement configuré. Cela peut arriver parce que :

  • L'utilisateur a entièrement ignoré l'assistant de configuration ou l'utilisateur a ignoré l'étape de configuration de l'interaction vocale.
  • L'utilisateur a sélectionné un VIA différent de celui configuré lors de l'intégration de l'appareil.

Dans tous les cas, un VoiceInteractionService dispose de plusieurs manières pour encourager l'utilisateur à terminer la configuration :

  • Rappel de notification.
  • Réponse vocale automatique lorsque l'utilisateur essaie de l'utiliser.

Remarque : Il est fortement déconseillé de présenter un flux de configuration VIA sans demande explicite de l'utilisateur. Cela signifie que les VIA doivent éviter d'afficher automatiquement le contenu sur le HU lors du démarrage de l'appareil ou à la suite d'un changement ou d'un déverrouillage d'utilisateur.

Rappel des notifications

Un rappel de notification est un moyen non intrusif d'indiquer la nécessité d'une configuration et de fournir aux utilisateurs la possibilité de naviguer dans le flux de configuration de l'assistant.

Rappel des notifications

Figure 2. Rappel de notification

Voici comment ce flux fonctionnerait :

Flux de rappel de notification

Figure 3. Flux de rappel de notification

Réponse vocale

Il s'agit du flux le plus simple à implémenter, initiant un énoncé sur un rappel VoiceInteractionSession#onShow() , expliquant à l'utilisateur ce qui doit être fait, puis lui demandant (si la configuration est autorisée compte tenu de l'état de restriction UX) s'il souhaite lancer le flux de configuration. Si la configuration n'est pas possible à ce moment-là, expliquez également cette situation.

Configuration à la première utilisation

Il est toujours possible pour l'utilisateur de déclencher un VIA mal configuré. Dans ces cas:

  1. Informez verbalement l'utilisateur de cette situation (par exemple : « Pour fonctionner correctement, j'ai besoin que vous effectuiez quelques étapes… »).
  2. Si le moteur de restrictions UX le permet (voir UX_RESTRICTIONS_NO_SETUP ), demandez à l'utilisateur s'il souhaite démarrer le processus de configuration, puis ouvrez l'écran Paramètres du VIA.
  3. Sinon (par exemple, si l'utilisateur conduit), laissez une notification lui demandant de cliquer sur l'option lorsqu'il peut le faire en toute sécurité.

Créer des écrans de configuration d'interaction vocale

Les écrans de configuration et de connexion doivent être développés en tant qu’activités régulières. Consultez les directives UX et visuelles pour le développement de l'interface utilisateur dans Assistants préchargés : conseils UX .

Conditions générales d'Utilisation:

  • Les VIA doivent permettre aux utilisateurs d'interrompre et de reprendre la configuration à tout moment.
  • L'installation ne doit pas être autorisée si la restriction UX_RESTRICTIONS_NO_SETUP est en vigueur. Pour plus de détails, voir Directives sur la distraction du conducteur .
  • Les écrans de configuration doivent correspondre au système de conception de chaque véhicule. La disposition générale de l'écran, les icônes, les couleurs et autres aspects doivent être cohérents avec le reste de l'interface utilisateur. Voir Personnalisation pour plus de détails.

Implémenter un écran de paramètres

Intégration des paramètres

Figure 4. Intégration des paramètres

Les écrans de paramètres sont des activités Android régulières. S'il est implémenté, leur point d'entrée doit être déclaré dans le res/xml/interaction_service.xml dans le cadre des manifestes VIA (voir Manifests ). La section Paramètres est un bon endroit pour poursuivre la configuration et la connexion (si l'utilisateur ne l'a pas terminé) ou proposer une option de déconnexion ou de changement d'utilisateur si nécessaire. Semblables aux écrans de configuration décrits ci-dessus, ces écrans devraient :

  • Offrez la possibilité de revenir à l'écran précédent dans la pile d'écrans (par exemple, vers Paramètres de la voiture).
  • Ne pas être autorisé en conduisant. Pour plus de détails, voir Directives sur la distraction du conducteur .
  • Faites correspondre chaque système de conception de véhicule. Pour plus de détails, voir Personnalisation .

Déclarez les autorisations requises dans le fichier manifeste

Les autorisations requises par un VIA peuvent être divisées en trois catégories :

  • Autorisations de signature système. Il s’agit d’autorisations accordées uniquement aux APK préinstallés et signés par le système. Les utilisateurs ne peuvent pas accorder ces autorisations, seuls les OEM peuvent les accorder lors de la création de leurs images système. Pour plus d'informations sur l'obtention d'autorisations de signature, consultez Accorder des autorisations privilégiées au système .
  • Autorisations dangereuses. Il s'agit d'autorisations qu'un utilisateur doit accorder à l'aide de la boîte de dialogue PermissionsController. Les OEM peuvent pré-accorder certaines de ces autorisations au VoiceInteractionService par défaut. Mais étant donné que cette valeur par défaut peut changer d'un appareil à l'autre, les applications devraient pouvoir demander ces autorisations en cas de besoin.
  • Autres autorisations. Il s'agit de toutes les autres autorisations qui ne nécessitent pas l'intervention de l'utilisateur. Ces autorisations sont automatiquement accordées par le système.

Compte tenu de ce qui précède, la section suivante se concentre uniquement sur les demandes d’autorisations dangereuses. Les autorisations ne doivent être demandées que lorsque l'utilisateur est dans les écrans de connexion ou de configuration.

Si l'application ne dispose pas des autorisations nécessaires pour fonctionner, la procédure recommandée consiste à utiliser un énoncé vocal pour expliquer la situation à l'utilisateur et une notification pour fournir une autorisation que l'utilisateur peut utiliser pour revenir aux écrans de paramètres de VIA. . Pour plus de détails, voir 1. Rappel de notification .

Demander des autorisations dans le cadre de l'écran de configuration

Les autorisations dangereuses sont demandées à l'aide de la méthode habituelle ActivityCompat#requestPermission() (ou équivalente). Pour plus de détails sur la façon de demander des autorisations, consultez Demander des autorisations d'application .

Demander des autorisations

Figure 5. Demander des autorisations

Autorisation de l'écouteur de notification

Pour implémenter le flux TTR, les VIA doivent être désignés comme auditeurs de notification. Il ne s'agit pas d'une autorisation en soi, mais plutôt d'une configuration qui permet au système d'envoyer des notifications aux auditeurs enregistrés. Pour savoir si le VIA a eu accès à ces informations, les applications peuvent :

Si cet accès n'est pas pré-accordé, le VIA doit diriger l'utilisateur vers la section Accès aux notifications des paramètres de la voiture, en utilisant une combinaison d'énoncés et de notifications. Le code suivant peut être utilisé pour ouvrir la section appropriée de l'application des paramètres :

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

Implémenter une interface utilisateur de plaque vocale

Lorsqu'une VoiceInteractionSession reçoit un rappel onShow() , elle peut présenter une interface utilisateur de plaque vocale. Pour obtenir des directives visuelles et UX sur la mise en œuvre de la plaque vocale, voir Assistants préchargés : conseils UX .

Affichage de la plaque vocale

Figure 6. Affichage de la plaque vocale

Il existe deux options pour implémenter cette interface utilisateur :

  • Remplacer VoiceInteractionSession#onCreateContentView()
  • Lancez une activité à l'aide VoiceInteractionSession#startAssistantActivity()

Utilisez onCreateContentView()

C'est la manière par défaut de présenter une plaque vocale. La classe de base VoiceInteractionSession crée une fenêtre et gère son cycle de vie aussi longtemps qu'une session vocale est active. Les applications doivent remplacer VoiceInteractionSession#onCreateContentView() et renvoyer une vue attachée à cette fenêtre dès que la session est créée. Cette vue devrait initialement être invisible. Lorsqu'une interaction vocale démarre, cette vue doit être rendue visible sur VoiceInteractionSession#onShow() puis à nouveau invisible sur 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);
    }
    …
}

Lorsque vous utilisez cette méthode, vous souhaiterez peut-être ajuster VoiceInteractionSession#onComputeInsets() pour tenir compte des régions obscurcies de votre interface utilisateur.

Utilisez startAssistantActivity()

Dans ce cas, VoiceInteractionSession délègue la gestion de l’interface utilisateur de la plaque vocale à une activité régulière. Lorsque cette option est utilisée, une implémentation VoiceInteractionSession doit désactiver la création de sa fenêtre de contenu par défaut (voir Utilisation de onCreateContentView() ) lors du rappel onPrepareShow() . À VoiceInteractionSession#onShow() , la session démarrerait l'activité de la plaque vocale en utilisant VoiceInteractionSession#startAssistantActivity() . Cette méthode lance l’interface utilisateur avec les paramètres de fenêtre et les indicateurs d’activité appropriés.

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);
    }

    …
}

Pour maintenir une communication entre cette activité et la VoiceInteractionSession , un ensemble d'intentions internes ou de liaison de service peut être requis. Par exemple, lorsque VoiceInteractionSession#onHide() est invoquée, la session doit pouvoir transmettre cette requête à l'activité.

Important. Dans l'automobile, seules les activités spécialement annotées ou répertoriées dans la « liste autorisée » UXR peuvent être affichées pendant la conduite. Cela s'applique également aux activités démarrées avec VoiceInteractionSession#startAssistantActivity() . N'oubliez pas d'annoter votre activité avec <meta-data android:name="distractionOptimized" android:value="true"/> ou d'inclure cette activité dans la clé systemActivityWhitelist du /packages/services/Car/service/res/values/config.xml fichier /packages/services/Car/service/res/values/config.xml . Pour plus d'informations, consultez Directives relatives à la distraction du conducteur .

Implémenter la reconnaissance vocale

Dans cette section, vous apprendrez à mettre en œuvre la reconnaissance vocale grâce à la détection et à la reconnaissance de mots clés. Un mot clé est un mot déclencheur utilisé pour démarrer une nouvelle requête ou action vocalement. Par exemple, « OK Google » ou « Hey Google ».

Détection de mots clés DSP

Android donne accès à un détecteur de mots clés toujours actif au niveau DSP au moyen de AlwaysOnHotwordDetector . moyen d'implémenter la détection de mots clés avec un processeur faible. L'utilisation de cette fonctionnalité est divisée en deux parties :

L'implémentation de VoiceInteractionService peut créer un détecteur de mots clés à l'aide VoiceInteractionService#createAlwaysOnHotwordDetector() , en transmettant une phrase clé et des paramètres régionaux qu'ils souhaitent utiliser pour la détection. Par conséquent, l’application reçoit un rappel onAvailabilityChanged() avec l’une des valeurs possibles suivantes :

  • STATE_HARDWARE_UNAVAILABLE . La fonctionnalité DSP n'est pas disponible sur l'appareil. Dans ce cas, la détection logicielle des mots clés est utilisée.
  • STATE_HARDWARE_UNSUPPORTED . La prise en charge DSP n'est pas disponible en général, mais DSP ne prend pas en charge une combinaison donnée de phrase clé et de paramètres régionaux. L'application peut choisir d'utiliser le logiciel de détection de mots clés .
  • STATE_HARDWARE_ENROLLED . La détection des mots chauds est prête et peut être démarrée en appelant la méthode startRecognition() .
  • STATE_HARDWARE_UNENROLLED . Un modèle sonore pour la phrase clé demandée n'est pas disponible, mais l'inscription est possible.

L'inscription des modèles sonores de détection de mots clés peut être effectuée à l'aide de IVoiceInteractionManagerService#updateKeyphraseSoundModel() . Plusieurs modèles peuvent être enregistrés dans le système à un moment donné, mais un seul modèle est associé à un AlwaysOnHotwordDetector . La détection des mots clés DSP peut ne pas être disponible sur tous les appareils. Les développeurs VIA doivent vérifier les capacités matérielles à l’aide de la méthode getDspModuleProperties() . Pour obtenir un exemple de code montrant comment inscrire des modèles sonores, consultez VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java . Voir Capture simultanée concernant la reconnaissance simultanée de mots clés.

Détection de mots clés par logiciel

Comme indiqué ci-dessus, la détection des mots clés DSP peut ne pas être disponible sur tous les appareils (par exemple, l'émulateur Android ne fournit pas d'émulation DSP). Dans ce cas, la reconnaissance vocale logicielle est la seule alternative. Pour éviter d'interférer avec d'autres applications susceptibles d'avoir besoin d'accéder au microphone, les VIA doivent accéder à l'entrée audio en utilisant :

Ces deux constantes sont @hide et disponibles uniquement pour les applications groupées.

Gérer l'entrée audio et la reconnaissance vocale

L'entrée audio serait implémentée à l'aide de la classe MediaRecorder . Pour plus d'informations sur l'utilisation de cette API, consultez la présentation de MediaRecorder . Les services d'interaction vocale devraient également être des implémentations de la classe RecognitionService . Toute application du système nécessitant une reconnaissance vocale utilise le pour accéder à cette fonctionnalité. Pour faire de la reconnaissance vocale et avoir accès au microphone, les VIA doivent détenir android.permission.RECORD_AUDIO . Les applications accédant à une implémentation RecognitionService doivent également détenir cette autorisation.

Avant Android 10, l'accès au microphone n'était accordé qu'à une seule application à la fois (à l'exception de la détection des mots clés, voir ci-dessus). À partir d'Android 10, l'accès au microphone peut être partagé. Pour plus d'informations, consultez Partage de l'entrée audio .

Accéder à la sortie audio

Lorsque VIA est prêt à fournir des réponses verbales, il est important de suivre cet ensemble de lignes directrices :