Tworzenie aplikacji

Aby zaimplementować aplikację interakcji głosowej (VIA), wykonaj następujące kroki:

  1. Utwórz szkielet VIA.
  2. ( opcjonalnie ) Zaimplementuj przepływ konfiguracji/logowania.
  3. ( opcjonalnie ) Zaimplementuj ekran Ustawienia.
  4. Zadeklaruj wymagane uprawnienia w pliku manifestu.
  5. Zaimplementuj interfejs użytkownika płyty głosowej.
  6. Zaimplementuj rozpoznawanie głosu (musi obejmować implementację API RecognitionService).
  7. Zaimplementuj wypowiedź (opcjonalnie możesz zaimplementować interfejs API TextToSpeech).
  8. Implementuj realizację poleceń. Zobacz tę treść w części Wykonywanie poleceń .

W poniższych sekcjach opisano, jak wykonać każdy krok wymieniony powyżej.

Utwórz szkielet VIA

Manifestuje

Aplikacja jest wykrywana jako obsługująca interakcję głosową, jeśli w manifeście znajdują się następujące informacje:

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:

  • VIA muszą udostępniać usługę rozszerzającą VoiceInteractionService z filtrem intencji dla akcji VoiceInteractionService.SERVICE_INTERFACE ("android.service.voice.VoiceInteractionService") .
  • Ta usługa musi posiadać uprawnienia do podpisu systemowego BIND_VOICE_INTERACTION .
  • Usługa ta powinna zawierać plik metadanych android.voice_interaction zawierający następujące 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" />
    

Aby uzyskać szczegółowe informacje na temat każdego pola, zobacz R.styleable#VoiceInteractionService . Biorąc pod uwagę, że wszystkie VIA to także usługi rozpoznawania głosu, w swoim manifeście musisz także zawrzeć następujące 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ą również następujących 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 podmiotów:

Cykle życia

Rysunek 1. Cykle życia

Jak wspomniano wcześniej, VoiceInteractionService jest punktem wejścia do VIA. Do głównych obowiązków tej usługi należy:

  • Zainicjuj wszystkie procesy, które powinny działać tak długo, jak ten VIA jest aktywny. Na przykład wykrywanie słów kluczowych.
  • Raportuje obsługiwane akcje głosowe (patrz Asystent głosowy „Dotknij, aby przeczytać” ).
  • Uruchamiaj sesje interakcji głosowej z ekranu blokady (klawiatura).

W najprostszej formie implementacja VoiceInteractionService wyglądałaby następująco:

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

Do obsługi funkcji Tap-to-Read asystenta głosowego wymagana jest implementacja VoiceInteractionService#onGetSupportedVoiceActions() . Usługa VoiceInteractionSessionService jest używana przez system do tworzenia sesji VoiceInteractionSession i interakcji z nią. Ma tylko jeden obowiązek: rozpoczynać nowe sesje na żądanie.

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

Wreszcie, większość pracy zostanie wykonana w sesji VoiceInteractionSession . Pojedyncza instancja sesji może zostać ponownie wykorzystana do realizacji wielu interakcji użytkownika. W AAOS istnieje pomocnicza CarVoiceInteractionSession , pomagająca wdrożyć niektóre unikalne funkcjonalności 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ą wyjaśnione w poniższych sekcjach. zobacz pełną listę w dokumentacji VoiceInteractionSession .

Zaimplementuj przepływ konfiguracji/logowania

Konfiguracja i logowanie mogą nastąpić:

  • Podczas dołączania urządzenia (Kreator konfiguracji).
  • Podczas zmiany usług interakcji głosowej (Ustawienia).
  • Przy pierwszym uruchomieniu, gdy aplikacja jest wybrana.

Aby uzyskać szczegółowe informacje na temat zalecanego środowiska użytkownika i wskazówek wizualnych, zobacz Wstępnie załadowani asystenci: Wskazówki dotyczące UX .

Konfiguracja podczas zmiany usług głosowych

Użytkownik zawsze może wybrać VIA, który nie został poprawnie skonfigurowany. Może się to zdarzyć, ponieważ:

  • Użytkownik całkowicie pominął Kreatora instalacji lub krok konfiguracji interakcji głosowej.
  • Użytkownik wybrał VIA inny niż ten skonfigurowany podczas instalowania urządzenia.

W każdym razie VoiceInteractionService ma kilka sposobów na zachęcenie użytkownika do dokończenia konfiguracji:

  • Przypomnienie o powiadomieniu.
  • Automatyczna odpowiedź głosowa, gdy użytkownik spróbuje z niej skorzystać.

Uwaga : Zdecydowanie odradza się przedstawianie procesu konfiguracji VIA bez wyraźnej prośby użytkownika. Oznacza to, że VIA powinny unikać automatycznego wyświetlania treści na HU podczas uruchamiania urządzenia lub w wyniku zmiany użytkownika lub odblokowania.

Przypomnienie o powiadomieniu

Przypomnienie o powiadomieniu to nieinwazyjny sposób wskazania potrzeby konfiguracji i zapewnienia użytkownikom możliwości przejścia do procesu konfiguracji asystenta.

Przypomnienie o powiadomieniu

Rysunek 2. Przypomnienie o powiadomieniu

Oto jak będzie działać ten przepływ:

Przepływ przypomnień o powiadomieniach

Rysunek 3. Przebieg przypomnienia o powiadomieniu

Odpowiedź głosowa

Jest to najprostszy sposób do wdrożenia, polegający na inicjowaniu wypowiedzi w wywołaniu zwrotnym VoiceInteractionSession#onShow() , wyjaśnianiu użytkownikowi, co należy zrobić, a następnie pytaniu go (jeśli konfiguracja jest dozwolona ze względu na stan ograniczenia UX), czy chce zainicjować przebieg konfiguracji. Jeśli konfiguracja nie jest w danym momencie możliwa, wyjaśnij również tę sytuację.

Konfiguracja przy pierwszym użyciu

Użytkownik zawsze może uruchomić VIA, który nie został poprawnie skonfigurowany. W takich sprawach:

  1. Poinformuj użytkownika ustnie o tej sytuacji (na przykład: „Aby działać poprawnie, musisz wykonać kilka kroków…”).
  2. Jeśli silnik ograniczeń UX na to pozwala (patrz UX_RESTRICTIONS_NO_SETUP ), zapytaj użytkownika, czy chce rozpocząć proces instalacji, a następnie otwórz ekran Ustawienia dla VIA.
  3. W przeciwnym razie (na przykład, jeśli użytkownik prowadzi samochód), pozostaw powiadomienie dla użytkownika, aby mógł kliknąć opcję, gdy będzie to bezpieczne.

Twórz ekrany konfiguracji interakcji głosowych

Ekrany konfiguracji i logowania powinny być opracowywane w ramach zwykłych działań . Zobacz wskazówki dotyczące UX i wizualne dotyczące opracowywania interfejsu użytkownika w Wstępnie załadowanych asystentach: Wskazówki dotyczące UX .

Ogólne wytyczne:

  • VIA powinny umożliwiać użytkownikom przerwanie i wznowienie konfiguracji w dowolnym momencie.
  • Instalacja nie powinna być dozwolona, ​​jeśli obowiązuje ograniczenie UX_RESTRICTIONS_NO_SETUP . Aby uzyskać szczegółowe informacje, zobacz Wytyczne dotyczące rozpraszania uwagi kierowcy .
  • Ekrany konfiguracji powinny odpowiadać systemowi projektowemu każdego pojazdu. Ogólny układ ekranu, ikony, kolory i inne aspekty powinny być spójne z resztą interfejsu użytkownika. Aby uzyskać szczegółowe informacje, zobacz Dostosowywanie .

Zaimplementuj ekran ustawień

Integracja ustawień

Rysunek 4. Integracja ustawień

Ekrany ustawień to zwykłe czynności związane z Androidem. Jeśli zostały zaimplementowane, ich punkt wejścia musi zostać zadeklarowany w pliku res/xml/interaction_service.xml jako część manifestów VIA (zobacz Manifesty ). Sekcja Ustawienia to dobre miejsce, aby kontynuować konfigurację i zalogować się (jeśli użytkownik tego nie dokończył) lub w razie potrzeby zaoferować opcję wylogowania się lub zmiany użytkownika . Podobnie jak w przypadku ekranów konfiguracji opisanych powyżej, ekrany te powinny:

  • Zapewnij możliwość wyjścia z powrotem do poprzedniego ekranu na stosie ekranów (na przykład do Ustawień samochodu).
  • Nie wolno podczas jazdy. Aby uzyskać szczegółowe informacje, zobacz Wytyczne dotyczące rozpraszania uwagi kierowcy .
  • Dopasuj każdy system projektowania pojazdów. Aby uzyskać szczegółowe informacje, zobacz Dostosowywanie .

Zadeklaruj wymagane uprawnienia w pliku manifestu

Uprawnienia wymagane przez VIA można podzielić na trzy kategorie:

  • Uprawnienia do podpisu systemu. Są to uprawnienia przyznawane tylko dla wstępnie zainstalowanych, podpisanych przez system plików APK. Użytkownicy nie mogą przyznawać tych uprawnień. Tylko producenci OEM mogą je przyznawać podczas tworzenia obrazów systemów. Aby uzyskać więcej informacji na temat uzyskiwania uprawnień do podpisu, zobacz temat Przyznawanie uprawnień uprzywilejowanych systemowo .
  • Niebezpieczne uprawnienia. Są to uprawnienia, które użytkownik musi przyznać za pomocą okna dialogowego PermissionsController. Producenci OEM mogą wstępnie przyznać niektóre z tych uprawnień domyślnej usłudze VoiceInteractionService. Biorąc jednak pod uwagę, że to ustawienie domyślne może się zmieniać w zależności od urządzenia, aplikacje powinny mieć możliwość zażądania tych uprawnień w razie potrzeby.
  • Inne uprawnienia. Są to wszystkie inne uprawnienia, które nie wymagają interwencji użytkownika. Uprawnienia te są nadawane automatycznie przez system.

Biorąc pod uwagę powyższe, następna sekcja koncentruje się wyłącznie na żądaniu niebezpiecznych uprawnień. O uprawnienia należy pytać tylko wtedy, gdy użytkownik znajduje się na ekranie logowania lub ustawień.

Jeśli aplikacja nie ma uprawnień niezbędnych do działania, zaleca się użycie wypowiedzi głosowej w celu wyjaśnienia użytkownikowi sytuacji oraz powiadomienia zapewniającego afordancję, za pomocą której użytkownik może wrócić do ekranów ustawień VIA . Aby uzyskać szczegółowe informacje, zobacz 1. Przypomnienie o powiadomieniu .

Poproś o uprawnienia w ramach ekranu ustawień

Niebezpieczne uprawnienia są wymagane przy użyciu zwykłej metody ActivityCompat#requestPermission() (lub jej odpowiednika). Aby uzyskać szczegółowe informacje na temat żądania uprawnień, zobacz temat Żądanie uprawnień aplikacji .

Poproś o uprawnienia

Rysunek 5. Poproś o uprawnienia

Uprawnienie słuchacza powiadomień

Aby zaimplementować przepływ TTR, VIA muszą zostać wyznaczone jako słuchacze powiadomień. Nie jest to samo zezwolenie, ale konfiguracja umożliwiająca systemowi wysyłanie powiadomień do zarejestrowanych słuchaczy. Aby dowiedzieć się, czy VIA uzyskała dostęp do tych informacji, aplikacje mogą:

Jeżeli dostęp ten nie został wcześniej przyznany, VIA powinna skierować użytkownika do sekcji Dostęp do powiadomień w Ustawieniach samochodu, korzystając z kombinacji wypowiedzi i powiadomień. Poniższego kodu można użyć do otwarcia odpowiedniej sekcji aplikacji ustawień:

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

Zaimplementuj interfejs użytkownika płyty głosowej

Gdy sesja VoiceInteractionSession odbierze wywołanie zwrotne onShow() , może zaprezentować interfejs użytkownika płytki głosowej. Wskazówki wizualne i UX dotyczące implementacji płytki głosowej można znaleźć w artykule Wstępnie załadowani asystenci: Wskazówki dotyczące UX .

Wyświetlanie płytki głosowej

Rysunek 6. Wyświetlanie płytki głosowej

Istnieją dwie możliwości wdrożenia tego interfejsu użytkownika:

  • Zastąp sesję VoiceInteractionSession#onCreateContentView()
  • Uruchom działanie za pomocą VoiceInteractionSession#startAssistantActivity()

Użyj funkcji onCreateContentView()

Jest to domyślny sposób prezentacji płyty głosowej. Klasa bazowa VoiceInteractionSession tworzy okno i zarządza jego cyklem życia tak długo, jak długo trwa sesja głosowa. Aplikacje muszą zastąpić VoiceInteractionSession#onCreateContentView() i zwrócić widok dołączony do tego okna zaraz po utworzeniu sesji. Widok ten powinien być początkowo niewidoczny. Po rozpoczęciu interakcji głosowej widok ten powinien być widoczny w VoiceInteractionSession#onShow() , a następnie ponownie niewidoczny w 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);
    }
    …
}

Korzystając z tej metody, możesz chcieć dostosować VoiceInteractionSession#onComputeInsets() , aby uwzględnić zasłonięte obszary interfejsu użytkownika.

Użyj startAssistantActivity()

W tym przypadku VoiceInteractionSession deleguje obsługę interfejsu użytkownika płytki głosowej do zwykłego działania. Kiedy ta opcja jest używana, implementacja VoiceInteractionSession musi wyłączyć tworzenie domyślnego okna zawartości (zobacz Korzystanie z onCreateContentView() ) w wywołaniu zwrotnym onPrepareShow() . W VoiceInteractionSession#onShow() sesja rozpoczynałaby działanie płyty głosowej za pomocą VoiceInteractionSession#startAssistantActivity() . Ta metoda inicjuje interfejs użytkownika 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 tym działaniem a VoiceInteractionSession , może być wymagany zestaw wewnętrznych intencji lub powiązania usługi. Na przykład po wywołaniu funkcji VoiceInteractionSession#onHide() sesja musi mieć możliwość przekazania tego żądania do działania.

Ważny. W branży motoryzacyjnej podczas jazdy można wyświetlać wyłącznie czynności opatrzone specjalnymi adnotacjami lub czynności wymienione na „liście dozwolonych” UXR. Dotyczy to również działań rozpoczętych za pomocą VoiceInteractionSession#startAssistantActivity() . Pamiętaj, aby opatrzyć swoją aktywność adnotacją <meta-data android:name="distractionOptimized" android:value="true"/> lub uwzględnić tę aktywność w kluczu systemActivityWhitelist /packages/services/Car/service/res/values/config.xml plik /packages/services/Car/service/res/values/config.xml . Aby uzyskać więcej informacji, zobacz Wskazówki dotyczące rozpraszania uwagi kierowcy .

Zaimplementuj rozpoznawanie głosu

W tej sekcji dowiesz się, jak wdrożyć rozpoznawanie głosu poprzez wykrywanie i rozpoznawanie słów kluczowych. Słowo-klucz to słowo wyzwalające używane do rozpoczęcia nowego zapytania lub akcji za pomocą głosu. Na przykład „OK Google” lub „Hej Google”.

Wykrywanie słów-kluczy DSP

Android zapewnia dostęp do zawsze włączonego detektora słów kluczowych na poziomie DSP za pomocą AlwaysOnHotwordDetector . sposób na wdrożenie wykrywania słów-kluczy przy niskim procesorze. Korzystanie z tej funkcjonalności podzielone jest na dwie części:

Implementacja VoiceInteractionService może utworzyć detektor słów-kluczy za pomocą VoiceInteractionService#createAlwaysOnHotwordDetector() , przekazując frazę kluczową i ustawienia regionalne, których chcą używać do wykrywania. W rezultacie aplikacja otrzymuje wywołanie zwrotne onAvailabilityChanged() z jedną z następujących możliwych wartości:

  • STATE_HARDWARE_UNAVAILABLE . Urządzenie nie obsługuje funkcji DSP. W tym przypadku wykorzystywane jest oprogramowanie do wykrywania słów kluczowych.
  • STATE_HARDWARE_UNSUPPORTED . Obsługa DSP nie jest ogólnie dostępna, ale DSP nie obsługuje danej kombinacji słów kluczowych i ustawień regionalnych. Aplikacja może zdecydować się na oprogramowanie do wykrywania słów kluczowych .
  • STATE_HARDWARE_ENROLLED . Wykrywanie gorących słów jest już gotowe i można je uruchomić wywołując metodę startRecognition() .
  • STATE_HARDWARE_UNENROLLED . Model dźwiękowy dla żądanej frazy kluczowej nie jest dostępny, ale możliwa jest rejestracja.

Rejestrację modeli dźwiękowych do wykrywania słów kluczowych można wykonać za pomocą IVoiceInteractionManagerService#updateKeyphraseSoundModel() . W systemie może być zarejestrowanych jednocześnie wiele modeli, ale tylko jeden model jest powiązany z AlwaysOnHotwordDetector . Wykrywanie słów kluczowych DSP może nie być dostępne na wszystkich urządzeniach. Programiści VIA powinni sprawdzić możliwości sprzętu za pomocą metody getDspModuleProperties() . Przykładowy kod pokazujący sposób rejestrowania modeli dźwięku można znaleźć w VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java . Zobacz Współbieżne przechwytywanie dotyczące jednoczesnego rozpoznawania słów-kluczy.

Oprogramowanie do wykrywania słów kluczowych

Jak wskazano powyżej, wykrywanie słów kluczowych DSP może nie być dostępne na wszystkich urządzeniach (na przykład emulator Androida nie zapewnia emulacji DSP). W tym przypadku jedyną alternatywą jest programowe rozpoznawanie głosu. Aby uniknąć zakłócania działania innych aplikacji, które mogą potrzebować dostępu do mikrofonu, urządzenia VIA muszą uzyskać dostęp do wejścia audio za pomocą:

Obie te stałe są @hide i są dostępne tylko dla aplikacji dołączonych do pakietu.

Zarządzaj wejściem audio i rozpoznawaniem głosu

Wejście audio zostanie zaimplementowane przy użyciu klasy MediaRecorder . Aby uzyskać więcej informacji na temat korzystania z tego interfejsu API, zobacz Omówienie MediaRecorder . Oczekuje się, że usługi interakcji głosowej będą również implementacjami klasy RecognitionService . Każda aplikacja w systemie, która wymaga rozpoznawania głosu, korzysta z tej możliwości. Aby móc rozpoznawać głos i mieć dostęp do mikrofonu, VIA musi posiadać android.permission.RECORD_AUDIO . Oczekuje się, że aplikacje uzyskujące dostęp do implementacji RecognitionService również będą posiadać to uprawnienie.

Przed Androidem 10 dostęp do mikrofonu miała tylko jedna aplikacja na raz (z wyjątkiem wykrywania słów-kluczy, patrz wyżej). Począwszy od Androida 10, dostęp do mikrofonu można udostępniać. Aby uzyskać więcej informacji, zobacz Udostępnianie wejścia audio .

Uzyskaj dostęp do wyjścia audio

Kiedy VIA będzie gotowa do udzielenia odpowiedzi ustnej, ważne jest, aby postępować zgodnie z poniższym zestawem wytycznych: