Sviluppo di app

Per implementare un'applicazione di interazione vocale (VIA), completare questi passaggi:

  1. Crea uno scheletro VIA.
  2. ( facoltativo ) Implementare un flusso di configurazione/accesso.
  3. ( facoltativo ) Implementare una schermata Impostazioni.
  4. Dichiarare le autorizzazioni richieste nel file manifest.
  5. Implementare un'interfaccia utente della targa vocale.
  6. Implementare il riconoscimento vocale (deve includere l'implementazione dell'API RecognitionService).
  7. Implementare l'espressione (facoltativamente, è possibile implementare l'API TextToSpeech).
  8. Implementare l'adempimento dei comandi. Vedi questo contenuto in Esecuzione dei comandi .

Le sezioni seguenti descrivono come completare ciascun passaggio sopra menzionato.

Crea uno scheletro VIA

Manifesta

Un'app viene rilevata come un'app con interazione vocale quando nel manifest è incluso quanto segue:

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:

  • I VIA devono esporre un servizio che estende VoiceInteractionService , con un filtro di intenti per l'azione VoiceInteractionService.SERVICE_INTERFACE ("android.service.voice.VoiceInteractionService") .
  • Questo servizio deve contenere l'autorizzazione per la firma del sistema BIND_VOICE_INTERACTION .
  • Questo servizio dovrebbe 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 informazioni dettagliate su ciascun campo, vedere R.styleable#VoiceInteractionService . Dato che tutti i VIA sono anche servizi di riconoscimento vocale, devi includere anche quanto segue nel tuo 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 diagramma seguente illustra il ciclo di vita di ciascuna di queste entità:

Cicli vitali

Figura 1. Cicli di vita

Come affermato in precedenza, VoiceInteractionService è il punto di accesso a un VIA. Le principali responsabilità di questo servizio sono:

  • Inizializza tutti i processi che dovrebbero essere mantenuti in esecuzione finché questo VIA è attivo. Ad esempio, il rilevamento delle hotword.
  • Segnala le azioni vocali supportate (vedi Assistente vocale Tocca per leggere ).
  • Avvia sessioni di interazione vocale dalla schermata di blocco (blocco tastiera).

Nella sua forma più semplice, un'implementazione di VoiceInteractionService sarebbe simile a questa:

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() è necessaria per gestire la funzione Tap-to-Read dell'Assistente vocale . Un VoiceInteractionSessionService viene utilizzato dal sistema per creare e interagire con un VoiceInteractionSession . Ha solo una responsabilità, avviare nuove sessioni quando richiesto.

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

Infine, una VoiceInteractionSession è il luogo in cui verrà svolta la maggior parte del lavoro. Una singola istanza di sessione potrebbe essere riutilizzata per completare più interazioni utente. In AAOS esiste un helper CarVoiceInteractionSession , che aiuta a implementare alcune delle funzionalità uniche 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 dispone di un ampio set di metodi di callback spiegati nelle sezioni seguenti. vedere la documentazione per VoiceInteractionSession per un elenco completo.

Implementare un flusso di configurazione/accesso

La configurazione e l'accesso possono verificarsi:

  • Durante l'onboarding del dispositivo (configurazione guidata).
  • Durante lo scambio del servizio di interazione vocale (Impostazioni).
  • Al primo avvio quando l'app è selezionata.

Per informazioni dettagliate sull'esperienza utente consigliata e sulla guida visiva, vedere Assistenti precaricati: guida UX .

Configurazione durante lo scambio del servizio vocale

È sempre possibile per l'utente selezionare un VIA che non è stato configurato correttamente. Ciò può accadere perché:

  • L'utente ha saltato completamente la configurazione guidata oppure ha saltato il passaggio di configurazione dell'interazione vocale.
  • L'utente ha selezionato un VIA diverso da quello configurato durante l'onboarding del dispositivo.

In ogni caso, un VoiceInteractionService ha diversi modi per incoraggiare l'utente a completare la configurazione:

  • Promemoria di notifica.
  • Risposta vocale automatica quando l'utente tenta di utilizzarlo.

Nota : è fortemente sconsigliato presentare un flusso di configurazione VIA senza una richiesta esplicita dell'utente. Ciò significa che i VIA dovrebbero evitare di visualizzare automaticamente il contenuto sull'HU durante l'avvio del dispositivo o in seguito al cambio o allo sblocco dell'utente.

Promemoria di notifica

Un promemoria di notifica è un modo non invasivo per indicare la necessità di configurazione e per fornire agli utenti la possibilità di navigare nel flusso di configurazione dell'assistente.

Promemoria di notifica

Figura 2. Promemoria di notifica

Ecco come funzionerebbe questo flusso:

Flusso di promemoria delle notifiche

Figura 3. Flusso di promemoria delle notifiche

Risposta vocale

Questo è il flusso più semplice da implementare, avviando un'espressione su un callback VoiceInteractionSession#onShow() , spiegando all'utente cosa deve essere fatto e quindi chiedendogli (se la configurazione è consentita dato lo stato di restrizione UX) se desidera avviare il flusso di configurazione. Se la configurazione non è possibile in quel momento, spiega anche questa situazione.

Configurazione al primo utilizzo

È sempre possibile per l'utente attivare un VIA che non è stato configurato correttamente. In tali casi:

  1. Informa verbalmente l'utente di questa situazione (ad esempio: "Per funzionare correttamente, ho bisogno che tu completi alcuni passaggi…").
  2. Se il motore delle restrizioni UX lo consente (vedi UX_RESTRICTIONS_NO_SETUP ), chiedi all'utente se desidera avviare il processo di configurazione e quindi aprire la schermata Impostazioni per VIA.
  3. Altrimenti (ad esempio, se l'utente sta guidando), lascia una notifica affinché l'utente possa fare clic sull'opzione quando è sicuro farlo.

Crea schermate di configurazione dell'interazione vocale

Le schermate di configurazione e di accesso dovrebbero essere sviluppate come attività regolari. Consulta le linee guida visive e UX per lo sviluppo dell'interfaccia utente in Assistenti precaricati: linee guida UX .

Linee guida generali:

  • I VIA dovrebbero consentire agli utenti di interrompere e riprendere la configurazione in qualsiasi momento.
  • L'installazione non dovrebbe essere consentita se è attiva la restrizione UX_RESTRICTIONS_NO_SETUP . Per i dettagli, vedere Linee guida per la distrazione del conducente .
  • Le schermate di configurazione devono corrispondere al sistema di progettazione di ciascun veicolo. Il layout generale dello schermo, le icone, i colori e altri aspetti devono essere coerenti con il resto dell'interfaccia utente. Vedi Personalizzazione per i dettagli.

Implementare una schermata delle impostazioni

Integrazione delle impostazioni

Figura 4. Integrazione delle impostazioni

Le schermate delle impostazioni sono normali attività Android. Se implementato, il relativo punto di ingresso deve essere dichiarato in res/xml/interaction_service.xml come parte dei manifesti VIA (vedere Manifests ). La sezione Impostazioni è un buon posto per continuare la configurazione e l'accesso (se l'utente non l'ha completata) o offrire un'opzione di disconnessione o cambio utente, se necessario. Simili alle schermate di configurazione descritte sopra, queste schermate dovrebbero:

  • Fornire la possibilità di tornare alla schermata precedente nella pila di schermate (ad esempio, alle Impostazioni auto).
  • Non essere consentito durante la guida. Per i dettagli, vedere Linee guida per la distrazione del conducente .
  • Abbina ciascun sistema di progettazione del veicolo. Per i dettagli, vedere Personalizzazione .

Dichiarare le autorizzazioni richieste nel file manifest

Le autorizzazioni richieste da un VIA possono essere suddivise in tre categorie:

  • Autorizzazioni per la firma del sistema. Si tratta di autorizzazioni concesse solo agli APK preinstallati e firmati dal sistema. Gli utenti non sono in grado di concedere queste autorizzazioni, solo gli OEM possono concederle quando creano le proprie immagini di sistema. Per ulteriori informazioni su come ottenere le autorizzazioni per la firma, vedere Concedere autorizzazioni con privilegi di sistema .
  • Permessi pericolosi. Si tratta delle autorizzazioni che un utente deve concedere utilizzando la finestra di dialogo PermissionsController. Gli OEM possono preconcedere alcune di queste autorizzazioni al VoiceInteractionService predefinito. Ma dato che questa impostazione predefinita potrebbe cambiare da dispositivo a dispositivo, le app dovrebbero essere in grado di richiedere queste autorizzazioni quando necessario.
  • Altre autorizzazioni. Queste sono tutte le altre autorizzazioni che non richiedono l'intervento dell'utente. Queste autorizzazioni vengono concesse automaticamente dal sistema.

Considerato quanto sopra, la sezione seguente si concentra solo sulla richiesta di autorizzazioni pericolose. Le autorizzazioni devono essere richieste solo mentre l'utente si trova nelle schermate di accesso o di impostazione.

Se l'app non dispone delle autorizzazioni necessarie per funzionare, il flusso consigliato consiste nell'utilizzare un'espressione vocale per spiegare la situazione all'utente e una notifica per fornire un'affordance che l'utente può utilizzare per tornare alle schermate delle impostazioni VIA . Per i dettagli, vedere 1. Promemoria di notifica .

Richiedi le autorizzazioni come parte della schermata delle impostazioni

Le autorizzazioni pericolose vengono richieste utilizzando il normale metodo ActivityCompat#requestPermission() (o equivalente). Per informazioni dettagliate su come richiedere le autorizzazioni, vedere Richiedere autorizzazioni per l'app .

Richiedi autorizzazioni

Figura 5. Richiedi autorizzazioni

Autorizzazione ascoltatore di notifiche

Per implementare il flusso TTR, i VIA devono essere designati come ascoltatori di notifiche. Questa non è un'autorizzazione di per sé, ma piuttosto una configurazione che consente al sistema di inviare notifiche agli ascoltatori registrati. Per sapere se al VIA è stato concesso l'accesso a queste informazioni, le app possono:

Se questo accesso non è concesso in anticipo, VIA dovrebbe indirizzare l'utente alla sezione Accesso alle notifiche delle Impostazioni dell'auto, utilizzando una combinazione di espressioni e notifiche. Il seguente codice può essere utilizzato per aprire la sezione appropriata dell'app Impostazioni:

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

Implementare un'interfaccia utente della targa vocale

Quando una VoiceInteractionSession riceve una richiamata onShow() , può presentare un'interfaccia utente della targa vocale. Per le linee guida visive e UX sull'implementazione della piastra vocale, vedere Assistenti precaricati: guida UX .

Visualizzazione della targa vocale

Figura 6. Visualizzazione della targa vocale

Sono disponibili due opzioni su come implementare questa interfaccia utente:

  • Sostituisci VoiceInteractionSession#onCreateContentView()
  • Avvia un'attività utilizzando VoiceInteractionSession#startAssistantActivity()

Utilizza onCreateContentView()

Questo è il modo predefinito di presentare una targa vocale. La classe base VoiceInteractionSession crea una finestra e ne gestisce il ciclo di vita finché è attiva una sessione vocale. Le app devono sovrascrivere VoiceInteractionSession#onCreateContentView() e restituire una visualizzazione allegata a quella finestra non appena viene creata la sessione. Questa vista dovrebbe inizialmente essere invisibile. Quando inizia un'interazione vocale, questa vista dovrebbe essere resa visibile su VoiceInteractionSession#onShow() e quindi nuovamente invisibile su 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, potresti voler regolare VoiceInteractionSession#onComputeInsets() per tenere conto delle aree oscurate dell'interfaccia utente.

Utilizza startAssistantActivity()

In questo caso, VoiceInteractionSession delega la gestione dell'interfaccia utente della targa vocale a un'attività regolare. Quando viene utilizzata questa opzione, un'implementazione VoiceInteractionSession deve disabilitare la creazione della relativa finestra di contenuto predefinita (vedere Utilizzo di onCreateContentView() ) sul callback onPrepareShow() . A VoiceInteractionSession#onShow() , la sessione avvierebbe l'attività della targa vocale utilizzando VoiceInteractionSession#startAssistantActivity() . Questo metodo avvia l'interfaccia utente 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 VoiceInteractionSession , potrebbe essere necessario un set di intenti interni o un'associazione al servizio. Ad esempio, quando viene richiamato VoiceInteractionSession#onHide() , la sessione deve essere in grado di passare questa richiesta all'attività.

Importante. In Automotive, durante la guida è possibile visualizzare solo le attività con annotazioni specifiche o le attività elencate nella "lista consentita" UXR. Questo vale anche per le attività avviate con VoiceInteractionSession#startAssistantActivity() . Ricordati di annotare la tua attività con <meta-data android:name="distractionOptimized" android:value="true"/> o di includere questa attività nella chiave systemActivityWhitelist di /packages/services/Car/service/res/values/config.xml file /packages/services/Car/service/res/values/config.xml . Per ulteriori informazioni, vedere Linee guida per la distrazione del conducente .

Implementare il riconoscimento vocale

In questa sezione imparerai come implementare il riconoscimento vocale attraverso il rilevamento e il riconoscimento delle hotword. Una hotword è una parola chiave utilizzata per avviare una nuova query o azione tramite voce. Ad esempio, "OK Google" o "Ehi Google".

Rilevamento hotword DSP

Android fornisce l'accesso a un rilevatore di hotword sempre attivo a livello DSP tramite AlwaysOnHotwordDetector . modo per implementare il rilevamento delle hotword con poca CPU. L'utilizzo di questa funzionalità è diviso in due parti:

L'implementazione di VoiceInteractionService può creare un rilevatore di hotword utilizzando VoiceInteractionService#createAlwaysOnHotwordDetector() , passando una frase chiave e le impostazioni internazionali che desiderano utilizzare per il rilevamento. Di conseguenza, l'app riceve una richiamata onAvailabilityChanged() con uno dei seguenti valori possibili:

  • STATE_HARDWARE_UNAVAILABLE . La funzionalità DSP non è disponibile sul dispositivo. In questo caso viene utilizzato il rilevamento hotword software.
  • STATE_HARDWARE_UNSUPPORTED . Il supporto DSP non è disponibile in generale, ma DSP non supporta determinate combinazioni di frasi chiave e impostazioni locali. L'app può scegliere di utilizzare il software Hotword Detection .
  • STATE_HARDWARE_ENROLLED . Il rilevamento delle hot word è pronto e può essere avviato chiamando il metodo startRecognition() .
  • STATE_HARDWARE_UNENROLLED . Non è disponibile un modello sonoro per la frase chiave richiesta, ma è possibile registrarsi.

La registrazione dei modelli audio di rilevamento hotword può essere eseguita utilizzando IVoiceInteractionManagerService#updateKeyphraseSoundModel() . È possibile registrare più modelli nel sistema contemporaneamente, ma solo un modello è associato a AlwaysOnHotwordDetector . Il rilevamento hotword DSP potrebbe non essere disponibile in tutti i dispositivi. Gli sviluppatori VIA dovrebbero verificare le funzionalità hardware utilizzando il metodo getDspModuleProperties() . Per un codice di esempio che mostra come registrare i modelli audio, consulta VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java . Vedere Acquisizione simultanea per quanto riguarda il riconoscimento simultaneo di hotword.

Rilevamento hotword software

Come indicato in precedenza, il rilevamento delle hotword DSP potrebbe non essere disponibile in tutti i dispositivi (ad esempio, l'emulatore Android non fornisce l'emulazione DSP). In questo caso, il riconoscimento vocale software è l’unica alternativa. Per evitare di interferire con altre app che potrebbero richiedere l'accesso al microfono, i VIA devono accedere all'input audio utilizzando:

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, vedere la panoramica di MediaRecorder . Si prevede che anche i servizi di interazione vocale siano implementazioni della classe RecognitionService . 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, i VIA devono contenere android.permission.RECORD_AUDIO . È previsto che anche le app che accedono a un'implementazione RecognitionService dispongano di questa autorizzazione.

Prima di Android 10, l'accesso al microfono veniva concesso a una sola app alla volta (ad eccezione del rilevamento hotword, vedi sopra). A partire da Android 10, l'accesso al microfono può essere condiviso. Per ulteriori informazioni vedere Condivisione dell'input audio .

Accedi all'uscita audio

Quando il VIA è pronto a fornire risposte verbali, è importante seguire la seguente serie di linee guida: