Pour implémenter une application d'interaction vocale (VIA), procédez comme suit :
- Créez un squelette VIA.
- ( facultatif ) Implémentez un flux de configuration/connexion.
- ( facultatif ) Implémentez un écran Paramètres.
- Déclarez les autorisations requises dans le fichier manifeste.
- Implémentez une interface utilisateur de plaque vocale.
- Implémenter la reconnaissance vocale (doit inclure la mise en œuvre de l'API RecognitionService).
- Implémentez l'énoncé (vous pouvez éventuellement implémenter l'API TextToSpeech).
- 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'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_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 :
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.
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, 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:
- Informez verbalement l'utilisateur de cette situation (par exemple : « Pour fonctionner correctement, j'ai besoin que vous effectuiez quelques étapes… »).
- 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.
- 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
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 .
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 :
- (Facultatif) Vérifiez à l'avance s'il existe des écouteurs de notification en utilisant
CarAssistUtils#assistantIsNotificationListener()
. Cela pourrait être fait, par exemple, pendant le flux de configuration. - (Obligatoire) Réagissez à la gestion de
CarVoiceInteractionSession#onShow()
avec l'actionVOICE_ACTION_HANDLE_EXCEPTION
et l'exceptionEXCEPTION_NOTIFICATION_LISTENER_PERMISSIONS_MISSING
.
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 .
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 :
- Instanciation d'un
AlwaysOnHotwordDetector
. - Inscription 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 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éthodestartRecognition()
. -
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 :
- La capture audio doit utiliser MediaRecorder.AudioSource.HOTWORD .
- Détenez l’autorisation
android.Manifest.permission.CAPTURE_AUDIO_HOTWORD
.
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 :
- Lors de la demande de focus audio ou de la gestion de la sortie audio, l'application doit utiliser
AudioAttributes#USAGE_ASSISTANT
etAudioAttributes#CONTENT_TYPE_SPEECH
comme attributs audio. - Lors de la reconnaissance vocale, le focus audio doit être demandé avec
AudioManage#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
. Sachez que certaines applications multimédias peuvent ne pas réagir correctement aux commandes multimédias (voir Exécution des commandes multimédias ) lorsque leur focus audio est supprimé.