Pour implémenter une application d'interaction vocale (VIA, Voice Interaction Application), procédez comme suit :
- Créez une structure de VIA.
- (Facultatif) Implémentez un flux de configuration/connexion.
- (Facultatif) Implémentez un écran de paramètres.
- Déclarez les autorisations requises dans le fichier manifeste.
- Implémentez une interface utilisateur de plaque vocale.
- Implémentez la reconnaissance vocale (doit inclure l'implémentation de l'API RecognitionService).
- Implémentez l'énoncé (vous pouvez éventuellement implémenter l'API TextToSpeech).
- Implémentez le traitement des commandes. Consultez ce contenu dans Traiter les commandes.
Les sections suivantes décrivent comment effectuer chaque étape mentionnée ci-dessus.
Créer une structure de VIA
Fichiers manifestes
Une application est détectée comme une application avec interaction vocale lorsque les éléments suivants sont inclus dans le fichier 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'intent pour l'actionVoiceInteractionService.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_interactioncontenant 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 en savoir plus sur chaque champ, consultez R.styleable#VoiceInteractionService.
Étant donné que toutes les VIA sont également des services de reconnaissance vocale, vous devez également inclure les éléments suivants dans votre fichier 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 schéma suivant illustre le cycle de vie de chacune de ces entités :

Figure 1. Cycles de vie
Comme indiqué précédemment, VoiceInteractionService est le point d'entrée d'une VIA. Les principales responsabilités de ce service sont les suivantes :
- Initialiser tous les processus qui doivent rester actifs tant que cette VIA est active. Par exemple, la détection de mots clés.
- Signaler les commandes vocales compatibles (voir Assistant vocal Tap-to-Read (TTR)).
- Lancer des sessions d'interaction vocale depuis l'écran de verrouillage (keyguard).
Dans sa forme la plus simple, une implémentation de VoiceInteractionService se présente comme suit :
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
la fonctionnalité Tap-to-Read de l'Assistant vocal.
Un VoiceInteractionSessionService est utilisé par le système pour créer et interagir avec une 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, la plupart du travail est effectué dans une VoiceInteractionSession. Une seule instance de session peut être réutilisée pour effectuer plusieurs interactions utilisateur. Dans AAOS, un helper CarVoiceInteractionSession existe, ce qui permet d'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 comporte un grand ensemble de méthodes de rappel qui sont
expliquées dans les sections suivantes. Consultez la documentation de VoiceInteractionSession pour obtenir la 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 du remplacement du service d'interaction vocale (paramètres).
- Lors du premier lancement de l'application.
Pour en savoir plus sur l'expérience utilisateur recommandée et les conseils visuels, consultez Assistants préchargés : conseils sur l'expérience utilisateur.
Configuration lors du remplacement du service vocal
L'utilisateur peut toujours sélectionner une VIA qui n'a pas été correctement configurée. Elle peut avoir plusieurs causes :
- L'utilisateur a ignoré l'assistant de configuration ou l'étape de configuration de l'interaction vocale.
- L'utilisateur a sélectionné une VIA différente de celle configurée lors de l'intégration de l'appareil.
Dans tous les cas, un VoiceInteractionService dispose de plusieurs moyens d'encourager l'utilisateur à terminer la configuration :
- Rappel de notification.
- Réponse vocale automatique lorsque l'utilisateur tente de l'utiliser.
Remarque : Il est fortement déconseillé de présenter un flux de configuration de VIA sans demande explicite de l'utilisateur. Cela signifie que les VIA doivent éviter d'afficher automatiquement du contenu sur l'unité centrale lors du démarrage de l'appareil ou à la suite d'un changement ou d'un déverrouillage de l'utilisateur.
Rappel de notification
Un rappel de notification est un moyen non intrusif d'indiquer la nécessité d'une configuration et de fournir aux utilisateurs un moyen d'accéder au flux de configuration de l'assistant.

Figure 2. Rappel de notification
Voici comment ce flux fonctionnerait :

Figure 3. Flux de rappel de notification
Réponse vocale
Il s'agit du flux le plus simple à implémenter. Il lance un énoncé sur un rappel VoiceInteractionSession#onShow(), explique à l'utilisateur ce qu'il doit faire, puis lui demande (si la configuration est autorisée en fonction de l'état de restriction de l'expérience utilisateur) s'il souhaite lancer le flux de configuration. Si la configuration n'est pas possible pour le moment, expliquez également cette situation.
Configuration lors de la première utilisation
L'utilisateur peut toujours déclencher une VIA qui n'a pas été correctement configurée. Dans ce cas :
- Informez verbalement l'utilisateur de cette situation (par exemple, "Pour fonctionner correctement, vous devez effectuer quelques étapes…").
- Si le moteur de restrictions de l'expérience utilisateur le permet (voir UX_RESTRICTIONS_NO_SETUP), demandez à l'utilisateur s'il souhaite démarrer le processus de configuration, puis ouvrez l'écran des paramètres de la VIA.
- Sinon (par exemple, si l'utilisateur conduit), laissez une notification pour que l'utilisateur clique 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 consignes visuelles et d'expérience utilisateur pour le développement de l'interface utilisateur dans Assistants préchargés : conseils sur l'expérience utilisateur.
Consignes générales :
- Les VIA doivent permettre aux utilisateurs d'interrompre et de reprendre la configuration à tout moment.
- La configuration ne doit pas être autorisée si la restriction
UX_RESTRICTIONS_NO_SETUPest en vigueur. Pour en savoir plus, consultez Consignes relatives à la distraction du conducteur. - Les écrans de configuration doivent correspondre au système de conception de chaque véhicule. La mise en page générale de l'écran, les icônes, les couleurs et d'autres aspects doivent être cohérents avec le reste de l'interface utilisateur. Pour en savoir plus, consultez Personnalisation.
Implémenter un écran de paramètres

Figure 4. Intégration des paramètres
Les écrans de paramètres sont des activités Android régulières. S'ils sont implémentés, leur point d'entrée
doit être déclaré dans le res/xml/interaction_service.xml dans le cadre des fichiers manifestes de la VIA (voir
Fichiers manifestes).
La section "Paramètres" est un bon endroit pour poursuivre la configuration et la connexion (si l'utilisateur ne l'a pas terminée) ou pour proposer une option de déconnexion ou de changement d'utilisateur si nécessaire. Comme pour les écrans de configuration décrits ci-dessus, ces écrans doivent :
- Fournir la possibilité de revenir à l'écran précédent dans la pile d'écrans (par exemple, aux paramètres de la voiture).
- Ne pas être autorisés pendant la conduite. Pour en savoir plus, consultez Consignes relatives à la distraction du conducteur.
- Correspondre à chaque système de conception de véhicule. Pour en savoir plus, consultez Personnalisation.
Déclarer les autorisations requises dans le fichier manifeste
Les autorisations requises par une 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 en savoir plus sur l'obtention des 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. Toutefois, étant donné que cette valeur par défaut peut varier d'un appareil à l'autre, les applications doivent pouvoir demander ces autorisations si nécessaire.
- Autres autorisations. Il s'agit de toutes les autres autorisations qui ne nécessitent pas d'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 la demande d'autorisations dangereuses. Les autorisations ne doivent être demandées que lorsque l'utilisateur se trouve sur les écrans de connexion ou de paramètres.
Si l'application ne dispose pas des autorisations nécessaires à son fonctionnement, le flux recommandé consiste à utiliser un énoncé vocal pour expliquer la situation à l'utilisateur et une notification pour fournir un moyen que l'utilisateur peut utiliser pour revenir aux écrans de paramètres de la VIA. Pour en savoir plus, consultez 1. Rappel de notification.
Demander des autorisations dans l'écran de paramètres
Les autorisations dangereuses sont demandées à l'aide de la méthode ActivityCompat#requestPermission() standard (ou équivalente). Pour en savoir plus sur la demande d'autorisations, consultez
Demander des autorisations d'application.

Figure 5. Demander des autorisations
Autorisation d'écouteur de notifications
Pour implémenter le flux TTR, les VIA doivent être désignées comme écouteur de notifications. Il ne s'agit pas d'une autorisation à proprement parler, mais d'une configuration qui permet au système d'envoyer des notifications aux écouteurs enregistrés. Pour savoir si la VIA a eu accès à ces informations, les applications peuvent :
- (Facultatif) Vérifier s'il existe des écouteurs de notifications à l'avance à l'aide de
CarAssistUtils#assistantIsNotificationListener(). Cela peut être fait, par exemple, lors du flux de configuration. - (Obligatoire) Réagir à la gestion de
CarVoiceInteractionSession#onShow()avec l'actionVOICE_ACTION_HANDLE_EXCEPTIONet l'exceptionEXCEPTION_NOTIFICATION_LISTENER_PERMISSIONS_MISSING.
Si cet accès n'est pas préaccordé, la VIA doit rediriger l'utilisateur vers la section "Accès aux notifications" des paramètres de la voiture, à l'aide d'une combinaison d'énoncés et de notifications. Le code suivant peut être utilisé pour ouvrir la section appropriée de l'application 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 consignes visuelles et d'expérience utilisateur sur l'implémentation de la plaque vocale,consultez
Assistants préchargés : conseils sur l'expérience utilisateur.

Figure 6. Affichage de la plaque vocale
Il existe deux façons d'implémenter cette interface utilisateur :
- Remplacer
VoiceInteractionSession#onCreateContentView() - Lancer une activité à l'aide de
VoiceInteractionSession#startAssistantActivity()
Utiliser onCreateContentView()
Il s'agit de la méthode par défaut pour présenter une plaque vocale. La classe de base VoiceInteractionSession crée une fenêtre et gère son cycle de vie tant qu'une session vocale est active. Les applications doivent remplacer VoiceInteractionSession#onCreateContentView() et renvoyer une vue associée à cette fenêtre dès la création de la session. Cette vue doit initialement être invisible. Lorsqu'une interaction vocale démarre, cette vue doit être rendue visible sur VoiceInteractionSession#onShow(), puis de 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 pouvez ajuster VoiceInteractionSession#onComputeInsets()
pour tenir compte des régions masquées de votre interface utilisateur.
Utiliser 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 VoiceInteractionSession
implémentation doit désactiver la création de sa fenêtre de contenu par défaut (voir Utiliser onCreateContentView()) sur le rappel onPrepareShow(). Dans VoiceInteractionSession#onShow(), la session démarre l'activité de la plaque vocale à l'aide de 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'intents internes ou de liaison de service peut être requis. Par exemple, lorsque VoiceInteractionSession#onHide() est appelé, la session doit pouvoir transmettre cette requête à l'activité.
Important Dans le secteur automobile, seules les activités spécialement annotées ou celles listées dans la liste d'autorisation 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 fichier /packages/services/Car/service/res/values/config.xml. Pour en savoir plus, consultez Consignes relatives à la distraction du conducteur.
Implémenter la reconnaissance vocale
Dans cette section, vous allez apprendre à implémenter la reconnaissance vocale par 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 par commande vocale. Par exemple, "Ok Google" ou "Hey Google".
Détection de mots clés DSP
Android fournit un accès à un détecteur de mots clés toujours activé au niveau du DSP via
AlwaysOnHotwordDetector.
méthode d'implémentation de la détection de mots clés avec un faible niveau d'utilisation du processeur. L'utilisation de cette fonctionnalité est divisée en deux parties :
- Instanciation d'un
AlwaysOnHotwordDetector. - Enregistrement d'un modèle sonore de détection de mots clés.
L'implémentation de VoiceInteractionService peut créer un détecteur de mots clés à l'aide de
VoiceInteractionService#createAlwaysOnHotwordDetector(),
en transmettant une expression clé et des paramètres régionaux qu'il souhaite utiliser pour la détection. L'application reçoit alors 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 de mots clés logicielle est utilisée.STATE_HARDWARE_UNSUPPORTED. La prise en charge du DSP n'est pas disponible en général, mais le DSP n'est pas compatible avec la combinaison d'expression clé et de paramètres régionaux donnée. L'application peut choisir d'utiliser la détection de mots clés logicielle.STATE_HARDWARE_ENROLLED. La détection de mots clés est prête et peut être démarrée en appelant la méthodestartRecognition().STATE_HARDWARE_UNENROLLED. Un modèle sonore pour l'expression clé demandée n'est pas disponible, mais l'enregistrement est possible.
L'enregistrement des modèles sonores de détection de mots clés peut être effectué à 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 de mots clés DSP peut ne pas être disponible sur tous les appareils. Les développeurs de VIA
doivent vérifier les capacités matérielles à l'aide de la getDspModuleProperties()
méthode. Pour obtenir un exemple de code montrant
comment enregistrer des modèles sonores, consultez VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java.
Consultez Capture simultanée concernant
la reconnaissance simultanée de mots clés.
Détection de mots clés logicielle
Comme indiqué ci-dessus, la détection de 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 qui pourraient avoir besoin d'accéder au microphone, les VIA doivent accéder à l'entrée audio à l'aide des éléments suivants :
- La capture audio doit utiliser MediaRecorder.AudioSource.HOTWORD.
- Détenir l'autorisation
android.Manifest.permission.CAPTURE_AUDIO_HOTWORD.
Ces deux constantes sont @hide et ne sont disponibles que pour les applications groupées.
Gérer l'entrée audio et la reconnaissance vocale
L'entrée audio est implémentée à l'aide de la classe MediaRecorder.
Pour en savoir plus sur l'utilisation de cette API, consultez la présentation de MediaRecorder. Les services d'interaction vocale doivent également être des implémentations de classe RecognitionService. Toute application du système qui nécessite une reconnaissance vocale utilise pour accéder à cette fonctionnalité. Pour effectuer une 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 de mots clés, voir ci-dessus). À partir d'Android 10, l'accès au microphone peut être partagé. Pour en savoir plus, consultez Partager l'entrée audio.
Accéder à la sortie audio
Lorsque la VIA est prête à fournir des réponses verbales, il est important de suivre l'ensemble de consignes suivant :
- Lorsqu'elle demande la priorité audio ou gère la sortie audio, l'application
doit utiliser
AudioAttributes#USAGE_ASSISTANTetAudioAttributes#CONTENT_TYPE_SPEECHcomme attributs audio. - Lors de la reconnaissance vocale, la priorité audio doit être demandée avec
AudioManage#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE. Sachez que certaines applications multimédias peuvent ne pas réagir correctement aux commandes multimédias (voir Traiter les commandes multimédias) lorsque leur priorité audio est supprimée.