Per implementare un'applicazione per le interazioni vocali (VIA), devi completare questi passaggi:
- Crea uno scheletro VIA.
- (Facoltativo) Implementa un flusso di configurazione/accesso.
- (Facoltativo) Implementa una schermata Impostazioni.
- Dichiara le autorizzazioni richieste nel file manifest.
- Implementa un'interfaccia utente per il riquadro vocale.
- Implementare il riconoscimento vocale (deve includere l'implementazione dell'API RecognitionService).
- Implementa l'enunciato (facoltativamente puoi implementare l'API TextToSpeech).
- Implementa il completamento dei comandi. Visualizza questi contenuti in Esecuzione dei comandi.
Le seguenti sezioni descrivono come completare ogni passaggio indicato sopra.
Crea uno scheletro VIA
Manifest
Viene rilevata un'app con Interazione vocale quando: incluse nel manifest:
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>
In questo esempio:
- Le ViA devono esporre un servizio che estenda
VoiceInteractionService
, con un filtro per intent per l'azioneVoiceInteractionService.SERVICE_INTERFACE ("android.service.voice.VoiceInteractionService")
. - Questo servizio deve disporre dell'autorizzazione di firma di sistema di
BIND_VOICE_INTERACTION
. - Questo servizio deve includere un file di metadati
android.voice_interaction
per contenere quanto segue: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" />
Per maggiori dettagli su ciascun campo, vedi R.styleable#VoiceInteractionService
.
Dato che tutti i VIA sono anche servizi di riconoscimento vocale, devi anche
includi quanto segue nel file manifest:
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>
I servizi di riconoscimento vocale richiedono anche i seguenti metadati:
res/xml/recognition_service.xml
<recognition-service xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="com.example.MyRecognizerSettingsActivity" />
VoiceInteractionService, VoiceInteractionSessionService e VoiceInteractionSession
Il seguente diagramma illustra il ciclo di vita di ciascuna di queste entità:
Figura 1. Cicli di vita
Come indicato in precedenza, VoiceInteractionService
è il punto di ingresso
in un VIA. Le principali responsabilità di questo servizio sono:
- Inizializza tutti i processi che devono essere mantenuti in esecuzione per tutto il tempo questo VIA è quello attivo. Ad esempio, rilevamento hotword.
- Consente di segnalare azioni vocali supportate (vedi Tocca per leggere dell'Assistente vocale).
- Avvia sessioni di interazione vocale dalla schermata di blocco (keyguard).
Nella sua forma più semplice, un'implementazione VoiceInteractionService sembra nel seguente modo:
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'implementazione di VoiceInteractionService#onGetSupportedVoiceActions()
è
necessari per gestire
Assistente vocale Tocca per leggere.
Il sistema utilizza un VoiceInteractionSessionService per creare e
interagire con VoiceInteractionSession. Ha una sola responsabilità,
per avviare nuove sessioni quando richiesto.
public class MyVoiceInteractionSessionService extends VoiceInteractionSessionService { @Override public VoiceInteractionSession onNewSession(Bundle args) { return new MyVoiceInteractionSession(this); } }
Infine, VoiceInteractionSession è il momento in cui si svolge la maggior parte del lavoro
che sarebbe stato fatto. Un'istanza di una singola sessione può essere riutilizzata per completare
le interazioni degli utenti. In AAOS esiste un helper CarVoiceInteractionSession
,
contribuendo a implementare alcune
funzionalità esclusive del settore automobilistico.
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
ha un'ampia gamma di metodi di callback
spiegate nelle sezioni seguenti. consulta la documentazione di VoiceInteractionSession
per un elenco completo.
Implementare un flusso di configurazione/accesso
La configurazione e l'accesso possono avvenire nei seguenti casi:
- Durante le operazioni preliminari del dispositivo (configurazione guidata).
- Durante lo scambio del servizio di interazione vocale (Impostazioni).
- Al primo avvio, quando l'app è selezionata.
Per maggiori dettagli sull'esperienza utente consigliata e sulle indicazioni visive, consulta Assistenti precaricati: indicazioni UX.
Configurazione durante lo scambio del servizio vocale
È sempre possibile che l'utente selezioni una VIA che non è stata configurato. Ciò può accadere perché:
- L'utente ha saltato completamente la configurazione guidata o l'utente ha saltato la voce passaggio per la configurazione dell'interazione.
- L'utente ha selezionato una VIA diversa da quella configurata durante il dispositivo l'onboarding.
In ogni caso, un VoiceInteractionService
ha diversi modi per incoraggiare l'utente
per completare la configurazione:
- Promemoria di notifica.
- Risposta vocale automatica quando l'utente prova a utilizzarla.
Nota: sconsigliamo vivamente di presentare un flusso di configurazione VIA senza una richiesta esplicita dell'utente. Ciò significa che le VM dovrebbero evitare visualizzazione di contenuti nell'interfaccia utente durante l'avvio del dispositivo o a seguito di un cambio dell'utente sblocca.
Promemoria notifica
Un promemoria di notifica è un modo non invasivo per indicare la necessità di una configurazione, e fornire agli utenti l'invito ad accedere alla configurazione dell'assistente flusso di lavoro.
Figura 2. Promemoria notifica
Ecco come funziona questo flusso:
Figura 3. Flusso di promemoria delle notifiche
Risposta vocale
Questo è il flusso più semplice da implementare, con l'avvio di un'espressione
un callback VoiceInteractionSession#onShow()
, che spiega all'utente cosa
deve essere completata, quindi chiedi (se la configurazione è consentita in base allo stato di restrizione UX)
se il cliente vuole avviare
il flusso di configurazione. Se al momento non è possibile effettuare la configurazione, spiega:
anche in questa situazione.
Configurazione al primo utilizzo
L'utente può sempre attivare una VIA che non è stata configurato. In questi casi:
- Comunica a voce l'utente in merito alla situazione (ad esempio, "Per funzionare correttamente, Devi completare alcuni passaggi ... ").
- Se il motore delle limitazioni UX lo consente (vedi UX_RESTRICTIONS_NO_CONFIGURAZIONE), chiedi all'utente se vuole avviare la processo di configurazione e apri la schermata Impostazioni per il VIA.
- In caso contrario, ad esempio se l'utente sta guidando, lascia una notifica in modo che possa fai clic sull'opzione quando puoi farlo in sicurezza.
Creare schermate di configurazione per l'interazione vocale
Le schermate di configurazione e di accesso devono essere sviluppate come normali attività. Consulta le le linee guida visive e relative all'esperienza utente per lo sviluppo della UI in Assistenti precaricati: indicazioni UX.
Linee guida generali:
- Le Via devono consentire agli utenti di interrompere e riprendere la configurazione in qualsiasi momento.
- La configurazione non deve essere consentita se è attiva la limitazione di
UX_RESTRICTIONS_NO_SETUP
. Per maggiori dettagli, vedi Linee guida sulla distrazione per chi guida. - Le schermate di configurazione devono corrispondere al sistema di progettazione di ciascun veicolo. Schermata generale layout, icone, colori e altri aspetti devono essere coerenti con il resto dell'interfaccia utente. Consulta Personalizzazione per maggiori dettagli.
Implementazione di una schermata delle impostazioni
Figura 4. Integrazione delle impostazioni
Le schermate delle impostazioni sono le normali attività di Android. Se implementato, il relativo punto di ingresso
deve essere dichiarato in res/xml/interaction_service.xml
nell'ambito della VIA
(vedi
manifest).
La sezione Impostazioni è un buon posto per continuare la configurazione e l'accesso (se l'utente non ha completato
) oppure offrire un'opzione per uscire o cambiare utente, se necessario. Simile alla configurazione
descritte sopra, queste schermate devono:
- Dare l'opzione per tornare alla schermata precedente nell'elenco filtri (ad esempio, Impostazioni auto).
- Non è consentita durante la guida. Per maggiori dettagli, consulta le linee guida sulla distrazione del conducente.
- Abbina ogni sistema di progettazione del veicolo. Per maggiori dettagli, vedi Personalizzazione.
Dichiara le autorizzazioni richieste nel file manifest
Le autorizzazioni richieste da un VIA possono essere suddivise in tre categorie:
- Autorizzazioni di firma del sistema. Queste sono le autorizzazioni concessa soltanto agli APK preinstallati firmati dal sistema. Gli utenti non possono concedere queste autorizzazioni, solo gli OEM possono concederle durante la creazione delle immagini di sistema. Per ulteriori informazioni su come ottenere le autorizzazioni di firma, vedi Concedere autorizzazioni con privilegi di sistema.
- Autorizzazioni pericolose. Queste sono le autorizzazioni che un utente deve concedere usando la finestra di dialogo PermissionsController. Gli OEM possono pre-concessione alcuni di questi le autorizzazioni per il servizio VoiceInteractionService predefinito. Ma dato che questa impostazione potrebbero cambiare da dispositivo a dispositivo, le app devono poter richiedere questi le autorizzazioni quando necessario.
- Altre autorizzazioni. Queste sono tutte le altre autorizzazioni non richiedono l'intervento dell'utente. Queste autorizzazioni vengono concesse automaticamente dal sistema.
Considerato quanto sopra, la seguente sezione si concentra solo sulla richiesta autorizzazioni pericolose. Le autorizzazioni devono essere richieste solo mentre l'utente nelle schermate di accesso o di impostazione.
Se l'app non dispone delle autorizzazioni necessarie per funzionare, la procedura consigliata è quella di utilizzare un enunciato vocale per spiegare la situazione al all'utente e una notifica per fornire un'invito che l'utente può utilizzare per torna alle schermate delle impostazioni di VIA. Per maggiori dettagli, vedi 1. Promemoria di notifica.
Richiedi le autorizzazioni nella schermata delle impostazioni
Le autorizzazioni pericolose vengono richieste utilizzando il normale metodo ActivityCompat#requestPermission()
(o equivalente). Per maggiori dettagli su come richiedere le autorizzazioni, consulta
Richiedi autorizzazioni app.
Figura 5. Richiedi autorizzazioni
Autorizzazione listener di notifiche
Per implementare il flusso TTR, i VIA devono essere designati come listener di notifiche. Non si tratta di un'autorizzazione a sé stante, ma di un'autorizzazione che consente al sistema di inviare notifiche agli utenti e ascoltatori. Per sapere se alla VIA è stato concesso l'accesso a queste informazioni, le app possono:
- (Facoltativo) Controlla in anticipo se sono presenti listener di notifiche utilizzando
CarAssistUtils#assistantIsNotificationListener()
. Questa operazione può essere eseguita, ad esempio, durante il flusso di configurazione. - (Obbligatorio) Reagisci alla gestione di
CarVoiceInteractionSession#onShow()
con l'azioneVOICE_ACTION_HANDLE_EXCEPTION
e l'eccezioneEXCEPTION_NOTIFICATION_LISTENER_PERMISSIONS_MISSING
.
Se questo accesso non viene concesso in anticipo, la VIA deve indirizzare l'utente alla Sezione Accesso alle notifiche di Impostazioni auto, utilizzando una combinazione di frasi e notifiche. Il seguente codice può essere usato per aprire la sezione appropriata del app impostazioni:
private void requestNotificationListenerAccess() { Intent intent = new Intent(Settings .ACTION_NOTIFICATION_LISTENER_SETTINGS); intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName()); startActivity(intent); }
Implementa un'interfaccia utente per il riquadro vocale
Quando un VoiceInteractionSession
riceve una richiamata di onShow()
,
può presentare una UI di riquadro vocale. Per le linee guida relative alle immagini e all'esperienza utente relative all'implementazione della finestra vocale,consulta:
Assistenti precaricati: indicazioni UX.
Figura 6. Visualizzazione della finestra di conversazione
Esistono due opzioni per implementare questa UI:
- Esegui l'override di
VoiceInteractionSession#onCreateContentView()
- Lancia un'attività utilizzando
VoiceInteractionSession#startAssistantActivity()
Utilizzare onCreateContentView()
Questo è il modo predefinito per presentare una finestra di conversazione. VoiceInteractionSession
una classe base crea una finestra e gestisce il suo ciclo di vita per tutto il tempo mediante una voce
la sessione è attiva. Le app devono sostituire VoiceInteractionSession#onCreateContentView()
e restituire una visualizzazione allegata a quella finestra non appena la sessione
è stato creato. Questa visualizzazione inizialmente dovrebbe essere invisibile. Quando inizia un'interazione vocale,
questa vista deve essere resa visibile su VoiceInteractionSession#onShow()
e poi di nuovo invisibile il giorno 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); } … }
Quando utilizzi questo metodo, potrebbe essere opportuno modificare VoiceInteractionSession#onComputeInsets()
per tenere conto delle aree oscurate della UI.
Usa startAssistantActivity()
In questo caso, VoiceInteractionSession
delega la gestione della voce
a una normale attività. Quando viene utilizzata questa opzione, viene applicata una VoiceInteractionSession
deve disattivare la creazione della relativa finestra di contenuto predefinita (vedi Utilizzo di onCreateContentView()) nella onPrepareShow()
di Google. Alle ore VoiceInteractionSession#onShow()
, la sessione avvierà la voce
attività durante una targa utilizzando VoiceInteractionSession#startAssistantActivity()
. Questo
avvia la UI con le impostazioni della finestra e i flag di attività corretti.
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); } … }
Per mantenere una comunicazione tra questa attività e il
VoiceInteractionSession
, un insieme di intent interni o di associazione di servizi potrebbe essere
obbligatorio. Ad esempio, quando viene richiamato VoiceInteractionSession#onHide()
, il parametro
La sessione deve essere in grado di passare questa richiesta all'attività.
Importante: Nel settore auto e motori, vengono visualizzate solo
attività o attività elencate nella "lista consentita" dell'UXR possono essere visualizzati
alla guida. Questo vale per le attività iniziate con
VoiceInteractionSession#startAssistantActivity()
. Ricorda di prestare attenzione
annota la tua attività con <meta-data
android:name="distractionOptimized" android:value="true"/>
o includi questo
attività nella chiave systemActivityWhitelist
di /packages/services/Car/service/res/values/config.xml
. Per ulteriori informazioni, vedi Driver
Linee guida sulla distrazione.
Implementare il riconoscimento vocale
In questa sezione imparerai a implementare il riconoscimento vocale tramite l'app e riconoscimento delle hotword. Una hotword è una parola di attivazione utilizzata per avviare una nuova query o un'azione vocale. Ad esempio, "Hey Google" o "Hey Google".
Rilevamento hotword DSP
Android fornisce l'accesso a un rilevatore hotword sempre attivo a livello di DSP
di AlwaysOnHotwordDetector
.
per implementare il rilevamento della hotword con CPU ridotta. L'utilizzo di questa funzionalità è
diviso in due parti:
- Creazione di un'istanza di un
AlwaysOnHotwordDetector
. - Registrazione di un modello audio per il rilevamento della hotword.
L'implementazione di VoiceInteractionService può creare un rilevatore hotword utilizzando
VoiceInteractionService#createAlwaysOnHotwordDetector()
,
passando una frase chiave e una lingua da usare per il rilevamento. Di conseguenza,
l'app riceve un onAvailabilityChanged()
con uno dei seguenti valori possibili:
STATE_HARDWARE_UNAVAILABLE
. La funzionalità DSP non è disponibile nella dispositivo. In questo caso, viene utilizzato il rilevamento hotword software.STATE_HARDWARE_UNSUPPORTED
. Il supporto DSP non è disponibile in generale, ma Il DSP non supporta la combinazione di frase chiave e lingua. L'app può scegliere di utilizzare Rilevamento hotword.STATE_HARDWARE_ENROLLED
. Il rilevamento hotword è pronto e può essere avviato chiamando il metodostartRecognition()
.STATE_HARDWARE_UNENROLLED
. Un modello audio per la frase chiave richiesta non è disponibile, ma è possibile registrarsi.
La registrazione dei modelli audio per il rilevamento della hotword può essere effettuata utilizzando IVoiceInteractionManagerService#updateKeyphraseSoundModel()
.
Nel sistema possono essere registrati più modelli contemporaneamente, ma solo uno
modello è associato a un AlwaysOnHotwordDetector
.
Il rilevamento della hotword DSP potrebbe non essere disponibile su tutti i dispositivi. Sviluppatori VIA
dovrebbe controllare le funzionalità hardware utilizzando getDspModuleProperties()
. Per vedere il codice di esempio
su come registrare i modelli audio, visita la pagina VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java
.
Consulta Acquisizione simultanea per informazioni
riconoscimento hotword simultaneo.
Rilevamento hotword software
Come indicato sopra, il rilevamento della hotword DSP potrebbe non essere disponibile in tutti (ad esempio, l'emulatore Android non fornisce l'emulazione DSP). In questo caso, il riconoscimento vocale tramite software è l'unica alternativa. Per evitare interferenze con altri alle app che potrebbero richiedere l'accesso al microfono, i VIA devono accedere all'input audio utilizzando:
- L'acquisizione dell'audio deve utilizzare MediaRecorder.AudioSource.HOTWORD.
- Blocca l'autorizzazione
android.Manifest.permission.CAPTURE_AUDIO_HOTWORD
.
Entrambe queste costanti sono @hide
e disponibili solo per le app in bundle.
Gestisci l'input audio e il riconoscimento vocale
L'input audio verrebbe implementato utilizzando la classe MediaRecorder.
Per ulteriori informazioni su come utilizzare questa API, consulta MediaRecorder
Panoramica. Anche i servizi di interazione vocale dovrebbero essere RecognitionService
implementazioni di classe. Qualsiasi app nel sistema che richiede il riconoscimento vocale utilizza
per accedere a questa funzionalità. Per eseguire il riconoscimento vocale e avere accesso al microfono, ViA
deve contenere android.permission.RECORD_AUDIO
.
App che accedono a un RecognitionService
anche l'implementazione deve avere questa autorizzazione.
Prima di Android 10, l'accesso al microfono veniva concesso a una sola app alla volta orario (ad eccezione del rilevamento della hotword, vedi sopra). A partire da Android 10, L'accesso al microfono può essere condiviso. Per ulteriori informazioni, consulta la sezione Condivisione Ingresso audio.
Accedi all'uscita audio
Quando la VIA è pronta a fornire risposte verbali, è importante segui queste linee guida:
- Per richiedere la messa a fuoco audio o gestire l'output audio, l'app
deve utilizzare
AudioAttributes#USAGE_ASSISTANT
eAudioAttributes#CONTENT_TYPE_SPEECH
come attributi audio. - Durante il riconoscimento vocale, la messa a fuoco audio deve essere richiesta con
AudioManage#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
. Tieni presente che alcune app multimediali potrebbero non reagire correttamente ai comandi multimediali (vedi Fulfilling Media Commands) mentre l'audio viene rimosso lo stato attivo.