App-Entwicklung

So implementieren Sie eine Voice Interaction Application (VIA):

  1. VIA-Skelett erstellen
  2. Optional: Implementieren Sie einen Einrichtungs-/Anmeldeablauf.
  3. Optional: Implementieren Sie einen Bildschirm mit den Einstellungen.
  4. Erforderliche Berechtigungen in der Manifestdatei deklarieren
  5. Implementieren Sie eine Benutzeroberfläche für das Unterhaltungsfenster.
  6. Implementieren Sie die Spracherkennung (muss die Implementierung der RecognitionService API enthalten).
  7. Implementieren Sie die Äußerung. Optional können Sie die TextToSpeech API implementieren.
  8. Befehlsausführung implementieren Weitere Informationen finden Sie unter Befehle ausführen.

In den folgenden Abschnitten wird beschrieben, wie Sie die einzelnen oben genannten Schritte ausführen.

VIA-Gerüst erstellen

Manifeste

Eine App wird als App mit Sprachinteraktion erkannt, wenn das Manifest Folgendes enthält:

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 diesem Beispiel gilt Folgendes:

  • VIAs müssen einen Dienst bereitstellen, der VoiceInteractionService erweitert, mit einem Intent-Filter für die Aktion VoiceInteractionService.SERVICE_INTERFACE ("android.service.voice.VoiceInteractionService").
  • Dieser Dienst muss die Berechtigung für die BIND_VOICE_INTERACTION-Systemsignatur haben.
  • Dieser Dienst sollte eine android.voice_interaction-Metadatendatei mit den folgenden Informationen enthalten:

    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" />

Weitere Informationen zu den einzelnen Feldern finden Sie unter R.styleable#VoiceInteractionService. Da alle VIAs auch Spracherkennungsdienste sind, müssen Sie auch Folgendes in Ihr Manifest aufnehmen:

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>

Für Spracherkennungsdienste ist außerdem das folgende Metadatenfeld erforderlich:

res/xml/recognition_service.xml

<recognition-service
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:settingsActivity="com.example.MyRecognizerSettingsActivity" />

VoiceInteractionService, VoiceInteractionSessionService und VoiceInteractionSession

Das folgende Diagramm zeigt den Lebenszyklus der einzelnen Entitäten:

Lebenszyklen

Abbildung 1: Lebenszyklen

Wie bereits erwähnt, ist VoiceInteractionService der Einstiegspunkt für eine VIA. Die Hauptaufgaben dieses Dienstes sind:

  • Initialisieren Sie alle Prozesse, die so lange ausgeführt werden sollen, wie dieser VIA aktiv ist. Zum Beispiel die Hotword-Erkennung.
  • Berichte unterstützen Sprachbedienung (siehe Sprachassistent – Zum Vorlesen tippen).
  • Sprachinteraktionssitzungen über den Sperrbildschirm (Keyguard) starten

In der einfachsten Form sieht eine VoiceInteractionService-Implementierung so aus:

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

Die Implementierung von VoiceInteractionService#onGetSupportedVoiceActions() ist erforderlich, um Zum Vorlesen tippen zu unterstützen. Ein VoiceInteractionSessionService wird vom System verwendet, um eine VoiceInteractionSession zu erstellen und mit ihr zu interagieren. Es hat nur eine Aufgabe: neue Sitzungen zu starten, wenn dies angefordert wird.

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

Schließlich wird die meiste Arbeit in einer VoiceInteractionSession erledigt. Eine einzelne Sitzungsinstanz kann wiederverwendet werden, um mehrere Nutzerinteraktionen abzuschließen. In AAOS gibt es einen Helfer CarVoiceInteractionSession , der bei der Implementierung einiger der einzigartigen Automobilfunktionen hilft.

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 bietet eine Vielzahl von Callback-Methoden, die in den folgenden Abschnitten beschrieben werden. Eine vollständige Liste finden Sie in der Dokumentation zu VoiceInteractionSession.

Einrichtungs-/Anmeldeablauf implementieren

Einrichtung und Anmeldung können erfolgen:

  • Während der Geräteeinrichtung (Einrichtungsassistent).
  • Während des Wechsels des Sprachinteraktionsdienstes (Einstellungen).
  • Beim ersten Start, wenn die App ausgewählt ist.

Details zur empfohlenen Nutzererfahrung und visuelle Anleitungen finden Sie unter Vorinstallierte Assistenten: UX-Anleitung.

Einrichtung beim Wechsel des Sprachdienstes

Der Nutzer kann immer eine VIA auswählen, die nicht richtig konfiguriert wurde. Das kann folgende Gründe haben:

  • Der Nutzer hat den Einrichtungsassistenten vollständig übersprungen oder den Konfigurationsschritt für die Sprachinteraktion übersprungen.
  • Der Nutzer hat eine andere VIA als die ausgewählt, die beim Onboarding des Geräts konfiguriert wurde.

In jedem Fall hat ein VoiceInteractionService mehrere Möglichkeiten, den Nutzer zur Einrichtung zu ermutigen:

  • Erinnerung für Benachrichtigungen
  • Automatische Sprachantwort, wenn der Nutzer versucht, die Funktion zu verwenden.

Hinweis: Es wird dringend davon abgeraten, einen VIA-Einrichtungsablauf ohne explizite Nutzeranfrage zu präsentieren. Das bedeutet, dass VIAs nicht automatisch Inhalte auf der HU anzeigen sollten, wenn das Gerät hochgefahren wird oder wenn ein Nutzer wechselt oder das Gerät entsperrt wird.

Erinnerung an Benachrichtigung

Eine Benachrichtigungserinnerung ist eine unaufdringliche Möglichkeit, auf die Notwendigkeit der Einrichtung hinzuweisen und Nutzern die Möglichkeit zu geben, den Einrichtungsablauf des Assistenten aufzurufen.

Erinnerung an Benachrichtigung

Abbildung 2: Erinnerung an Benachrichtigung

So funktioniert dieser Ablauf:

Ablauf für Erinnerungsbenachrichtigungen

Abbildung 3: Ablauf für Erinnerungsbenachrichtigungen

Sprachantwort

Dies ist der einfachste Ablauf, der implementiert werden kann. Er wird durch einen VoiceInteractionSession#onShow()-Callback ausgelöst, erklärt dem Nutzer, was zu tun ist, und fragt ihn dann (sofern die Einrichtung gemäß dem UX-Einschränkungsstatus zulässig ist), ob er den Einrichtungsablauf starten möchte. Wenn die Einrichtung zu diesem Zeitpunkt nicht möglich ist, erkläre auch das.

Einrichtung bei der ersten Verwendung

Es ist immer möglich, dass der Nutzer eine VIA auslöst, die nicht richtig konfiguriert wurde. In solchen Fällen gilt Folgendes:

  1. Informieren Sie den Nutzer mündlich über diese Situation (z. B. „Damit ich richtig funktionieren kann, musst du einige Schritte ausführen …“).
  2. Wenn die Engine für UX-Einschränkungen dies zulässt (siehe UX_RESTRICTIONS_NO_SETUP), frage den Nutzer, ob er den Einrichtungsprozess starten möchte, und öffne dann den Einstellungsbildschirm für die VIA.
  3. Andernfalls, z. B. wenn der Nutzer gerade fährt, sollten Sie eine Benachrichtigung hinterlassen, damit er auf die Option klicken kann, wenn es sicher ist.

Einrichtungsbildschirme für die Sprachinteraktion erstellen

Einrichtungs- und Anmeldebildschirme sollten als reguläre Aktivitäten entwickelt werden. Weitere Informationen zur Entwicklung der Benutzeroberfläche finden Sie in den UX- und visuellen Richtlinien unter Vorinstallierte Assistenten: UX-Leitfaden.

Allgemeine Richtlinien:

  • Nutzer sollten die Einrichtung jederzeit unterbrechen und fortsetzen können.
  • Die Einrichtung sollte nicht zulässig sein, wenn die Einschränkung UX_RESTRICTIONS_NO_SETUP gilt. Weitere Informationen finden Sie in den Richtlinien zu Ablenkungen für Fahrer.
  • Die Einrichtungsbildschirme müssen dem Designsystem für das jeweilige Fahrzeug entsprechen. Das allgemeine Bildschirmlayout, die Symbole, die Farben und andere Aspekte sollten mit dem Rest der Benutzeroberfläche übereinstimmen. Weitere Informationen finden Sie unter Anpassung.

Einstellungsbildschirm implementieren

Integration der Einstellungen

Abbildung 4: Integration der Einstellungen

Einstellungsbildschirme sind normale Android-Aktivitäten. Wenn der Einstiegspunkt implementiert ist, muss er in den VIA-Manifesten (siehe Manifeste) im res/xml/interaction_service.xml deklariert werden. Im Bereich „Einstellungen“ können Sie die Einrichtung und Anmeldung fortsetzen (falls der Nutzer sie nicht abgeschlossen hat) oder bei Bedarf die Optionen Abmelden oder Nutzer wechseln anbieten. Ähnlich wie bei den oben beschriebenen Einrichtungsbildschirmen gilt für diese Bildschirme:

  • Bieten Sie die Möglichkeit, zum vorherigen Bildschirm im Bildschirmstapel zurückzukehren (z. B. zu den Fahrzeugeinstellungen).
  • Während der Fahrt nicht zulässig sein. Weitere Informationen finden Sie in den Richtlinien zu Ablenkungen für Fahrer.
  • Ordnen Sie die einzelnen Fahrzeugdesignsysteme zu. Weitere Informationen finden Sie unter Anpassung.

Erforderliche Berechtigungen in der Manifestdatei deklarieren

Die von einem VIA benötigten Berechtigungen lassen sich in drei Kategorien unterteilen:

  • Berechtigungen für Systemsignaturen: Diese Berechtigungen werden nur vorinstallierten, systemsignierten APKs gewährt. Nutzer können diese Berechtigungen nicht erteilen. Nur OEMs können sie beim Erstellen ihrer System-Images erteilen. Weitere Informationen zum Erhalten von Signaturberechtigungen finden Sie unter Berechtigungen mit Systemprivilegien erteilen.
  • Gefährliche Berechtigungen: Diese Berechtigungen müssen von einem Nutzer über das PermissionsController-Dialogfeld gewährt werden. OEMs können einige dieser Berechtigungen für den standardmäßigen VoiceInteractionService vorab erteilen. Da sich diese Standardeinstellung jedoch von Gerät zu Gerät ändern kann, sollten Apps diese Berechtigungen bei Bedarf anfordern können.
  • Weitere Berechtigungen: Das sind alle anderen Berechtigungen, für die keine Nutzerinteraktion erforderlich ist. Diese Berechtigungen werden automatisch vom System erteilt.

Daher konzentriert sich der folgende Abschnitt nur auf das Anfordern gefährlicher Berechtigungen. Berechtigungen sollten nur angefordert werden, wenn sich der Nutzer auf den Anmelde- oder Einstellungsbildschirmen befindet.

Wenn die App nicht die erforderlichen Berechtigungen hat, sollte die Situation dem Nutzer per Sprachausgabe erklärt werden. Außerdem sollte eine Benachrichtigung angezeigt werden, über die der Nutzer zu den Einstellungen für die Sprachzugriff auf das Auto zurückkehren kann. Weitere Informationen finden Sie unter 1. Erinnerung an Benachrichtigung:

Berechtigungen auf dem Einstellungsbildschirm anfordern

Gefährliche Berechtigungen werden mit der regulären ActivityCompat#requestPermission()-Methode (oder einer entsprechenden Methode) angefordert. Weitere Informationen zum Anfordern von Berechtigungen finden Sie unter App-Berechtigungen anfordern.

Berechtigungen anfordern

Abbildung 5: Berechtigungen anfordern

Berechtigung zum Abhören von Benachrichtigungen

Um den TTR-Ablauf zu implementieren, müssen VIAs als Benachrichtigungs-Listener festgelegt werden. Dies ist keine Berechtigung an sich, sondern eine Konfiguration, die es dem System ermöglicht, Benachrichtigungen an registrierte Listener zu senden. So können Apps herausfinden, ob der VIA Zugriff auf diese Informationen erhalten hat:

Wenn dieser Zugriff nicht vorab gewährt wurde, sollte das VIA den Nutzer über eine Kombination aus Äußerungen und Benachrichtigungen zum Bereich „Benachrichtigungszugriff“ der Fahrzeugeinstellungen weiterleiten. Mit dem folgenden Code kann der entsprechende Bereich der Einstellungen geöffnet werden:

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

Benutzeroberfläche für Unterhaltungsfenster implementieren

Wenn ein VoiceInteractionSession einen onShow()-Callback erhält, kann er eine Benutzeroberfläche für die Spracheingabe präsentieren. Visuelle und UX-Richtlinien zur Implementierung von Sprach-Plates finden Sie unter Vorinstallierte Assistenten: UX-Leitfaden.

Unterhaltungsfenster anzeigen

Abbildung 6 Unterhaltungsfenster anzeigen

Es gibt zwei Möglichkeiten, diese Benutzeroberfläche zu implementieren:

  • Überschreiben VoiceInteractionSession#onCreateContentView()
  • Aktivität mit VoiceInteractionSession#startAssistantActivity() starten

onCreateContentView() verwenden

Dies ist die Standardmethode zur Darstellung einer Voiceplate. Die Basisklasse VoiceInteractionSession erstellt ein Fenster und verwaltet seinen Lebenszyklus, solange eine Sprachsitzung aktiv ist. Apps müssen VoiceInteractionSession#onCreateContentView() überschreiben und eine Ansicht zurückgeben, die an dieses Fenster angehängt ist, sobald die Sitzung erstellt wird. Diese Ansicht sollte anfangs unsichtbar sein. Wenn eine Sprachinteraktion beginnt, sollte diese Ansicht auf VoiceInteractionSession#onShow() sichtbar und dann auf VoiceInteractionSession#onHide() wieder unsichtbar gemacht werden.

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

Wenn Sie diese Methode verwenden, sollten Sie VoiceInteractionSession#onComputeInsets() anpassen, um verdeckte Bereiche der Benutzeroberfläche zu berücksichtigen.

startAssistantActivity() verwenden

In diesem Fall delegiert VoiceInteractionSession die Verarbeitung der Sprachsteuerungs-Benutzeroberfläche an eine reguläre Aktivität. Wenn diese Option verwendet wird, muss bei der VoiceInteractionSession-Implementierung die Erstellung des Standardinhaltsfensters (siehe onCreateContentView() verwenden) im onPrepareShow()-Callback deaktiviert werden. Um VoiceInteractionSession#onShow() würde die Sitzung die Sprachplattenaktivität mit VoiceInteractionSession#startAssistantActivity() starten. Mit dieser Methode wird die Benutzeroberfläche mit den richtigen Fenstereinstellungen und Aktivitäts-Flags initialisiert.

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

    
}

Damit die Kommunikation zwischen dieser Aktivität und dem VoiceInteractionSession aufrechterhalten werden kann, sind möglicherweise eine Reihe interner Intents oder eine Dienstbindung erforderlich. Wenn beispielsweise VoiceInteractionSession#onHide() aufgerufen wird, muss die Sitzung diese Anfrage an die Aktivität weiterleiten können.

Wichtig: Im Bereich Automotive dürfen während der Fahrt nur speziell gekennzeichnete Aktivitäten oder Aktivitäten, die auf der UXR-Zulassungsliste aufgeführt sind, angezeigt werden. Das gilt auch für Aktivitäten, die mit VoiceInteractionSession#startAssistantActivity() gestartet wurden. Denken Sie daran, Ihre Aktivität entweder mit <meta-data android:name="distractionOptimized" android:value="true"/> zu annotieren oder sie in den systemActivityWhitelist-Schlüssel der /packages/services/Car/service/res/values/config.xml-Datei aufzunehmen. Weitere Informationen finden Sie in den Richtlinien zu Ablenkungen für Fahrer.

Spracherkennung implementieren

In diesem Abschnitt erfahren Sie, wie Sie die Spracherkennung durch die Erkennung von Hotwords implementieren. Ein Aktivierungswort ist ein Auslöserwort, mit dem eine neue Anfrage oder Aktion per Sprache gestartet wird. Sagen Sie beispielsweise „Ok Google“ oder „Hey Google“.

DSP-Hotword-Erkennung

Android bietet über die AlwaysOnHotwordDetector Zugriff auf einen Always-On-Hotword-Detektor auf DSP-Ebene. Möglichkeit, die Hotword-Erkennung mit geringer CPU-Auslastung zu implementieren. Die Nutzung dieser Funktion ist in zwei Teile unterteilt:

Bei der Implementierung von VoiceInteractionService kann ein Hotword-Detektor mit VoiceInteractionService#createAlwaysOnHotwordDetector() erstellt werden. Dazu wird eine Schlüsselphrase und ein Gebietsschema übergeben, die für die Erkennung verwendet werden sollen. Infolgedessen erhält die App einen onAvailabilityChanged()-Callback mit einem der folgenden möglichen Werte:

  • STATE_HARDWARE_UNAVAILABLE. Die DSP-Funktion ist auf dem Gerät nicht verfügbar. In diesem Fall wird die Software-Hotword-Erkennung verwendet.
  • STATE_HARDWARE_UNSUPPORTED. Der DSP-Support ist nicht allgemein verfügbar, aber DSP unterstützt die angegebene Kombination aus Schlüsselwortgruppe und Sprache nicht. Die App kann die Software-Hotword-Erkennung verwenden.
  • STATE_HARDWARE_ENROLLED. Die Hotword-Erkennung ist bereit und kann durch Aufrufen der Methode startRecognition() gestartet werden.
  • STATE_HARDWARE_UNENROLLED: Ein Soundmodell für die angeforderte Schlüsselphrase ist nicht verfügbar, aber die Registrierung ist möglich.

Die Registrierung von Soundmodellen für die Hotword-Erkennung kann mit IVoiceInteractionManagerService#updateKeyphraseSoundModel() erfolgen. Es können mehrere Modelle gleichzeitig im System registriert sein, aber nur ein Modell ist mit einem AlwaysOnHotwordDetector verknüpft. Die Hotword-Erkennung durch den DSP ist möglicherweise nicht auf allen Geräten verfügbar. VIA-Entwickler sollten die Hardwarefunktionen mit der getDspModuleProperties()-Methode prüfen. Beispielcode zum Registrieren von Soundmodellen finden Sie unter VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java. Informationen zur gleichzeitigen Hotword-Erkennung finden Sie unter Gleichzeitige Aufnahme.

Software-Hotword-Erkennung

Wie oben erwähnt, ist die DSP-Hotword-Erkennung möglicherweise nicht auf allen Geräten verfügbar. Der Android-Emulator bietet beispielsweise keine DSP-Emulation. In diesem Fall ist die Software-Spracherkennung die einzige Alternative. Damit andere Apps, die möglicherweise Zugriff auf das Mikrofon benötigen, nicht beeinträchtigt werden, müssen VIAs über Folgendes auf die Audioeingabe zugreifen:

Beide Konstanten sind @hide und nur für gebündelte Apps verfügbar.

Audioeingabe und Spracherkennung verwalten

Die Audioeingabe würde mit der MediaRecorder-Klasse implementiert. Weitere Informationen zur Verwendung dieser API finden Sie in der MediaRecorder-Übersicht. Sprachinteraktionsdienste müssen auch RecognitionService-Klassenimplementierungen sein. Jede App im System, die Spracherkennung erfordert, verwendet die, um auf diese Funktion zuzugreifen. Für die Spracherkennung und den Zugriff auf das Mikrofon müssen VIAs android.permission.RECORD_AUDIO haben. Apps, die auf eine RecognitionService-Implementierung zugreifen, müssen diese Berechtigung ebenfalls haben.

Vor Android 10 hatte jeweils nur eine App Zugriff auf das Mikrofon (mit Ausnahme der Hotword-Erkennung, siehe oben). Ab Android 10 kann der Mikrofonzugriff freigegeben werden. Weitere Informationen finden Sie unter Audioeingabe freigeben.

Auf Audioausgabe zugreifen

Wenn die VIA bereit ist, verbale Antworten zu geben, ist es wichtig, die folgenden Richtlinien zu beachten: