Aby wdrożyć aplikację do interakcji głosowych (VIA), wykonaj te czynności:
- Utwórz szkielet VIA.
- (opcjonalnie) Wdróż proces konfiguracji lub logowania.
- (opcjonalnie) Wdróż ekran Ustawienia.
- Zadeklaruj wymagane uprawnienia w pliku manifestu.
- Wdróż interfejs płyty głosowej.
- Wdróż rozpoznawanie głosu (musi obejmować implementację interfejsu RecognitionService API).
- Zaimplementuj wypowiedź (opcjonalnie możesz zaimplementować interfejs TextToSpeech API).
- Wdrożenie realizacji poleceń. Zobacz te treści w sekcji Wykonywanie poleceń.
W sekcjach poniżej znajdziesz opis każdego z wymienionych wyżej kroków.
Tworzenie szkieletu VIA
Pliki manifestu
Aplikacja jest wykrywana jako aplikacja z interakcją głosową, gdy w pliku manifestu znajduje się:
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>
W tym przykładzie:
- Asystenci głosowi muszą udostępniać usługę, która rozszerza
VoiceInteractionService, z filtrem intencji dla działaniaVoiceInteractionService.SERVICE_INTERFACE ("android.service.voice.VoiceInteractionService"). - Ta usługa musi mieć uprawnienie do podpisu systemowego
BIND_VOICE_INTERACTION. - Ta usługa powinna zawierać
android.voice_interactionplik metadanych, który zawiera te informacje: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" />
Szczegółowe informacje o poszczególnych polach znajdziesz w sekcji R.styleable#VoiceInteractionService.
Wszystkie usługi VIA są też usługami rozpoznawania głosu, dlatego w pliku manifestu musisz też uwzględnić te informacje:
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>
Usługi rozpoznawania głosu wymagają też tych metadanych:
res/xml/recognition_service.xml
<recognition-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:settingsActivity="com.example.MyRecognizerSettingsActivity" />VoiceInteractionService, VoiceInteractionSessionService i VoiceInteractionSession
Poniższy diagram przedstawia cykl życia każdego z tych elementów:

Rysunek 1. Cykle życia
Jak już wspomnieliśmy, VoiceInteractionService to punkt wejścia
do VIA. Główne obowiązki tego zespołu to:
- Inicjowanie procesów, które powinny być uruchomione tak długo, jak to VIA jest aktywny. Na przykład wykrywanie słów-kluczy.
- Raportuje obsługiwane komendy głosowe (patrz Asystent głosowy – funkcja „Kliknij, aby przeczytać”).
- Uruchamiaj sesje interakcji głosowej z poziomu ekranu blokady (keyguard).
W najprostszej postaci implementacja VoiceInteractionService wyglądałaby tak:
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; } ... }
Wdrożenie VoiceInteractionService#onGetSupportedVoiceActions() jest wymagane do obsługi funkcji dotknij, aby przeczytać Asystenta głosowego.
Usługa VoiceInteractionSessionService jest używana przez system do tworzenia sesji VoiceInteractionSession i wchodzenia z nią w interakcje. Ma tylko jedno zadanie: rozpoczynać nowe sesje na żądanie.
public class MyVoiceInteractionSessionService extends VoiceInteractionSessionService { @Override public VoiceInteractionSession onNewSession(Bundle args) { return new MyVoiceInteractionSession(this); } }
W VoiceInteractionSession wykonywana jest większość pracy. Jedno wystąpienie sesji może być ponownie użyte do wykonania wielu interakcji użytkownika. W AAOS istnieje pomocnik CarVoiceInteractionSession , który pomaga wdrażać niektóre unikalne funkcje motoryzacyjne.
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 ma duży zestaw metod wywołania zwrotnego, które są opisane w sekcjach poniżej. Pełną listę znajdziesz w dokumentacji VoiceInteractionSession.
Wdrażanie procesu konfiguracji lub logowania
Konfigurowanie i logowanie może odbywać się:
- Podczas konfigurowania urządzenia (w kreatorze konfiguracji).
- Podczas przełączania usług interakcji głosowej (Ustawienia).
- Przy pierwszym uruchomieniu po wybraniu aplikacji.
Szczegółowe informacje o zalecanej wygodzie użytkownika i wskazówki wizualne znajdziesz w artykule Wstępnie załadowani asystenci: wskazówki dotyczące UX.
Konfiguracja podczas przełączania usługi głosowej
Użytkownik zawsze może wybrać VIA, który nie został prawidłowo skonfigurowany. Może się tak zdarzyć, ponieważ:
- Użytkownik całkowicie pominął Kreatora konfiguracji lub pominął krok konfiguracji interakcji głosowej.
- Użytkownik wybrał VIA inne niż skonfigurowane podczas wprowadzania urządzenia.
W każdym przypadku VoiceInteractionService może zachęcić użytkownika do dokończenia konfiguracji na kilka sposobów:
- Przypomnienie o powiadomieniu.
- Automatyczna odpowiedź głosowa, gdy użytkownik próbuje z niej skorzystać.
Uwaga: zdecydowanie odradzamy wyświetlanie procesu konfiguracji VIA bez wyraźnej prośby użytkownika. Oznacza to, że VIA nie powinny automatycznie wyświetlać treści na HU podczas uruchamiania urządzenia ani w wyniku przełączenia lub odblokowania przez użytkownika.
Przypomnienie o powiadomieniu
Przypomnienie w formie powiadomienia to nienachalny sposób na poinformowanie o konieczności konfiguracji i umożliwienie użytkownikom przejścia do procesu konfiguracji asystenta.

Rysunek 2. Przypomnienie o powiadomieniu
Proces ten wyglądałby tak:

Rysunek 3. Proces przypominania o powiadomieniach
Odpowiedź głosowa
Jest to najprostszy proces do wdrożenia. Rozpoczyna się on od wywołania zwrotnego VoiceInteractionSession#onShow(), wyjaśnia użytkownikowi, co należy zrobić, a następnie pyta go (jeśli konfiguracja jest dozwolona w danym stanie ograniczeń UX), czy chce rozpocząć proces konfiguracji. Jeśli konfiguracja nie jest w danym momencie możliwa, również to wyjaśnij.
Konfiguracja przy pierwszym użyciu
Użytkownik zawsze może wywołać VIA, która nie została prawidłowo skonfigurowana. W takich przypadkach:
- Poinformuj użytkownika o tej sytuacji (np. „Aby działać prawidłowo, muszę wykonać kilka czynności…”).
- Jeśli silnik ograniczeń UX na to pozwala (patrz UX_RESTRICTIONS_NO_SETUP), zapytaj użytkownika, czy chce rozpocząć proces konfiguracji, a następnie otwórz ekran Ustawienia dla VIA.
- W innych przypadkach (np. gdy użytkownik prowadzi samochód) pozostaw powiadomienie, aby użytkownik mógł kliknąć opcję, gdy będzie to bezpieczne.
Tworzenie ekranów konfiguracji interakcji głosowych
Ekrany konfiguracji i logowania powinny być opracowane jako zwykłe aktywności. Zapoznaj się z wskazówkami dotyczącymi UX i wyglądu interfejsu w preinstalowanych asystentach.
Ogólne wskazówki:
- Asystenci głosowi powinni umożliwiać użytkownikom przerwanie i wznowienie konfiguracji w dowolnym momencie.
- Konfiguracja nie powinna być dozwolona, jeśli obowiązuje ograniczenie
UX_RESTRICTIONS_NO_SETUP. Szczegółowe informacje znajdziesz w wytycznych dotyczących rozpraszania uwagi kierowcy. - Ekrany konfiguracji powinny być zgodne z systemem projektowania każdego pojazdu. Ogólny układ ekranu, ikony, kolory i inne aspekty powinny być spójne z pozostałą częścią interfejsu. Szczegóły znajdziesz w sekcji Dostosowywanie.
Implementowanie ekranu ustawień

Rysunek 4. Integracja ustawień
Ekran ustawień to zwykła aktywność na Androidzie. Jeśli punkt wejścia jest zaimplementowany, musi być zadeklarowany w res/xml/interaction_service.xml w ramach manifestów VIA (patrz Manifesty).
Sekcja Ustawienia to dobre miejsce, aby kontynuować konfigurację i logowanie (jeśli użytkownik nie zakończył tych czynności) lub w razie potrzeby zaoferować opcję wylogowania lub przełączenia użytkownika. Podobnie jak opisane powyżej ekrany konfiguracji, te ekrany powinny:
- Zapewnij możliwość powrotu do poprzedniego ekranu w stosie ekranów (np. do ustawień samochodu).
- nie może być dozwolone podczas jazdy; Szczegółowe informacje znajdziesz we wskazówkach dotyczących rozpraszania uwagi kierowcy.
- Dopasuj każdy system projektowania pojazdów. Więcej informacji znajdziesz w sekcji Dostosowywanie.
Zadeklaruj wymagane uprawnienia w pliku manifestu.
Uprawnienia wymagane przez dostawcę usług weryfikacji tożsamości można podzielić na 3 kategorie:
- Uprawnienia do podpisu systemowego Są to uprawnienia przyznawane tylko wstępnie zainstalowanym plikom APK podpisanym przez system. Użytkownicy nie mogą przyznawać tych uprawnień. Mogą to robić tylko producenci OEM podczas tworzenia obrazów systemu. Więcej informacji o uzyskiwaniu uprawnień do podpisu znajdziesz w artykule Przyznawanie uprawnień systemowych.
- Uprawnienia niebezpieczne Są to uprawnienia, które użytkownik musi przyznać w oknie PermissionsController. Producenci OEM mogą wstępnie przyznawać niektóre z tych uprawnień domyślnej usłudze VoiceInteractionService. Jednak domyślne ustawienia mogą się różnić w zależności od urządzenia, dlatego aplikacje powinny mieć możliwość proszenia o te uprawnienia w razie potrzeby.
- Inne uprawnienia Są to wszystkie inne uprawnienia, które nie wymagają interwencji użytkownika. Te uprawnienia są przyznawane automatycznie przez system.
W związku z tym w sekcji poniżej skupimy się tylko na żądaniu uprawnień niebezpiecznych. O uprawnienia należy prosić tylko wtedy, gdy użytkownik znajduje się na ekranie logowania lub ustawień.
Jeśli aplikacja nie ma uprawnień potrzebnych do działania, zalecamy użycie komunikatu głosowego, aby wyjaśnić sytuację użytkownikowi, oraz powiadomienia, które umożliwi użytkownikowi powrót do ekranów ustawień VIA. Więcej informacji znajdziesz w sekcji 1. przypomnienie o powiadomieniu.
Prośba o uprawnienia na ekranie ustawień
O uprawnienia określane jako niebezpieczne należy prosić za pomocą zwykłej metody ActivityCompat#requestPermission() (lub równoważnej). Szczegółowe informacje o tym, jak poprosić o uprawnienia, znajdziesz w artykule Przekazywanie próśb o uprawnienia aplikacji.

Rysunek 5. Prośba o uprawnienia
Zgoda na odbieranie powiadomień
Aby wdrożyć proces TTR, dostawcy usług weryfikacji tożsamości muszą być wyznaczeni jako odbiorcy powiadomień. Nie jest to samo w sobie uprawnienie, ale konfiguracja, która umożliwia systemowi wysyłanie powiadomień do zarejestrowanych odbiorców. Aby sprawdzić, czy wirtualny asystent otrzymał dostęp do tych informacji, aplikacje mogą:
- (Opcjonalnie) Sprawdź z wyprzedzeniem, czy są dostępne odbiorniki powiadomień, używając
CarAssistUtils#assistantIsNotificationListener(). Można to zrobić np. podczas procesu konfiguracji. - (Obowiązkowe) Reaguj na obsługę
CarVoiceInteractionSession#onShow()za pomocą działaniaVOICE_ACTION_HANDLE_EXCEPTIONi wyjątkuEXCEPTION_NOTIFICATION_LISTENER_PERMISSIONS_MISSING.
Jeśli dostęp nie został wcześniej przyznany, VIA powinna skierować użytkownika do sekcji Dostęp do powiadomień w Ustawieniach samochodu, używając kombinacji wypowiedzi i powiadomień. Poniższy kod umożliwia otwarcie odpowiedniej sekcji aplikacji Ustawienia:
private void requestNotificationListenerAccess() {
Intent intent = new Intent(Settings
.ACTION_NOTIFICATION_LISTENER_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
startActivity(intent);
}Wdrażanie interfejsu tabliczki z głosami
Gdy VoiceInteractionSession otrzyma wywołanie zwrotne onShow(), może wyświetlić interfejs użytkownika z informacjami głosowymi. Wskazówki dotyczące interfejsu i wrażeń użytkownika w przypadku implementacji modułu głosowego znajdziesz w artykule Preloaded Assistants: UX Guidance (Wstępnie załadowani asystenci: wskazówki dotyczące wrażeń użytkownika).

Rysunek 6. Wyświetlanie tabliczki z głosami
Ten interfejs użytkownika można wdrożyć na 2 sposoby:
- Zastąp
VoiceInteractionSession#onCreateContentView() - Uruchamianie aktywności przy użyciu dodatku
VoiceInteractionSession#startAssistantActivity()
Używanie metody onCreateContentView()
Jest to domyślny sposób prezentowania tabliczki z głosem. Klasa bazowa VoiceInteractionSessiontworzy okno i zarządza jego cyklem życia tak długo, jak trwa sesja głosowa. Aplikacje muszą zastąpić VoiceInteractionSession#onCreateContentView() i zwrócić widok dołączony do tego okna natychmiast po utworzeniu sesji. Ten widok powinien być początkowo niewidoczny. Gdy rozpocznie się interakcja głosowa, ten widok powinien być widoczny na urządzeniu VoiceInteractionSession#onShow(), a potem ponownie niewidoczny na urządzeniu 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); } … }
Jeśli używasz tej metody, możesz dostosować VoiceInteractionSession#onComputeInsets(), aby uwzględnić zasłonięte obszary interfejsu.
Używanie funkcji startAssistantActivity()
W takim przypadku VoiceInteractionSession przekazuje obsługę interfejsu tablicy głosowej do zwykłej aktywności. Gdy ta opcja jest używana, implementacja VoiceInteractionSession musi wyłączyć tworzenie domyślnego okna treści (patrz Using onCreateContentView()) w wywołaniu zwrotnym onPrepareShow(). O godzinie VoiceInteractionSession#onShow() sesja rozpocznie aktywność związaną z komendami głosowymi przy użyciu usługi VoiceInteractionSession#startAssistantActivity(). Ta metoda inicjuje interfejs z odpowiednimi ustawieniami okna i flagami aktywności.
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); } … }
Aby utrzymać komunikację między tą aktywnością a VoiceInteractionSession, może być wymagany zestaw wewnętrznych intencji lub powiązanie usługi. Gdy na przykład wywoływana jest funkcja VoiceInteractionSession#onHide(), sesja musi być w stanie przekazać to żądanie do aktywności.
Ważne: W przypadku motoryzacji podczas jazdy mogą być wyświetlane tylko specjalnie oznaczone aktywności lub aktywności wymienione na „białej liście” UXR. Dotyczy to również aktywności rozpoczętych za pomocą VoiceInteractionSession#startAssistantActivity(). Pamiętaj, aby dodać do aktywności adnotację <meta-data
android:name="distractionOptimized" android:value="true"/> lub uwzględnić tę aktywność w kluczu systemActivityWhitelist pliku /packages/services/Car/service/res/values/config.xml. Więcej informacji znajdziesz w wytycznych dotyczących rozpraszania uwagi kierowcy.
Wdrażanie rozpoznawania głosu
Z tej sekcji dowiesz się, jak wdrożyć rozpoznawanie głosu za pomocą wykrywania i rozpoznawania słów aktywujących. Słowo aktywujące to słowo wyzwalające używane do rozpoczęcia nowego zapytania lub działania za pomocą głosu. na przykład „OK Google” lub „Hej Google”.
Wykrywanie słowa-klucza przez procesor DSP
Android zapewnia dostęp do zawsze włączonego detektora słów kluczowych na poziomie procesora DSP za pomocą interfejsu AlwaysOnHotwordDetector.
sposób wdrożenia wykrywania słów-kluczy przy niskim wykorzystaniu procesora. Korzystanie z tej funkcji dzieli się na 2 części:
- Utworzenie instancji
AlwaysOnHotwordDetector. - Rejestracja modelu dźwiękowego wykrywania słowa-klucza.
Implementacja VoiceInteractionService może utworzyć detektor słów aktywujących za pomocą
VoiceInteractionService#createAlwaysOnHotwordDetector(),
przekazując kluczową frazę i ustawienia regionalne, które mają być używane do wykrywania. W rezultacie aplikacja otrzymuje wywołanie zwrotne onAvailabilityChanged() z jedną z tych wartości:
STATE_HARDWARE_UNAVAILABLE. Funkcja DSP jest niedostępna na tym urządzeniu. W tym przypadku używane jest wykrywanie słów-kluczy przez oprogramowanie.STATE_HARDWARE_UNSUPPORTED. Obsługa platformy DSP nie jest dostępna w ogóle, ale platforma DSP nie obsługuje podanej kombinacji słów kluczowych i języka. Aplikacja może korzystać z programowego wykrywania słów kluczowych.STATE_HARDWARE_ENROLLED. Wykrywanie słów-kluczy jest gotowe i można je uruchomić, wywołując metodęstartRecognition().STATE_HARDWARE_UNENROLLED. Model dźwiękowy dla żądanej kluczowej frazy jest niedostępny, ale rejestracja jest możliwa.
Rejestracja modeli dźwiękowych wykrywania słów-kluczy może odbywać się za pomocą IVoiceInteractionManagerService#updateKeyphraseSoundModel().
W systemie może być zarejestrowanych wiele modeli, ale tylko jeden z nich jest powiązany z AlwaysOnHotwordDetector.
Wykrywanie słów kluczowych przez procesor DSP może nie być dostępne na wszystkich urządzeniach. Deweloperzy VIA powinni sprawdzać możliwości sprzętowe za pomocą metody getDspModuleProperties(). Przykładowy kod pokazujący, jak rejestrować modele dźwiękowe, znajdziesz w VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java.
Więcej informacji o jednoczesnym rozpoznawaniu słów aktywujących znajdziesz w sekcji Jednoczesne przechwytywanie.
Wykrywanie słów-kluczy przez oprogramowanie
Jak wspomnieliśmy powyżej, wykrywanie słowa aktywacyjnego przez procesor DSP może nie być dostępne na wszystkich urządzeniach (np. emulator Androida nie zapewnia emulacji procesora DSP). W takim przypadku jedyną alternatywą jest rozpoznawanie głosu przez oprogramowanie. Aby uniknąć zakłóceń w działaniu innych aplikacji, które mogą potrzebować dostępu do mikrofonu, wirtualni asystenci muszą uzyskiwać dostęp do wejścia audio za pomocą:
- Przechwytywanie dźwięku musi korzystać z MediaRecorder.AudioSource.HOTWORD.
- mieć uprawnienie
android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
Obie te stałe mają wartość @hide i są dostępne tylko dla aplikacji w pakiecie.
Zarządzanie danymi wejściowymi audio i rozpoznawaniem głosu
Wejście audio będzie realizowane za pomocą klasy MediaRecorder.
Więcej informacji o korzystaniu z tego interfejsu API znajdziesz w artykule MediaRecorder – omówienie. Usługi interakcji głosowej również powinny być implementacjami klasy RecognitionService. Każda aplikacja w systemie, która wymaga rozpoznawania głosu, korzysta z tej funkcji. Aby korzystać z rozpoznawania głosu i mieć dostęp do mikrofonu, VIA musi mieć android.permission.RECORD_AUDIO.
Aplikacje korzystające z implementacji RecognitionService
również powinny mieć to uprawnienie.
Przed Androidem 10 dostęp do mikrofonu miała tylko jedna aplikacja naraz (z wyjątkiem wykrywania słów aktywujących – patrz wyżej). Od Androida 10 dostęp do mikrofonu może być udostępniany. Więcej informacji znajdziesz w artykule Udostępnianie wejścia audio.
Dostęp do wyjścia audio
Gdy wirtualny asystent jest gotowy do udzielania odpowiedzi głosowych, ważne jest, aby przestrzegać tych wytycznych:
- Podczas żądania fokusu audio lub zarządzania wyjściem audio aplikacja musi używać atrybutów audio
AudioAttributes#USAGE_ASSISTANTiAudioAttributes#CONTENT_TYPE_SPEECH. - Podczas rozpoznawania mowy należy poprosić o skupienie dźwięku za pomocą
AudioManage#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE. Pamiętaj, że niektóre aplikacje multimedialne mogą nie reagować prawidłowo na polecenia multimedialne (patrz Realizowanie poleceń multimedialnych), gdy ich fokus audio zostanie usunięty.