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 de paramètres.
- Déclarez les autorisations requises dans le fichier manifeste.
- Implémentez une interface utilisateur de carte vocale.
- Implémentez la reconnaissance vocale (elle 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 la section Exécuter des commandes.
Les sections suivantes décrivent comment effectuer chaque étape mentionnée ci-dessus.
Créer un squelette VIA
Fichiers manifestes
Une application est détectée comme étant dotée d'une 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 disposer de 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 en savoir plus 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 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 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 les suivantes:
- Initialisez tous les processus qui doivent rester en cours d'exécution aussi longtemps que ce VIA est actif. (par exemple, la détection de mots clés)
- Rapports sur les commandes vocales compatibles (voir Commandes vocales de l'Assistant Google pour lire à voix haute).
- Lancer des sessions d'interaction vocale depuis l'écran de verrouillage (verrouillage des touches).
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é Lire à l'aide de l'Assistant vocal.
Le système utilise un VoiceInteractionSessionService pour créer et interagir avec une VoiceInteractionSession. Il n'a qu'une seule responsabilité : démarrer de nouvelles sessions à la demande.
public class MyVoiceInteractionSessionService extends VoiceInteractionSessionService { @Override public VoiceInteractionSession onNewSession(Bundle args) { return new MyVoiceInteractionSession(this); } }
Enfin, la majeure partie du travail se fait dans une VoiceInteractionSession. Une seule instance de session peut être réutilisée pour effectuer plusieurs interactions utilisateur. Dans AAOS, un CarVoiceInteractionSession
d'assistance 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
dispose d'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 se produire:
- Lors de l'intégration de l'appareil (assistant de configuration).
- Lors du changement de service lors d'une interaction vocale (paramètres)
- Lors du premier lancement de l'application lorsqu'elle est sélectionnée.
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 transfert d'un service vocal
L'utilisateur peut toujours sélectionner un VIA qui n'a pas été correctement configuré. Cela peut être dû aux raisons suivantes:
- L'utilisateur a complètement ignoré l'assistant de configuration ou l'étape de configuration des interactions vocales.
- 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 façons d'encourager l'utilisateur à terminer la configuration:
- Rappel de notification.
- Réponse vocale automatique lorsque l'utilisateur tente de l'utiliser.
Remarque: Nous vous déconseillons vivement de présenter un flux de configuration VIA sans demande explicite de l'utilisateur. Cela signifie que les VIA doivent éviter d'afficher automatiquement du contenu sur l'HU lors du démarrage de l'appareil, ou à la suite d'un changement d'utilisateur ou d'un déverrouillage.
Rappel de notification
Un rappel par notification est un moyen non intrusif d'indiquer la nécessité de la configuration et de fournir aux utilisateurs une affordance pour 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 une énonciation sur un rappel VoiceInteractionSession#onShow()
, explique à l'utilisateur ce qu'il doit faire, puis lui demande (si la configuration est autorisée compte tenu de l'état de la restriction d'expérience utilisateur) s'il souhaite lancer le flux de configuration. Si la configuration n'est pas possible pour le moment, expliquez-le également.
Configuration lors de la première utilisation
L'utilisateur peut toujours déclencher un VIA qui n'a pas été correctement configuré. Dans ce cas:
- Informez l'utilisateur verbalement de cette situation (par exemple, "Pour que cela fonctionne correctement, je vais vous demander de suivre 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 des paramètres de la VIA.
- Dans le cas contraire (par exemple, si l'utilisateur conduit), laissez une notification lui demandant de cliquer sur l'option lorsqu'il est sûr de le faire.
Créer des écrans de configuration des interactions vocales
Les écrans de configuration et de connexion doivent être développés en tant qu'activités standards. Consultez les consignes relatives à l'expérience utilisateur et aux éléments visuels pour le développement de l'UI dans la section Assistants préchargés: consignes relatives à 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_SETUP
est en vigueur. Pour en savoir plus, consultez les Consignes concernant les distractions 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 la section 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 standards. Le cas échéant, leur point d'entrée doit être déclaré dans res/xml/interaction_service.xml
dans les fichiers manifestes 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 les écrans de configuration décrits ci-dessus, ces écrans doivent:
- Fournissez l'option de revenir à l'écran précédent dans la pile d'écrans (par exemple, aux paramètres de la voiture).
- ne sont pas autorisés en conduisant ; Pour en savoir plus, consultez les Consignes concernant les distractions du conducteur.
- Associez chaque système de conception de véhicule. Pour en savoir plus, consultez la section Personnalisation.
Déclarer les autorisations requises dans le fichier manifeste
Les autorisations requises par un VIA peuvent être réparties en trois catégories:
- Autorisations de signature système. Ces autorisations ne sont accordées qu'aux APK signés par le système préinstallés. 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 d'autorisations de signature, consultez Accorder des autorisations de niveau 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 à 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 accordées automatiquement par le système.
Compte tenu de ce qui précède, la section suivante ne concerne que les demandes 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 pour fonctionner, le flux recommandé consiste à utiliser une expression vocale pour expliquer la situation à l'utilisateur et une notification pour fournir une affordance que l'utilisateur peut utiliser pour revenir aux écrans de paramètres VIA. Pour en savoir plus, consultez 1. Rappel de notification.
Demander des autorisations sur l'écran des paramètres
Les autorisations dangereuses sont demandées à l'aide de la méthode ActivityCompat#requestPermission()
standard (ou équivalente). Pour savoir comment demander des autorisations, consultez la section Demander des autorisations d'application.
Figure 5. Demander des autorisations
Autorisation de l'écouteur de notifications
Pour implémenter le flux TTR, les VIA doivent être désignées comme écouteurs de notifications. Il ne s'agit pas d'une autorisation en soi, mais d'une configuration qui permet au système d'envoyer des notifications aux écouteurs enregistrés. Pour savoir si l'accès à ces informations a été accordé à l'VIA, les applications peuvent:
- (Facultatif) Vérifiez à l'avance si des écouteurs de notification sont présents à l'aide de
CarAssistUtils#assistantIsNotificationListener()
. Vous pouvez le faire, par exemple, lors du 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 accordé à l'avance, le 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. Vous pouvez utiliser le code suivant 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'un VoiceInteractionSession
reçoit un rappel onShow()
, il peut présenter une UI de plaque vocale. Pour obtenir des consignes visuelles et sur l'expérience utilisateur concernant l'implémentation d'une plate-forme vocale,consultez la section Assistants préchargés: consignes relatives à l'expérience utilisateur.
Figure 6. Afficher l'élément vocal
Vous pouvez implémenter cette UI de deux manières:
- Ignorer
VoiceInteractionSession#onCreateContentView()
- Lancer une activité à l'aide de
VoiceInteractionSession#startAssistantActivity()
Utiliser onCreateContentView()
Il s'agit de la méthode par défaut de présentation d'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 être initialement invisible. Lorsqu'une interaction vocale commence, cette vue doit être 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 UI.
Utiliser startAssistantActivity()
Dans ce cas, VoiceInteractionSession
délègue la gestion de l'interface utilisateur de la plaque de commande 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 Utiliser onCreateContentView()) dans le rappel onPrepareShow()
. À VoiceInteractionSession#onShow()
, la session démarre l'activité de la plaque de commande vocale à l'aide de VoiceInteractionSession#startAssistantActivity()
. Cette méthode lance l'UI 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 VoiceInteractionSession
, un ensemble d'intents internes ou de liaisons de service peut être requis. Par exemple, lorsque VoiceInteractionSession#onHide()
est appelé, la session doit pouvoir transmettre cette requête à l'activité.
Important Dans Automotive, seules les activités annotées spécialement ou celles figurant sur la "liste d'autorisation" de l'UXR peuvent être affichées pendant la conduite. Cela s'applique également aux activités lancé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 les Consignes concernant les distractions du conducteur.
Implémenter la reconnaissance vocale
Dans cette section, vous allez apprendre à implémenter la reconnaissance vocale via la détection et la reconnaissance des mots clés. Un mot clé est un mot déclencheur utilisé pour lancer une nouvelle requête ou une nouvelle action par commande vocale. (par exemple, "Ok Google" ou "Hey Google").
Détection de mot clé de la DSP
Android permet d'accéder à un détecteur de mot clé toujours activé au niveau du DSP à l'aide de AlwaysOnHotwordDetector
.
de mettre en œuvre la détection de mot clé avec une faible utilisation du processeur. L'utilisation de cette fonctionnalité se divise en deux parties:
- Instanciation d'un
AlwaysOnHotwordDetector
. - Enregistrement d'un modèle de son de détection de mot clé.
L'implémentation de VoiceInteractionService peut créer un détecteur de mot clé à l'aide de VoiceInteractionService#createAlwaysOnHotwordDetector()
, en transmettant une expression clé et les paramètres régionaux à utiliser pour la détection. Par conséquent, l'application reçoit un rappel onAvailabilityChanged()
avec l'une des valeurs suivantes:
STATE_HARDWARE_UNAVAILABLE
. La fonctionnalité DSP n'est pas disponible sur l'appareil. Dans ce cas, la détection du mot clé logiciel est utilisée.STATE_HARDWARE_UNSUPPORTED
. L'assistance DSP n'est pas disponible en général, mais le DSP n'est pas compatible avec une combinaison de mots clés et de paramètres régionaux donnés. L'application peut choisir d'utiliser la détection de mot clé logiciel.STATE_HARDWARE_ENROLLED
. La détection des mots clés est prête et peut être lancée en appelant la méthodestartRecognition()
.STATE_HARDWARE_UNENROLLED
. Aucun modèle audio pour la phrase clé demandée n'est disponible, mais l'enregistrement est possible.
Vous pouvez enregistrer des modèles de son de détection de mot clé à 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
.
Il est possible que la détection des mots clés DSP ne soit pas disponible sur tous les appareils. Les développeurs VIA doivent vérifier les fonctionnalités matérielles à l'aide de la méthode getDspModuleProperties()
. Pour obtenir un exemple de code montrant comment enregistrer des modèles de son, consultez VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java
.
Pour en savoir plus sur la reconnaissance simultanée des mots clés, consultez la section Capture simultanée.
Détection de mot clé 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 qui pourraient avoir besoin d'accéder au micro, 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 sera 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 la reconnaissance vocale utilise cette fonctionnalité pour y accéder. Pour effectuer la reconnaissance vocale et avoir accès au micro, les VIA doivent détenir android.permission.RECORD_AUDIO
.
Les applications qui accèdent à une implémentation RecognitionService
doivent également disposer de cette autorisation.
Avant Android 10, l'accès au micro 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 micro peut être partagé. Pour en savoir plus, consultez la section Partager la saisie audio.
Accéder à la sortie audio
Lorsque le VIA est prêt à fournir des réponses verbales, il est important de suivre les consignes suivantes:
- Lorsque vous demandez la priorité audio ou que vous gérez la sortie audio, l'application doit utiliser
AudioAttributes#USAGE_ASSISTANT
etAudioAttributes#CONTENT_TYPE_SPEECH
comme attributs audio. - Lors de la reconnaissance vocale, la priorité audio doit être demandée avec
AudioManage#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
. Notez que certaines applications multimédias peuvent ne pas réagir correctement aux commandes multimédias (voir la section Exécuter des commandes multimédias) lorsque leur focus audio est supprimé.