App-Entwicklung

So implementieren Sie eine Voice Interaction Application (VIA):

  1. Erstellen Sie ein VIA-Skelett.
  2. (Optional) Implementieren Sie einen Einrichtungs-/Anmeldeablauf.
  3. (Optional) Implementieren Sie einen Bildschirm mit Einstellungen.
  4. Deklarieren Sie die erforderlichen Berechtigungen in der Manifestdatei.
  5. Implementieren Sie eine Benutzeroberfläche für die Sprachplatte.
  6. Implementieren Sie die Spracherkennung (einschließlich der Implementierung der RecognitionService API).
  7. Implementieren Sie die Äußerung (optional können Sie die TextToSpeech API implementieren).
  8. Implementieren Sie die Befehlsausführung. Weitere Informationen finden Sie unter Befehle ausführen.

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

VIA-Skelett erstellen

Manifeste

Eine App wird als App mit Sprachinteraktion erkannt, wenn das Folgende im Manifest enthalten ist:

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 BIND_VOICE_INTERACTION Systemsignaturberechtigung haben.
  • Dieser Dienst sollte eine Metadatendatei android.voice_interaction enthalten, die Folgendes enthält:

    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 außerdem 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 auch das folgende Metadatum 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:

  • Alle Prozesse initialisieren, die so lange ausgeführt werden sollen, wie diese VIA die aktive ist. Beispiel: Hotword-Erkennung.
  • Unterstützte Sprachaktionen melden (siehe „Tap-to-Read“ für den Sprachassistenten).
  • 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 „Tap-to-Read“ für den Sprachassistenten zu verarbeiten. Ein VoiceInteractionSessionService wird vom System verwendet, um eine VoiceInteractionSession zu erstellen und mit ihr zu interagieren. Er 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 für mehrere Nutzerinteraktionen wiederverwendet werden. In AAOS gibt es einen Helfer CarVoiceInteractionSession , der bei der Implementierung einiger der einzigartigen Funktionen für das Auto 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 hat eine große Anzahl von Callback-Methoden, die in den folgenden Abschnitten erläutert werden. Eine vollständige Liste finden Sie in der Dokumentation zu VoiceInteractionSession.

Einrichtungs-/Anmeldeablauf implementieren

Die Einrichtung und Anmeldung können in folgenden Fällen erfolgen:

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

Weitere Informationen zur empfohlenen Nutzererfahrung und visuellen Anleitung finden Sie unter Vorinstallierte Assistenten: UX-Anleitung.

Einrichtung beim Wechsel des Sprachdienstes

Nutzer können jederzeit 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 Schritt zur Konfiguration der Sprachinteraktion übersprungen.
  • Der Nutzer hat eine andere VIA ausgewählt als die, die bei der Geräteeinrichtung konfiguriert wurde.

In jedem Fall hat ein VoiceInteractionService mehrere Möglichkeiten, den Nutzer aufzufordern, die Einrichtung abzuschließen:

  • Erinnerung per Benachrichtigung.
  • Automatische Sprachantwort, wenn der Nutzer versucht, die VIA zu verwenden.

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

Erinnerung per Benachrichtigung

Eine Erinnerung per Benachrichtigung ist eine unaufdringliche Möglichkeit, auf die Notwendigkeit der Einrichtung hinzuweisen und Nutzern eine Möglichkeit zu bieten, zum Einrichtungsablauf des Assistenten zu wechseln.

Erinnerung für Benachrichtigungen

Abbildung 2 : Erinnerung per Benachrichtigung

So funktioniert dieser Ablauf:

Ablauf für Erinnerungsbenachrichtigungen

Abbildung 3 : Ablauf für Erinnerung per Benachrichtigung

Sprachantwort

Dies ist der einfachste Ablauf, der implementiert werden kann. Er initiiert eine Äußerung bei einem VoiceInteractionSession#onShow()-Callback, erklärt dem Nutzer, was zu tun ist, und fragt ihn dann (wenn die Einrichtung aufgrund des UX-Einschränkungsstatus zulässig ist), ob er den Einrichtungsablauf starten möchte. Wenn die Einrichtung zu diesem Zeitpunkt nicht möglich ist, erklären Sie auch diese Situation.

Einrichtung bei der ersten Verwendung

Nutzer können jederzeit eine VIA auslösen, 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, müssen Sie einige Schritte ausführen …“).
  2. Wenn die Engine für UX-Einschränkungen dies zulässt (siehe UX_RESTRICTIONS_NO_SETUP), fragen Sie den Nutzer, ob er den Einrichtungsprozess starten möchte, und öffnen Sie dann den Bildschirm mit den Einstellungen für die VIA.
  3. Andernfalls (z. B. wenn der Nutzer fährt) hinterlassen Sie eine Benachrichtigung, damit der Nutzer auf die Option klicken kann, wenn es sicher ist.

Bildschirme für die Einrichtung der Sprachinteraktion erstellen

Einrichtungs- und Anmeldebildschirme sollten als reguläre Aktivitäten entwickelt werden. Die UX- und visuellen Richtlinien für die UI-Entwicklung finden Sie unter Vorinstallierte Assistenten: UX-Anleitung.

Allgemeine Richtlinien:

  • VIAs sollten Nutzern ermöglichen, die Einrichtung jederzeit zu unterbrechen und fortzusetzen.
  • Die Einrichtung sollte nicht zulässig sein, wenn die Einschränkung UX_RESTRICTIONS_NO_SETUP aktiv ist. Weitere Informationen finden Sie in den Richtlinien zu Ablenkungen für Fahrer.
  • Die Einrichtungsbildschirme sollten 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.

Bildschirm mit Einstellungen implementieren

Integration der Einstellungen

Abbildung 4 : Integration der Einstellungen

Bildschirme mit Einstellungen sind reguläre Android-Aktivitäten. Wenn sie implementiert sind, muss ihr Einstiegspunkt in der Datei res/xml/interaction_service.xml als Teil der VIA Manifeste deklariert werden (siehe Manifeste). Im Bereich „Einstellungen“ können Sie die Einrichtung und Anmeldung fortsetzen (wenn der Nutzer sie nicht abgeschlossen hat) oder bei Bedarf eine Option zum Abmelden oder Nutzer wechseln anbieten. Ähnlich wie bei den oben beschriebenen Einrichtungsbildschirmen sollten diese Bildschirme:

  • Die Möglichkeit bieten, 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 zum Ablenkungsgrad des Fahrers.
  • Dem Designsystem des jeweiligen Fahrzeugs entsprechen. Weitere Informationen finden Sie unter Anpassung.

Erforderliche Berechtigungen in der Manifestdatei deklarieren

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

  • Systemsignaturberechtigungen Diese Berechtigungen werden nur vorinstallierten, vom System signierten APKs erteilt. Nutzer können diese Berechtigungen nicht erteilen. Nur OEMs können sie erteilen, wenn sie ihre System-Images erstellen. Weitere Informationen zum Abrufen von Signaturberechtigungen finden Sie unter Berechtigungen mit Systemprivilegien erteilen.
  • Gefährliche Berechtigungen Diese Berechtigungen müssen von Nutzern über das Dialogfeld „PermissionsController“ erteilt werden. OEMs können einige dieser Berechtigungen vorab für den Standard-VoiceInteractionService erteilen. Da sich dieser Standard jedoch von Gerät zu Gerät unterscheiden kann, sollten Apps diese Berechtigungen bei Bedarf anfordern können.
  • Weitere Berechtigungen Das sind alle anderen Berechtigungen, die keine Nutzerinteraktion erfordern. 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, besteht der empfohlene Ablauf darin, die Situation dem Nutzer mit einer Sprachäußerung zu erklären und eine Benachrichtigung zu senden, die dem Nutzer eine Möglichkeit bietet, zu den VIA-Einstellungsbildschirmen zurückzukehren. Weitere Informationen finden Sie unter 1. Erinnerung per Benachrichtigung.

Berechtigungen als Teil des Einstellungsbildschirms anfordern

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

Berechtigungen anfordern

Abbildung 5 : Berechtigungen anfordern

Berechtigung für Benachrichtigungslistener

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

Wenn dieser Zugriff nicht vorab erteilt wurde, sollte die VIA den Nutzer mit einer Kombination aus Äußerungen und Benachrichtigungen zum Bereich „Benachrichtigungszugriff“ der Fahrzeugeinstellungen weiterleiten. Mit dem folgenden Code kann der entsprechende Bereich der Einstellungen-App 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 die Sprachplatte implementieren

Wenn eine VoiceInteractionSession ein onShow()-Callback erhält, kann sie eine Benutzeroberfläche für die Sprachplatte präsentieren. Visuelle und UX-Richtlinien zur Implementierung der Sprachplatte finden Sie unter Vorinstallierte Assistenten: UX-Anleitung.

Unterhaltungsfenster anzeigen

Abbildung 6 : Sprachplatte anzeigen

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

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

onCreateContentView() verwenden

Dies ist die Standardmethode zum Präsentieren einer Sprachplatte. 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 wurde. Diese Ansicht sollte anfangs unsichtbar sein. Wenn eine Sprachinteraktion beginnt, sollte diese Ansicht mit VoiceInteractionSession#onShow() sichtbar und dann mit 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 Benutzeroberfläche der Sprachplatte an eine reguläre Aktivität. Wenn diese Option verwendet wird, muss eine VoiceInteractionSession -Implementierung die Erstellung des Standardfensters für Inhalte (siehe onCreateContentView() verwenden) beim onPrepareShow() -Callback deaktivieren. Bei VoiceInteractionSession#onShow() würde die Sitzung die Aktivität der Sprachplatte mit VoiceInteractionSession#startAssistantActivity() starten. Diese Methode initiiert die Benutzeroberfläche mit den richtigen Fenstereinstellungen und Aktivitätsflags.

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

    
}

Um die Kommunikation zwischen dieser Aktivität und der VoiceInteractionSession aufrechtzuerhalten, 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 können während der Fahrt nur speziell annotierte Aktivitäten oder Aktivitäten angezeigt werden, die in der UXR-Zulassungsliste aufgeführt sind. 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 diese Aktivität dem Schlüssel systemActivityWhitelist der Datei /packages/services/Car/service/res/values/config.xml hinzuzufügen. 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 Hotword ist ein Auslösewort, mit dem eine neue Anfrage oder Aktion per Sprachbefehl gestartet wird. Beispiele: „OK Google“ oder „Hey Google“.

DSP-Hotword-Erkennung

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

Die VoiceInteractionService-Implementierung kann mit VoiceInteractionService#createAlwaysOnHotwordDetector(), einen Hotword-Detektor erstellen und dabei eine Schlüsselphrase und ein Gebietsschema übergeben, die für die Erkennung verwendet werden sollen. Dadurch erhält die App ein 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: Die DSP-Unterstützung ist generell nicht verfügbar, aber DSP unterstützt die angegebene Kombination aus Schlüsselphrase und Gebietsschema 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 DSP-Hotword-Erkennung ist möglicherweise nicht auf allen Geräten verfügbar. VIA-Entwickler sollten die Hardwarefunktionen mit der Methode getDspModuleProperties() prüfen. Beispielcode zur Registrierung von Soundmodellen finden Sie unter VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java. Informationen zur gleichzeitigen Hotword-Erkennung finden Sie unter Gleichzeitige Erfassung bezüglich gleichzeitiger Hotword-Erkennung.

Software-Hotword-Erkennung

Wie oben erwähnt, ist die DSP-Hotword-Erkennung möglicherweise nicht auf allen Geräten verfügbar (z. B. bietet der Android-Emulator keine DSP-Emulation). In diesem Fall ist die Software-Spracherkennung die einzige Alternative. Um Konflikte mit anderen Apps zu vermeiden, die möglicherweise Zugriff auf das Mikrofon benötigen, müssen VIAs auf die Audioeingabe mit Folgendem zugreifen:

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

Audioeingabe und Spracherkennung verwalten

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

Vor Android 10 wurde der Mikrofonzugriff jeweils nur einer App gewährt (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, müssen Sie die folgenden Richtlinien beachten: