Asystent głosowy – tryb „Dotknij, by przeczytać”

Android Automotive uważa, że głos jest kluczowym elementem bezpieczne dla użytkowników i jeden z najbezpieczniejszych sposobów współdziała z systemem operacyjnym Android Automotive podczas jazdy. W związku z tym rozszerzyliśmy Interfejsy API Asystenta głosowego na Androida (w tym VoiceInteractionSession) aby umożliwić asystentom głosowym wykonywanie zadań za użytkowników co może być trudne do osiągnięcia podczas jazdy.

Dotknij, by przeczytać umożliwia asystentom głosowym czytanie SMS-ów i odpowiadanie na nie w imieniu użytkownika, gdy wchodzi on w interakcję z powiadomieniami o wiadomościach. Aby podać tę funkcję możesz zintegrować z asystentem głosowym CarVoiceInteractionSession

W samochodach powiadomienia publikowane w Centrum powiadomień zostały rozpoznane jako INBOX lub INBOX_IN_GROUP (np. SMS-y) zawierają Przycisk Odtwórz. Użytkownik może kliknąć Odtwórz, aby wykonać grę Asystent głosowy odczyta powiadomienie na głos i opcjonalnie odpowie głosowo.

Powiadomienie „Dotknij, aby przeczytać”

Rysunek 1. Powiadomienie „Dotknij, by przeczytać” z przyciskiem odtwarzania.

Integracja z CarVoiceInteractionSession

W następnych sekcjach dowiesz się, jak zintegrować asystenta głosowego z CarVoiceInteractionSession

Obsługa interakcji głosowych

Aplikacje oferujące w samochodzie usługi interakcji głosowej muszą z dotychczasowymi interakcjami głosowymi na Androidzie. Więcej informacji znajdziesz w artykule o Asystencie Google na Androida. (z wyjątkiem VoiceInteractionSession). Chociaż wszystkie API interakcji głosowych elementy pozostają takie same jak te zaimplementowane na urządzeniach mobilnych, CarVoiceInteractionSession (opisane w sekcji Implementacja CarVoiceInteractionSession) zastępuje funkcja VoiceInteractionSession Więcej informacji znajdziesz na tych stronach:

Implementowanie CarVoiceInteractionSession

CarVoiceInteractionSession udostępnia interfejsy API, które pozwalają asystentom głosowym odczytywać SMS-y na głos, a następnie odpowiadać na te wiadomości w imieniu użytkownika.

Główna różnica między CarVoiceInteractionSession a VoiceInteractionSession zajęcia to CarVoiceInteractionSession Podaje podania w onShow aby Asystent głosowy mógł wykryć kontekst żądania użytkownika, gdy tylko CarVoiceInteractionSession rozpoczyna sesję. Parametry funkcji onShow dotyczące poszczególnych zajęć podano w tej tabeli:

Sesja głosowa w samochodzie Sesja VoiceInteraction
Funkcja onShow przyjmuje te 3 parametry:
    .
  • args
  • showFlags
  • actions
Funkcja onShow przyjmuje te 2 parametry:
    .
  • args
  • showFlags

Zmiany w Androidzie 10

W Androidzie 10 platforma nazywa się VoiceInteractionService.onGetSupportedVoiceActions aby wykrywać obsługiwane działania. Asystent głosowy zastępuje implementuje dyrektywę VoiceInteractionService.onGetSupportedVoiceActions, jak w tym przykładzie:

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;
   }
}

Prawidłowe działania zostały opisane w poniższej tabeli. Szczegółowe informacje o poszczególnych działaniach znajdziesz w sekcji Wykresy sekwencji.

Działanie Oczekiwany ładunek Oczekiwane działanie związane z interakcją głosową
VOICE_ACTION_READ_NOTIFICATION odczytać na głos wiadomości dla użytkownika, a następnie uruchomić polecenie „Oznacz jako przeczytane”; gdy wiadomości zostaną odczytane. Opcjonalnie uruchom użytkownika.
VOICE_ACTION_REPLY_NOTIFICATION Interfejs Parcelable z kluczem.
KEY_NOTIFICATION które wskazuje miejsce StatusBarNotification.
Wymagana wartość android.permission.BIND_NOTIFICATION_LISTENER_SERVICE.
Poproś użytkownika o podanie treści odpowiedzi i wpisanie odpowiedzi w RemoteInputReply intencji oczekującej, a następnie uruchomić intencję oczekującą.
VOICE_ACTION_HANDLE_EXCEPTION Ciąg z kluczem.
KEY_EXCEPTION. mapujący na ExceptionValue (opisane w sekcji Wartości wyjątków).
KEY_FALLBACK_ASSISTANT_ENABLED, która jest mapowana na wartość logiczną. Jeśli wartość to true, asystent zastępczy, który może obsłużyć żądanie użytkownika, został wyłączono.
Działania, jakie należy podjąć w przypadku takiego wyjątku, są określone w dokumentacji wyjątku.

Wartości wyjątków

EXCEPTION_NOTIFICATION_LISTENER_PERMISSIONS_MISSING informuje asystenta głosowego, że nie ma uprawnienia Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE, a następnie może uzyskać je od użytkownika.

Poproś o zgodę na detektor powiadomień

Jeśli domyślny asystent głosowy nie ma słuchacza powiadomień FallbackAssistant platformy (jeśli funkcja została włączona przez producenta samochodu) może odczytać wiadomość na głos, zanim asystent głosowy powiadomiono o konieczności prośby o przyznanie uprawnień. Aby określić, czy usługa FallbackAssistant jest włączona i przeczytał wiadomość, asystent głosowy powinien sprawdzić KEY_FALLBACK_ASSISTANT_ENABLED Wartość logiczna w ładunku.

Platforma zaleca, by asystent głosowy dodał funkcję ograniczania szybkości ile razy poproszono o to uprawnienie. W ten sposób szanuje się użytkownik, który tego nie robi. chcesz przyznać asystentowi głosowemu te uprawnienia i wolisz FallbackAssistant, aby odczytać SMS-y na głos. Prośba użytkownik prosi o zgodę za każdym razem, gdy naciśnie Odtwórz w powiadomieniu o wiadomości co może negatywnie wpłynąć na wrażenia użytkownika. Platforma nie nakłada limitów liczby żądań w imieniu asystenta głosowego.

Gdy prosisz o zgodę słuchacza powiadomień, asystent głosowy powinien użyj funkcji CarUxRestrictionsManager , aby określić, czy użytkownik jest zaparkowany lub jedzie samochodem. Jeśli użytkownik prowadzi samochód, Asystent głosowy wyświetla powiadomienie z instrukcjami przyznawania uprawnień. Robię to pomaga użytkownikowi (i przypomina) zgodę na jego przyznanie, gdy jest to bezpieczniejsze.

Praca z StatusBar Notification

StatusBarNotification zaliczyło zadanie za pomocą funkcji Czytaj i odpowiadaj komendy głosowe są zawsze widoczne w powiadomieniu o wiadomościach zgodnych z samochodem zgodnie z opisem. w sekcji Powiadom wiadomości. Choć niektóre powiadomienia mogą nie mieć stanu Oczekiwanie na odpowiedź mają intencje oczekujące na oznaczenie Oznacz jako przeczytany.

Aby usprawnić interakcję z powiadomieniami, używaj NotificationPayloadHandler, który pozwala wyodrębniać wiadomości z powiadomień i zapisywać odpowiadać na wiadomości zgodne z odpowiednią intencją oczekującą. Po asystent głosowy przeczyta wiadomość, a asystent głosowy musi uruchomić znak „Znak” jako zamiar odczytu.

Spełnij warunki wstępne funkcji Dotknij, by przeczytać

Tylko VoiceInteractionSession głosu domyślnego Asystent jest powiadamiany, gdy użytkownik uruchomi komendę głosową, aby odczytać odpowiadać na wiadomości. Jak wspomnieliśmy powyżej, ten domyślny asystent głosowy musi też mieć uprawnienia do nasłuchiwania powiadomień.

Diagramy sekwencji

Te liczby pokazują przepływy logiczne funkcji CarVoiceInteractionSession actions:

VOICE_ACTION_READ_POWIADOMIENIE

Rysunek 2. Schemat sekwencji dla VOICE_ACTION_READ_Powiadomienie.

W przypadku ilustracji 3 zalecamy stosowanie aplikacji limitów liczby żądań uprawnień:

VOICE_ACTION_REPLY_Powiadomienie

Rysunek 3. Schemat sekwencji dla VOICE_ACTION_REPLY_Powiadomienie.

VOICE_ACTION_HANDLE_EXCEPTION

Rysunek 4. Schemat sekwencji: VOICE_ACTION_HANDLE_EXCEPTION.

Odczytywanie nazwy aplikacji

Jeśli chcesz, żeby asystent głosowy czytał na głos nazwę aplikacji do obsługi wiadomości podczas (np. „Jakub z Hangouts powiedział...”) utwórz funkcję podobną do tej, w poniższym przykładzie kodu, aby upewnić się, że asystent odczytuje prawidłowe imię:

@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;
}