Assistente vocale Tocca per leggere

Android Automotive considera la voce un componente fondamentale per le interazioni di guida sicura e uno dei modi più sicuri per gli utenti di interagire con il sistema operativo Android Automotive durante la guida. Di conseguenza, abbiamo ampliato le API di assistenti vocali Android (inclusa VoiceInteractionSession) per consentire agli assistenti vocali di eseguire per gli utenti attività che possono essere difficili da svolgere durante la guida.

La funzionalità Tocca per leggere consente agli assistenti vocali di leggere e rispondere ai messaggi per conto dell'utente quando quest'ultimo interagisce con le notifiche dei messaggi. Per fornire questa funzionalità, puoi integrare un assistente vocale conCarVoiceInteractionSession.

In Automotive, le notifiche pubblicate nel Centro notifiche identificate come INBOX o INBOX_IN_GROUP (ad esempio i messaggi SMS) includono un pulsante Riproduci. L'utente può fare clic su Riproduci per fare in modo che l'assistente vocale selezionato legga la notifica ad alta voce e, facoltativamente, rispondere tramite comandi vocali.

Notifica tocca per leggere

Figura 1. Notifica con tocco per leggere con pulsante Riproduci.

Eseguire l'integrazione con CarVoiceInteractionSession

Le sezioni seguenti descrivono come integrare un assistente vocale con CarVoiceInteractionSession.

Supportare le interazioni vocali

Le app che forniscono servizi di interazione vocale con l'auto devono integrarsi con le interazioni vocali Android esistenti. Per saperne di più, consulta Assistente Google per Android (ad eccezione di VoiceInteractionSession). Sebbene tutti gli elementi dell'API di interazione vocale rimangano invariati rispetto a quelli implementati sui dispositivi mobili, CarVoiceInteractionSession (descritto in Implementare CarVoiceInteractionSession) sostituisce VoiceInteractionSession. Per ulteriori informazioni, consulta queste pagine:

Implementa CarVoiceInteractionSession

CarVoiceInteractionSession espone API che puoi utilizzare per consentire agli assistenti vocali di leggere gli SMS e poi rispondere per conto dell'utente.

La differenza principale tra le classi CarVoiceInteractionSession e VoiceInteractionSession è che CarVoiceInteractionSession passa l'azione in onShow in modo che l'assistente vocale possa rilevare il contesto della richiesta dell'utente non appena CarVoiceInteractionSession avvia una sessione. I parametri per onShow per ogni classe sono elencati nella tabella seguente:

CarVoiceInteractionSession VoiceInteractionSession
onShow accetta questi tre parametri:
  • args
  • showFlags
  • actions
onShow accetta questi due parametri:
  • args
  • showFlags

Modifiche in Android 10

A partire da Android 10, la piattaforma chiama VoiceInteractionService.onGetSupportedVoiceActions per rilevare le azioni supportate. L'assistente vocale sostituisce e implementa VoiceInteractionService.onGetSupportedVoiceActions, come mostrato nell'esempio seguente:

public class MyInteractionService extends VoiceInteractionService {
    private static final List SUPPORTED_VOICE_ACTIONS = Arrays.asList(
        CarVoiceInteractionSession.VOICE_ACTION_READ_NOTIFICATION);

    @Override
    public Set onGetSupportedVoiceActions(@NonNull Set voiceActions) {
       Set result = new HashSet<>(voiceActions);
       result.retainAll(SUPPORTED_VOICE_ACTIONS);
       return result;
   }
}

Le azioni valide sono descritte nella tabella seguente. Per informazioni dettagliate su ogni azione, consulta Diagrammi di sequenza.

Azione Payload previsto Azione di interazione vocale prevista
VOICE_ACTION_READ_NOTIFICATION Leggi i messaggi all'utente e poi riattiva l'intent Contrassegna come letto in attesa quando i messaggi sono stati letti correttamente. Se vuoi, chiedi all'utente di rispondere.
VOICE_ACTION_REPLY_NOTIFICATION Parcellabile con chiave.
KEY_NOTIFICATION che corrisponde a StatusBarNotification.
Richiede android.permission.BIND_NOTIFICATION_LISTENER_SERVICE.
Chiedi all'utente di indicare il messaggio di risposta, inserisci il messaggio di risposta nel RemoteInputReply dell'intent in attesa e poi attiva l'intent in attesa.
VOICE_ACTION_HANDLE_EXCEPTION Stringa con chiave.
KEY_EXCEPTION che corrisponde a ExceptionValue (descritto in Valori di eccezione).
KEY_FALLBACK_ASSISTANT_ENABLED che mappa a un valore booleano. Se il valore è true, l'assistente di riserva che può gestire la richiesta dell'utente è stato disattivato.
L'azione prevista per l'eccezione è definita nella documentazione relativa all'eccezione.

Valori di eccezione

EXCEPTION_NOTIFICATION_LISTENER_PERMISSIONS_MISSING indica all'assistente vocale che manca l'autorizzazione Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE e di richiederla all'utente.

Richiedi l'autorizzazione di ascoltatore di notifiche

Se l'assistente vocale predefinito non dispone dell'autorizzazione di ascoltatore di notifiche, FallbackAssistant della piattaforma (se abilitato dal produttore dell'auto) potrebbe leggere il messaggio ad alta voce prima che all'assistente vocale venga inviata la notifica per richiedere l'autorizzazione. Per determinare se FallbackAssistant è attivato e ha letto il messaggio, l'assistente vocale deve controllare il valore booleano KEY_FALLBACK_ASSISTANT_ENABLED nel payload.

La piattaforma consiglia all'assistente vocale di aggiungere una logica di limitazione della frequenza per il numero di volte in cui viene richiesta questa autorizzazione. In questo modo, viene rispettato l'utente che non vuole concedere all'assistente vocale questa autorizzazione e preferisce che sia FallbackAssistant a leggere gli SMS ad alta voce. Richiedere all'utente l'autorizzazione ogni volta che preme Riproduci su una notifica del messaggio può essere un'esperienza utente negativa. La piattaforma non impone limiti di frequenza per conto dell'assistente vocale.

Quando richiede l'autorizzazione di accesso alle notifiche, l'assistente vocale deve usare CarUxRestrictionsManager per determinare se un utente è parcheggiato o sta guidando. Se l'utente è alla guida, l'assistente vocale visualizza una notifica con le istruzioni su come concedere l'autorizzazione. In questo modo, aiuti (e ricordi) all'utente di concedere l'autorizzazione quando è più sicuro.

Utilizzare StatusBarNotification

I valori StatusBarNotification passati con le azioni vocali Leggi e Rispondi sono sempre in una notifica di messaggistica compatibile con l'auto, come descritto in Avvisare gli utenti dei messaggi. Anche se alcune notifiche potrebbero non avere l'intent Rispondere in attesa, tutte hanno l'intent Contrassegna come letta in attesa.

Per semplificare le interazioni con le notifiche, utilizza NotificationPayloadHandler, che fornisce metodi per estrarre i messaggi dalla notifica e scrivere i messaggi di risposta all'intent in attesa appropriato della notifica. Dopo che l'assistente vocale ha letto il messaggio, deve attivare l'intent Contrassegnato come letto.

Soddisfare le precondizioni di Tocca per leggere

Solo VoiceInteractionSession dell'assistente vocale predefinito viene informato quando un utente attiva l'azione vocale per leggere e rispondere ai messaggi. Come accennato in precedenza, questo assistente vocale predefinito deve anche avere l'autorizzazione di ascoltatore di notifiche.

Diagrammi di sequenza

Queste figure mostrano i flussi di logica di CarVoiceInteractionSession actions:

VOICE_ACTION_READ_NOTIFICATION

Figura 2. Diagramma di sequenza per VOICE_ACTION_READ_NOTIFICATION.

Nel caso della Figura 3, è consigliabile l'applicazione di limiti di frequenza alle richieste di autorizzazione:

VOICE_ACTION_REPLY_NOTIFICATION

Figura 3. Diagramma di sequenza per VOICE_ACTION_REPLY_NOTIFICATION.

VOICE_ACTION_HANDLE_EXCEPTION

Figura 4. Diagramma di sequenza per VOICE_ACTION_HANDLE_EXCEPTION.

Leggi il nome dell'app

Se vuoi che l'assistente vocale legga il nome dell'app di messaggistica durante la lettura del messaggio (ad esempio, "Sam di Hangouts ha detto…"), crea una funzione come quella mostrata nel seguente esempio di codice per assicurarti che l'assistente legga il nome corretto:

@Nullable
String getMessageApplicationName(Context context, StatusBarNotification statusBarNotification) {
    ApplicationInfo info = getApplicationInfo(context, statusBarNotification.getPackageName());
    if (info == null) return null;

    Notification notification = statusBarNotification.getNotification();

    // Sometimes system packages will post on behalf of other apps, so check this
    // field for a system app notification.
    if (isSystemApp(info)
            && notification.extras.containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME)) {
        return notification.extras.getString(Notification.EXTRA_SUBSTITUTE_APP_NAME);
    } else {
        PackageManager pm = context.getPackageManager();
        return String.valueOf(pm.getApplicationLabel(info));
    }
}

@Nullable
ApplicationInfo getApplicationInfo(Context context, String packageName) {
    final PackageManager pm = context.getPackageManager();
    ApplicationInfo info;
    try {
        info = pm.getApplicationInfo(packageName, 0);
    } catch (PackageManager.NameNotFoundException e) {
        return null;
    }
    return info;
}

boolean isSystemApp(ApplicationInfo info) {
    return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}