Asystent Google i aplikacje do multimediów

Asystent Google umożliwia sterowanie wieloma urządzeniami, np. Google Home czy telefonem, za pomocą poleceń głosowych. Ma wbudowaną obsługę poleceń multimedialnych („odtwarzanie czegoś w wykonaniu Beyoncé”) i obsługuje elementy sterujące multimediami (np. wstrzymaj, pomiń, przewiń do przodu, kliknij kciuk w górę).

Asystent komunikuje się z aplikacjami do multimediów na Androida w ramach sesji multimediów. Może użyć zamiarów lub usług, aby uruchomić aplikację i rozpocząć odtwarzanie. Aby uzyskać najlepsze wyniki, aplikacja powinna stosować wszystkie funkcje opisane na tej stronie.

Użyj sesji multimediów

Każda aplikacja audio i wideo musi implementować sesję multimediów, by po rozpoczęciu odtwarzania Asystent mógł obsługiwać elementy sterujące transportem.

Pamiętaj, że chociaż Asystent wykonuje tylko działania wymienione w tej sekcji, najlepiej jest zaimplementować wszystkie interfejsy API przygotowywania i odtwarzania, by zapewnić zgodność z innymi aplikacjami. W przypadku działań, których nie obsługujesz, wywołania zwrotne sesji multimediów mogą po prostu zwracać błąd, korzystając z metody ERROR_CODE_NOT_SUPPORTED.

Włącz opcje sterowania multimediami i transportem, ustawiając te flagi w obiekcie MediaSession aplikacji:

Kotlin

session.setFlags(
        MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or
        MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
)

Java

session.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
    MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);

Sesja multimediów w aplikacji musi zadeklarować obsługiwane działania i zaimplementować odpowiednie wywołania zwrotne sesji multimediów. Zadeklaruj obsługiwane działania w narzędziu setActions().

Przykładowy projekt Universal Android Music Player to dobry przykład konfiguracji sesji multimediów.

Działania związane z odtwarzaniem

Aby rozpocząć odtwarzanie z usługi, sesja multimediów musi zawierać te działania PLAY i ich wywołania zwrotne:

Działanie Oddzwanianie
ACTION_PLAY onPlay()
ACTION_PLAY_FROM_SEARCH onPlayFromSearch()
ACTION_PLAY_FROM_URI (*) onPlayFromUri()

W sesji powinna też wdrożyć te działania PREPARE i ich wywołania zwrotne:

Działanie Oddzwanianie
ACTION_PREPARE onPrepare()
ACTION_PREPARE_FROM_SEARCH onPrepareFromSearch()
ACTION_PREPARE_FROM_URI (*) onPrepareFromUri()

* Działania oparte na identyfikatorach URI Asystenta Google działają tylko w firmach, które udostępniają Google identyfikatory URI. Więcej informacji o opisie treści multimedialnych Google znajdziesz w artykule Działania związane z multimediami.

Wdrożenie interfejsów API przygotowań pozwala zmniejszyć opóźnienia odtwarzania po wykonaniu polecenia głosowego. Aplikacje do multimediów, które chcą zmniejszyć opóźnienia odtwarzania, mogą wykorzystać dodatkowy czas na rozpoczęcie zapisywania treści w pamięci podręcznej i przygotowywanie odtwarzania multimediów.

Analizuj wyszukiwane hasła

Gdy użytkownik wyszukuje określony element multimedialny, np. „Włącz jazz na [nazwa aplikacji]” lub „Posłuchaj [tytuł utworu]”, metoda wywołania zwrotnego onPrepareFromSearch() lub onPlayFromSearch() otrzyma parametr zapytania i pakiet dodatków.

Aplikacja powinna przeanalizować zapytanie wyszukiwania głosowego i rozpocząć odtwarzanie, wykonując te czynności:

  1. Do filtrowania wyników używaj pakietu dodatków i ciągu zapytania zwracanego z wyszukiwania głosowego.
  2. Na podstawie tych wyników utwórz kolejkę odtwarzania.
  3. Odtwórz najbardziej odpowiedni element multimedialny z wyników.

Metoda onPlayFromSearch() wykorzystuje parametr „Extras” z bardziej szczegółowymi informacjami z wyszukiwania głosowego. Te dodatki ułatwiają znajdowanie treści audio w aplikacji i ich odtwarzanie. Jeśli w wynikach wyszukiwania nie można znaleźć tych danych, możesz zastosować mechanizmy logiczne, które przeanalizują nieprzetworzone zapytanie i odtwarzają na jego podstawie odpowiednie ścieżki.

W systemie operacyjnym Android Automotive i Androidzie Auto dostępne są te dodatki:

Ten fragment kodu pokazuje, jak zastąpić metodę onPlayFromSearch() w implementacji MediaSession.Callback, aby przeanalizować zapytanie wyszukiwania głosowego i rozpocząć odtwarzanie:

Kotlin

override fun onPlayFromSearch(query: String?, extras: Bundle?) {
    if (query.isNullOrEmpty()) {
        // The user provided generic string e.g. 'Play music'
        // Build appropriate playlist queue
    } else {
        // Build a queue based on songs that match "query" or "extras" param
        val mediaFocus: String? = extras?.getString(MediaStore.EXTRA_MEDIA_FOCUS)
        if (mediaFocus == MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE) {
            isArtistFocus = true
            artist = extras.getString(MediaStore.EXTRA_MEDIA_ARTIST)
        } else if (mediaFocus == MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE) {
            isAlbumFocus = true
            album = extras.getString(MediaStore.EXTRA_MEDIA_ALBUM)
        }

        // Implement additional "extras" param filtering
    }

    // Implement your logic to retrieve the queue
    var result: String? = when {
        isArtistFocus -> artist?.also {
            searchMusicByArtist(it)
        }
        isAlbumFocus -> album?.also {
            searchMusicByAlbum(it)
        }
        else -> null
    }
    result = result ?: run {
        // No focus found, search by query for song title
        query?.also {
            searchMusicBySongTitle(it)
        }
    }

    if (result?.isNotEmpty() == true) {
        // Immediately start playing from the beginning of the search results
        // Implement your logic to start playing music
        playMusic(result)
    } else {
        // Handle no queue found. Stop playing if the app
        // is currently playing a song
    }
}

Java

@Override
public void onPlayFromSearch(String query, Bundle extras) {
    if (TextUtils.isEmpty(query)) {
        // The user provided generic string e.g. 'Play music'
        // Build appropriate playlist queue
    } else {
        // Build a queue based on songs that match "query" or "extras" param
        String mediaFocus = extras.getString(MediaStore.EXTRA_MEDIA_FOCUS);
        if (TextUtils.equals(mediaFocus,
                MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE)) {
            isArtistFocus = true;
            artist = extras.getString(MediaStore.EXTRA_MEDIA_ARTIST);
        } else if (TextUtils.equals(mediaFocus,
                MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE)) {
            isAlbumFocus = true;
            album = extras.getString(MediaStore.EXTRA_MEDIA_ALBUM);
        }

        // Implement additional "extras" param filtering
    }

    // Implement your logic to retrieve the queue
    if (isArtistFocus) {
        result = searchMusicByArtist(artist);
    } else if (isAlbumFocus) {
        result = searchMusicByAlbum(album);
    }

    if (result == null) {
        // No focus found, search by query for song title
        result = searchMusicBySongTitle(query);
    }

    if (result != null && !result.isEmpty()) {
        // Immediately start playing from the beginning of the search results
        // Implement your logic to start playing music
        playMusic(result);
    } else {
        // Handle no queue found. Stop playing if the app
        // is currently playing a song
    }
}
onPlayFromSearch()

Bardziej szczegółowy przykład implementowania wyszukiwania głosowego w celu odtwarzania treści audio w aplikacji znajdziesz w artykule o Universal Android Music Player.

Obsługa pustych zapytań

Jeśli funkcja onPrepare(), onPlay(), onPrepareFromSearch() lub onPlayFromSearch() zostanie wywołana bez zapytania, aplikacja do multimediów powinna odtworzyć „bieżące” multimedia. Jeśli nie ma aktualnych multimediów, aplikacja powinna spróbować coś odtworzyć, na przykład utwór z ostatniej playlisty lub losowej kolejki. Asystent używa tych interfejsów API, gdy użytkownik prosi o „Włącz muzykę w aplikacji [nazwa aplikacji]” bez dodatkowych informacji.

Gdy użytkownik powie „Włącz muzykę w [nazwa aplikacji]”, system operacyjny Android Automotive lub Android Auto spróbuje uruchomić aplikację i odtworzyć dźwięk, wywołując metodę onPlayFromSearch() aplikacji. Ponieważ jednak użytkownik nie podał nazwy elementu multimedialnego, metoda onPlayFromSearch() otrzymuje pusty parametr zapytania. W takich przypadkach aplikacja powinna od razu zareagować, odtwarzając dźwięk, np. utwór z najnowszej playlisty lub losową kolejkę.

Deklarowanie starszej wersji komend głosowych

W większości przypadków obsługa opisanych powyżej działań odtwarzania zapewnia aplikacji wszystkie funkcje odtwarzania, których potrzebuje. Niektóre systemy wymagają jednak, aby aplikacja zawierała filtr intencji dla wyszukiwania. Obsługę tego filtra intencji zadeklaruj w plikach manifestu aplikacji.

Umieść ten kod w pliku manifestu aplikacji na telefon:

<activity>
    <intent-filter>
        <action android:name=
             "android.media.action.MEDIA_PLAY_FROM_SEARCH" />
        <category android:name=
             "android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

Kontrola transportu

Po aktywowaniu sesji multimediów w aplikacji Asystent może wydawać polecenia głosowe, aby sterować odtwarzaniem i aktualizować metadane multimediów. Aby to działało, kod powinien umożliwiać wykonywanie tych działań i zaimplementować odpowiednie wywołania zwrotne:

Działanie Oddzwanianie Opis
ACTION_SKIP_TO_NEXT onSkipToNext() Następny film
ACTION_SKIP_TO_PREVIOUS onSkipToPrevious() Poprzedni utwór
ACTION_PAUSE, ACTION_PLAY_PAUSE onPause() Wstrzymaj
ACTION_STOP onStop() Zatrzymaj
ACTION_PLAY onPlay() Wznów
ACTION_SEEK_TO onSeekTo() Przewiń do tyłu o 30 sekund.
ACTION_SET_RATING onSetRating(android.support.v4.media.RatingCompat) Kciuk w górę/w dół.
ACTION_SET_CAPTIONING_ENABLED onSetCaptioningEnabled(boolean) Włącz/wyłącz napisy.

Pamiętaj:

  • Aby polecenia wyszukiwania działały, PlaybackState musi być aktualny w języku state, position, playback speed, and update time. Po zmianie stanu aplikacja musi wywołać metodę setPlaybackState().
  • Aplikacja do multimediów musi też aktualizować metadane sesji multimediów. Możesz na przykład zapytać „Co to za utwór?”. W przypadku zmiany odpowiednich pól (takich jak tytuł utworu, wykonawca i nazwa) aplikacja musi wywołać metodę setMetadata().
  • Wartość MediaSession.setRatingType() musi być ustawiona, aby wskazywać typ oceny, którą aplikacja obsługuje. Aplikacja musi stosować atrybut onSetRating(). Jeśli aplikacja nie obsługuje oceny, należy ustawić jej typ na RATING_NONE.

Obsługiwane komendy głosowe będą się prawdopodobnie różnić w zależności od typu treści.

Typ treści Wymagane działania
Muzyka

Wymagana obsługa: Odtwórz, Wstrzymaj, Zatrzymaj, Przejdź dalej i Przejdź wstecz

Zdecydowanie zalecamy pomoc dotyczącą: Przewiń do

Podcast

Wymagana obsługa: Odtwórz, Wstrzymaj, Zatrzymaj i Przewijaj

Zaleca się pomoc dotyczącą: przejdź do następnego i poprzedniego kroku

Audiobook Wymagana obsługa: Odtwórz, Wstrzymaj, Zatrzymaj i Przewijaj
Radio Wymagana obsługa: Odtwórz, Wstrzymaj i Zatrzymaj
Wiadomości Wymagana obsługa: Odtwórz, Wstrzymaj, Zatrzymaj, Przejdź dalej i Przejdź wstecz
Film

Wymagana obsługa: Odtwórz, Wstrzymaj, Zatrzymanie, Przewiń do, Przewiń do tyłu i Przewiń do przodu

Zdecydowanie zalecam pomoc dotyczącą: przejdź do następnego i poprzedniego kroku

Musisz wykonać tyle działań wymienionych powyżej, na ile pozwala Twoja oferta, ale reagować na inne działania z uznaniem. Jeśli np. tylko użytkownicy wersji premium mogą wrócić do poprzedniego produktu, możesz zgłosić błąd, gdy użytkownik poziomu bezpłatnego poprosi Asystenta, by wrócił do poprzedniego elementu. Więcej wskazówek znajdziesz w sekcji dotyczącej obsługi błędów.

Przykładowe zapytania głosowe do wypróbowania

W tabeli poniżej znajdziesz przykładowe zapytania, których możesz użyć podczas testowania implementacji:

Wywołanie zwrotne sesji MediaSession wyrażenie „OK Google”, którego należy użyć
onPlay()

„Graj”.

„Wznów”.

onPlayFromSearch()
onPlayFromUri()
Muzyka

„Włącz muzykę lub utwory w aplikacji (nazwa aplikacji)”. To jest puste zapytanie.

„Włącz (utwór | wykonawca | album | gatunek | playlista) w aplikacji (app name)”.

Radio „Włącz (częstotliwość | stacja) on (nazwa aplikacji)”.
Audiobook

„Przeczytaj audiobooka na (nazwa aplikacji)”.

„Przeczytaj (audiobook) na temat (nazwa aplikacji)”.

Podcasty „Włącz (podcast) na urządzeniu (nazwa aplikacji)”.
onPause() „Wstrzymaj”.
onStop() „Zatrzymaj”.
onSkipToNext() „Dalej (utwór | odcinek | utwór)”.
onSkipToPrevious() „Poprzednia (utwór | odcinek | utwór)”.
onSeekTo()

„Uruchom ponownie”.

„Przeskocz do przodu o ## s”.

„Cofnij się o ## min”.

Nie dotyczy (nieaktualne MediaMetadata) „Co jest odtwarzane?”

Błędy

Asystent obsługuje błędy występujące podczas sesji multimediów i zgłasza je użytkownikom. Upewnij się, że sesja multimediów prawidłowo aktualizuje stan przesyłania i kod błędu w elemencie PlaybackState, zgodnie z opisem w sekcji Praca z sesją multimediów. Asystent rozpoznaje wszystkie kody błędów zwracane przez getErrorCode().

Najczęściej nieprawidłowo obsłużone przypadki

Oto kilka przykładów przypadków błędów, z którymi musisz się zająć we właściwy sposób:

  • Użytkownik musi się zalogować.
    • Ustaw kod błędu PlaybackState na ERROR_CODE_AUTHENTICATION_EXPIRED.
    • Ustaw komunikat o błędzie PlaybackState.
    • Jeśli jest to wymagane do odtwarzania, ustaw stan PlaybackState na STATE_ERROR. W przeciwnym razie możesz pozostawić resztę PlaybackState w niezmienionej postaci.
  • Użytkownik prosi o niedostępne działanie
    • Ustaw odpowiednio kod błędu PlaybackState. Na przykład ustaw PlaybackState na ERROR_CODE_NOT_SUPPORTED, jeśli działanie nie jest obsługiwane, lub ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED, jeśli jest ono chronione przed zalogowaniem.
    • Ustaw komunikat o błędzie PlaybackState.
    • Zachowaj resztę danych (PlaybackState) w niezmienionej postaci.
  • Użytkownik prosi o treści niedostępne w aplikacji
    • Ustaw odpowiednio kod błędu PlaybackState. Przykład: ERROR_CODE_NOT_AVAILABLE_IN_REGION.
    • Ustaw komunikat o błędzie PlaybackState.
    • Ustaw stan PlaybackSate na STATE_ERROR, aby przerwać odtwarzanie. W przeciwnym razie możesz pozostawić resztę PlaybackState w niezmienionej postaci.
  • Użytkownik prosi o treści, w przypadku których dopasowanie ścisłe jest niedostępne. Przykładem może być użytkownik poziomu bezpłatnego, który prosi o treści dostępne tylko dla użytkowników z poziomu premium.
    • Nie zwracaj błędu, tylko znajdź coś podobnego do gry. Przed rozpoczęciem odtwarzania Asystent wypowie najtrafniejszą odpowiedź.

Odtwarzanie z intencją

Asystent może uruchomić aplikację audio lub wideo i rozpocząć odtwarzanie, wysyłając zamiar za pomocą precyzyjnego linku.

Intencja i jej precyzyjny link mogą pochodzić z różnych źródeł:

  • Gdy Asystent uruchamia aplikację mobilną, może użyć wyszukiwarki Google, aby pobrać oznaczone treści, które dostarczają działanie związane z oglądaniem za pomocą linku.
  • Gdy Asystent uruchamia aplikację TV, aplikacja powinna zawierać dostawcę wyszukiwarki TV, który udostępnia identyfikatory URI treści multimedialnych. Asystent wysyła do dostawcy treści zapytanie, które powinno zwrócić intencję zawierającą identyfikator URI precyzyjnego linku i opcjonalne działanie. Jeśli zapytanie zwraca działanie w intencji, Asystent wysyła je wraz z identyfikatorem URI z powrotem do aplikacji. Jeśli dostawca nie określił działania, Asystent doda do intencji parametr ACTION_VIEW.

Asystent dodaje element EXTRA_START_PLAYBACK o wartości true do intencji wysyłanej do aplikacji. Aplikacja powinna rozpocząć odtwarzanie po otrzymaniu intencji z intencją EXTRA_START_PLAYBACK.

Obsługa intencji podczas ich aktywności

Użytkownicy mogą poprosić Asystenta o włączenie czegoś, gdy aplikacja nadal odtwarza treści z poprzedniego żądania. Oznacza to, że aplikacja może otrzymywać nowe zamiary rozpoczęcia odtwarzania, gdy odtwarzanie jest już uruchomione i aktywne.

Aktywności, które obsługują intencje z precyzyjnymi linkami, powinny zastąpić tag onNewIntent(), aby obsługiwać nowe żądania.

Po rozpoczęciu odtwarzania Asystent może dodać dodatkowe flagi do intencji wysyłanej do aplikacji. W szczególności może dodać tag FLAG_ACTIVITY_CLEAR_TOP, FLAG_ACTIVITY_NEW_TASK lub oba te elementy. Chociaż Twój kod nie musi obsługiwać tych flag, system Android na nie odpowiada. Może to mieć wpływ na działanie aplikacji, gdy nadejdzie drugie żądanie odtwarzania z nowym identyfikatorem URI, gdy poprzedni identyfikator URI będzie nadal odtwarzany. W takim przypadku warto sprawdzić, jak aplikacja zareaguje. Możesz użyć narzędzia wiersza poleceń adb do symulowania sytuacji (stała 0x14000000 to bitowa wartość logiczna LUB obu flag):

adb shell 'am start -a android.intent.action.VIEW --ez android.intent.extra.START_PLAYBACK true -d "<first_uri>"' -f 0x14000000
adb shell 'am start -a android.intent.action.VIEW --ez android.intent.extra.START_PLAYBACK true -d "<second_uri>"' -f 0x14000000

Odtwarzanie z usługi

Jeśli Twoja aplikacja ma media browser service, który umożliwia łączenie się z Asystentem, Asystent może uruchomić aplikację, komunikując się z usługą media session. Usługa przeglądarki multimediów nigdy nie powinna uruchamiać aktywności. Asystent uruchomi Twoją aktywność na podstawie parametru PendingIntent określonego przez Ciebie za pomocą funkcji setSessionActivity().

Pamiętaj, by ustawić MediaSession.Token podczas inicjowania usługi przeglądarki multimediów. Pamiętaj, aby zawsze ustawić obsługiwane działania odtwarzania, w tym podczas inicjowania. Zanim Asystent wyśle pierwsze polecenie odtwarzania, Asystent oczekuje, że aplikacja do multimediów ustawi działania związane z odtwarzaniem.

Aby zacząć od usługi, Asystent implementuje interfejsy API klienta przeglądarki multimediów. Wykonuje wywołania TransportControls, które wywołują wywołania zwrotne działań PLAY w trakcie sesji multimediów w aplikacji.

Poniższy diagram przedstawia kolejność połączeń generowanych przez Asystenta i odpowiadające im wywołania zwrotne sesji multimediów. Wywołania zwrotne przygotowań są wysyłane tylko wtedy, gdy Twoja aplikacja je obsługuje. Wszystkie wywołania są asynchroniczne. Asystent nie czeka na odpowiedź Twojej aplikacji.

Rozpoczynam odtwarzanie od sesji multimediów

Gdy użytkownik wydaje polecenie głosowe, aby rozpocząć odtwarzanie, Asystent poda odpowiedź z krótkim komunikatem. Po zakończeniu ogłoszenia Asystent wykonuje działanie PLAY. Nie czeka na konkretny stan odtwarzania.

Jeśli aplikacja obsługuje działania ACTION_PREPARE_*, Asystent wywołuje działanie PREPARE przed rozpoczęciem ogłoszenia.

Nawiązywanie połączenia z usługą MediaBrowserService

Aby uruchomić aplikację za pomocą usługi, Asystent musi mieć możliwość połączenia się z usługą MediaBrowserService i pobrać MediaSession.Token. Żądania połączenia są obsługiwane w metodzie onGetRoot() usługi. Prośby można obsługiwać na 2 sposoby:

  • Akceptuj wszystkie prośby o połączenie
  • Akceptuj prośby o połączenie tylko z aplikacji Asystent

Akceptuj wszystkie prośby o połączenie

Musisz zwrócić wartość BrowserRoot, aby zezwolić Asystentowi na wysyłanie poleceń do sesji multimediów. Najprostszym sposobem jest zezwolenie wszystkim aplikacjom MediaBrowser na łączenie się z MediaBrowserService. Musisz zwrócić niepustą wartość BrowserRoot. Oto odpowiedni kod z Universal Music Player:

Kotlin

override fun onGetRoot(
        clientPackageName: String,
        clientUid: Int,
        rootHints: Bundle?
): BrowserRoot? {

    // To ensure you are not allowing any arbitrary app to browse your app's contents, you
    // need to check the origin:
    if (!packageValidator.isCallerAllowed(this, clientPackageName, clientUid)) {
        // If the request comes from an untrusted package, return an empty browser root.
        // If you return null, then the media browser will not be able to connect and
        // no further calls will be made to other media browsing methods.
        Log.i(TAG, "OnGetRoot: Browsing NOT ALLOWED for unknown caller. Returning empty "
                + "browser root so all apps can use MediaController. $clientPackageName")
        return MediaBrowserServiceCompat.BrowserRoot(MEDIA_ID_EMPTY_ROOT, null)
    }

    // Return browser roots for browsing...
}

Java

@Override
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid,
                             Bundle rootHints) {

    // To ensure you are not allowing any arbitrary app to browse your app's contents, you
    // need to check the origin:
    if (!packageValidator.isCallerAllowed(this, clientPackageName, clientUid)) {
        // If the request comes from an untrusted package, return an empty browser root.
        // If you return null, then the media browser will not be able to connect and
        // no further calls will be made to other media browsing methods.
        LogHelper.i(TAG, "OnGetRoot: Browsing NOT ALLOWED for unknown caller. "
                + "Returning empty browser root so all apps can use MediaController."
                + clientPackageName);
        return new MediaBrowserServiceCompat.BrowserRoot(MEDIA_ID_EMPTY_ROOT, null);
    }

    // Return browser roots for browsing...
}

Zaakceptuj pakiet aplikacji Asystent i podpis

Możesz wyraźnie zezwolić Asystentowi na połączenie się z Twoją przeglądarką multimediów, sprawdzając nazwę pakietu i podpis. Aplikacja otrzyma nazwę pakietu w metodzie onGetRoot usługi MediaBrowserService. Musisz zwrócić wartość BrowserRoot, aby zezwolić Asystentowi na wysyłanie poleceń do sesji multimediów. Przykład Universal Music Player zawiera listę znanych nazw pakietów i podpisów. Poniżej znajdziesz nazwy pakietów i podpisy, których używa Asystent Google.

<signature name="Google" package="com.google.android.googlequicksearchbox">
    <key release="false">19:75:b2:f1:71:77:bc:89:a5:df:f3:1f:9e:64:a6:ca:e2:81:a5:3d:c1:d1:d5:9b:1d:14:7f:e1:c8:2a:fa:00</key>
    <key release="true">f0:fd:6c:5b:41:0f:25:cb:25:c3:b5:33:46:c8:97:2f:ae:30:f8:ee:74:11:df:91:04:80:ad:6b:2d:60:db:83</key>
</signature>

<signature name="Google Assistant on Android Automotive OS" package="com.google.android.carassistant">
    <key release="false">17:E2:81:11:06:2F:97:A8:60:79:7A:83:70:5B:F8:2C:7C:C0:29:35:56:6D:46:22:BC:4E:CF:EE:1B:EB:F8:15</key>
    <key release="true">74:B6:FB:F7:10:E8:D9:0D:44:D3:40:12:58:89:B4:23:06:A6:2C:43:79:D0:E5:A6:62:20:E3:A6:8A:BF:90:E2</key>
</signature>