Google Asistan, Google Home ve telefonunuz gibi birçok cihazı sesli komutlarla kontrol etmenizi sağlar. Medya komutlarını ("Beyoncé'den bir şarkı çal") anlama özelliği vardır ve medya kontrollerini (ör. duraklatma, atlama, ileri sarma, beğeni) destekler.
Asistan, medya oturumu kullanarak Android medya uygulamalarıyla iletişim kurar. Uygulamanızı başlatmak ve oynatmayı başlatmak için amaçları veya hizmetleri kullanabilir. En iyi sonuçları elde etmek için uygulamanız bu sayfada açıklanan tüm özellikleri uygulamalıdır.
Medya oturumu kullanma
Asistan'ın oynatma başladıktan sonra aktarım kontrollerini kullanabilmesi için her ses ve video uygulamasında medya oturumu uygulanmalıdır.
Asistan yalnızca bu bölümde listelenen işlemleri kullanır. Ancak diğer uygulamalarla uyumluluğu sağlamak için tüm hazırlık ve oynatma API'lerinin uygulanması en iyi uygulamadır. Desteklemediğiniz işlemler için medya oturumu geri çağırmaları, ERROR_CODE_NOT_SUPPORTED kullanarak basitçe bir hata döndürebilir.
Uygulamanızın MediaSession nesnesinde aşağıdaki işaretleri ayarlayarak medya ve aktarım kontrollerini etkinleştirin:
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);
Uygulamanızın medya oturumu, desteklediği işlemleri bildirmeli ve ilgili medya oturumu geri çağırmalarını uygulamalıdır. Desteklenen işlemlerinizi setActions() içinde tanımlayın.
Universal Android Music Player örnek projesi, medya oturumunun nasıl ayarlanacağına dair iyi bir örnektir.
Oynatma işlemleri
Bir hizmetten oynatmayı başlatmak için medya oturumunda şu PLAY işlemler ve geri çağırmaları olmalıdır:
| İşlem | Geri Arama |
|---|---|
ACTION_PLAY |
onPlay() |
ACTION_PLAY_FROM_SEARCH |
onPlayFromSearch() |
ACTION_PLAY_FROM_URI (*) |
onPlayFromUri() |
Oturumunuzda şu PREPARE işlemleri ve geri çağırmaları da uygulanmalıdır:
| İşlem | Geri Arama |
|---|---|
ACTION_PREPARE |
onPrepare() |
ACTION_PREPARE_FROM_SEARCH |
onPrepareFromSearch() |
ACTION_PREPARE_FROM_URI (*) |
onPrepareFromUri() |
(*) Google Asistan'ın URI tabanlı işlemleri yalnızca Google'a URI sağlayan şirketler için çalışır. Medya içeriğinizi Google'a açıklama hakkında daha fazla bilgi edinmek için Medya İşlemleri başlıklı makaleyi inceleyin.
Hazırlık API'lerini uygulayarak sesli komut sonrasındaki oynatma gecikmesi azaltılabilir. Oynatma gecikmesini iyileştirmek isteyen medya uygulamaları, içeriği önbelleğe almaya başlamak ve medya oynatmayı hazırlamak için ek süreyi kullanabilir.
Arama sorgularını ayrıştırma
Bir kullanıcı "[Uygulama adınız] uygulamasında caz çal" veya "[Şarkı adı] şarkısını dinle" gibi belirli bir medya öğesini aradığında onPrepareFromSearch() veya onPlayFromSearch() geri çağırma yöntemi bir sorgu parametresi ve ekstralar paketi alır.
Uygulamanız, sesli arama sorgusunu ayrıştırmalı ve aşağıdaki adımları uygulayarak oynatmaya başlamalıdır:
- Sonuçları filtrelemek için sesli aramadan döndürülen ekstralar paketini ve arama sorgusu dizesini kullanın.
- Bu sonuçlara göre bir oynatma sırası oluşturun.
- Sonuçlar arasından en alakalı medya öğesini oynatır.
onPlayFromSearch() yöntemi, sesli arama işleminden daha ayrıntılı bilgiler içeren bir ek parametre alır. Bu ek bilgiler, uygulamanızdaki ses içeriklerini oynatmak için bulmanıza yardımcı olur.
Arama sonuçları bu verileri sağlayamıyorsa ham arama sorgusunu ayrıştıracak ve sorguya göre uygun parçaları çalacak bir mantık uygulayabilirsiniz.
Android Automotive OS ve Android Auto'da aşağıdaki ekstralar desteklenir:
Aşağıdaki kod snippet'inde, sesli arama sorgusunu ayrıştırmak ve oynatmaya başlamak için onPlayFromSearch() yönteminin MediaSession.Callback uygulamanızda nasıl geçersiz kılınacağı gösterilmektedir:
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 } }
Uygulamanızda sesli içerik oynatmak için sesli aramayı nasıl uygulayacağınıza dair daha ayrıntılı bir örnek için Universal Android Music Player örneğine bakın.
Boş sorguları işleme
onPrepare(), onPlay(), onPrepareFromSearch() veya onPlayFromSearch()
bir arama sorgusu olmadan çağrılırsa medya uygulamanız "mevcut"
medyayı oynatmalıdır. Mevcut bir medya yoksa uygulama, en son oynatma listesindeki bir şarkı veya rastgele bir sıra gibi bir içerik çalmayı denemelidir. Asistan, kullanıcı ek bilgi vermeden "[Uygulama adınız] uygulamasında müzik çal" dediğinde bu API'leri kullanır.
Bir kullanıcı "[Uygulama adınız] uygulamasında müzik çal" dediğinde Android Automotive OS veya Android Auto, uygulamanızın onPlayFromSearch() yöntemini çağırarak uygulamanızı başlatmaya ve ses çalmaya çalışır. Ancak kullanıcı medya öğesinin adını söylemediği için onPlayFromSearch()
yöntemi boş bir sorgu parametresi alır. Bu gibi durumlarda uygulamanız, en son oynatma listesindeki bir şarkı veya rastgele bir sıra gibi sesleri hemen oynatarak yanıt vermelidir.
Sesli işlemler için eski destek beyan etme
Çoğu durumda, yukarıda açıklanan oynatma işlemlerini işlemek uygulamanıza ihtiyaç duyduğu tüm oynatma işlevlerini sağlar. Ancak bazı sistemler, uygulamanızın arama için bir amaç filtresi içermesini gerektirir. Uygulamanızın manifest dosyalarında bu Intent filtresi için destek beyan etmeniz gerekir.
Bu kodu bir telefon uygulamasının manifest dosyasına ekleyin:
<activity>
<intent-filter>
<action android:name=
"android.media.action.MEDIA_PLAY_FROM_SEARCH" />
<category android:name=
"android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Aktarım kontrolleri
Uygulamanızın medya oturumu etkin olduktan sonra Asistan, oynatmayı kontrol etmek ve medya meta verilerini güncellemek için sesli komutlar verebilir. Bu özelliğin çalışması için kodunuzun aşağıdaki işlemleri etkinleştirmesi ve ilgili geri çağırmaları uygulaması gerekir:
| İşlem | Geri Arama | Açıklama |
|---|---|---|
ACTION_SKIP_TO_NEXT |
onSkipToNext() |
Sonraki video |
ACTION_SKIP_TO_PREVIOUS |
onSkipToPrevious() |
Önceki şarkı |
ACTION_PAUSE, ACTION_PLAY_PAUSE |
onPause() |
Duraklat |
ACTION_STOP |
onStop() |
Durdur |
ACTION_PLAY |
onPlay() |
Devam ettir |
ACTION_SEEK_TO |
onSeekTo() |
30 saniye geri sar |
ACTION_SET_RATING |
onSetRating(android.support.v4.media.RatingCompat) |
Beğenme/beğenmeme. |
ACTION_SET_CAPTIONING_ENABLED |
onSetCaptioningEnabled(boolean) |
Altyazıları açma/kapatma |
Not:
- Sarma komutlarının çalışması için
PlaybackStateuygulamasınınstate, position, playback speed, and update timeile güncel olması gerekir. Durum değiştiğinde uygulamasetPlaybackState()işlevini çağırmalıdır. - Medya uygulaması, medya oturumu meta verilerini de güncel tutmalıdır. Bu özellik, "Hangi şarkı çalıyor?" gibi soruları destekler. Uygulama, geçerli alanlar (ör. parça başlığı, sanatçı ve ad) değiştiğinde
setMetadata()işlevini çağırmalıdır. - Uygulamanın desteklediği derecelendirme türünü belirtmek için
MediaSession.setRatingType()ayarlanmalı ve uygulamaonSetRating()'yi uygulamalıdır. Uygulama derecelendirmeyi desteklemiyorsa derecelendirme türünüRATING_NONEolarak ayarlamalıdır.
Desteklediğiniz sesli işlemler, içerik türüne göre değişiklik gösterebilir.
| İçerik Türü | Gerekli İşlemler |
|---|---|
| Müzik |
Desteklenmesi gerekenler: Oynat, Duraklat, Durdur, Sonrakine Atla ve Öncekine Atla Desteklenmesi önemle tavsiye edilen: Seek To |
| Podcast |
Desteklenmesi gerekir: Oynat, Duraklat, Durdur ve Şuraya Git Aşağıdaki özellikler için destek önerilir: Sonrakine Git ve Öncekine Git |
| Sesli kitap | Desteklenmesi gerekir: Oynat, Duraklat, Durdur ve Şuraya Git |
| Radyo | Desteklenmesi gerekenler: Oynatma, Duraklatma ve Durdurma |
| Haberler | Desteklenmesi gerekenler: Oynat, Duraklat, Durdur, Sonrakine Atla ve Öncekine Atla |
| Video |
Desteklenmesi gerekenler: Oynat, Duraklat, Durdur, Şuraya Git, Geri Sar ve İleri Sar Aşağıdaki özellikler için destek kesinlikle önerilir: Sonrakine Atla ve Öncekine Atla |
Ürün tekliflerinizin izin verdiği ölçüde yukarıda listelenen işlemlerin çoğunu desteklemeniz, ancak diğer işlemlere de uygun şekilde yanıt vermeniz gerekir. Örneğin, yalnızca premium kullanıcılar önceki öğeye dönebilme özelliğine sahipse ücretsiz katman kullanıcısı Asistan'dan önceki öğeye dönmesini istediğinde hata verebilirsiniz. Daha fazla bilgi için hata işleme bölümüne bakın.
Deneyebileceğiniz örnek sesli sorgular
Aşağıdaki tabloda, uygulamanızı test ederken kullanmanız gereken bazı örnek sorgular özetlenmiştir:
| MediaSession geri çağırması | Kullanılacak "Ok Google" ifadesi | |
|---|---|---|
onPlay() |
"Oynat." "Devam ettir." |
|
onPlayFromSearch()
onPlayFromUri() |
Müzik |
"(Uygulama adı) uygulamasında müzik veya şarkı çal." Bu, boş bir sorgudur. "(Uygulama adında) (şarkı | sanatçı | albüm | tür | oynatma listesi) çal." |
| Radyo | "(Uygulama adında) (frekansı | istasyonu) çal." | |
| Sesli kitap |
"Sesli kitabımı (uygulama adı) uygulamasında oku." "(Uygulama adında) (sesli kitabı) oku." |
|
| Podcast'ler | "(Uygulama adı) uygulamasında (podcast) adlı podcast'i çal." | |
onPause() |
"Duraklat." | |
onStop() |
"Durdur." | |
onSkipToNext() |
"Sonraki (şarkı | bölüm | parça)" | |
onSkipToPrevious() |
"Önceki (şarkı | bölüm | parça)" | |
onSeekTo() |
"Yeniden başlat." "## saniye ileri atla." "## dakika geri git." |
|
Geçerli değil (MediaMetadata cihazınızı güncel tutun) |
"Çalan ne?" | |
Hatalar
Asistan, medya oturumundaki hataları oluştuğu anda işler ve kullanıcılara bildirir. Medya oturumunuzun, Medya oturumuyla çalışma başlıklı makalede açıklandığı gibi, PlaybackState içinde aktarım durumunu ve hata kodunu doğru şekilde güncellediğinden emin olun. Asistan, getErrorCode() tarafından döndürülen tüm hata kodlarını tanır.
Sıkça yanlış işlenen durumlar
Aşağıda, doğru şekilde ele aldığınızdan emin olmanız gereken bazı hata örnekleri verilmiştir:
- Kullanıcının oturum açması gerekiyor
PlaybackStatehata kodunuERROR_CODE_AUTHENTICATION_EXPIREDolarak ayarlayın.PlaybackStatehata mesajını ayarlayın.- Oynatma için gerekliyse
PlaybackStatedurumunuSTATE_ERRORolarak ayarlayın. Aksi takdirde,PlaybackState'nın geri kalanını olduğu gibi bırakın.
- Kullanıcı, kullanılamayan bir işlem istiyor
PlaybackStatehata kodunu uygun şekilde ayarlayın. Örneğin, işlem desteklenmiyorsaPlaybackStatedeğeriniERROR_CODE_NOT_SUPPORTED, işlem oturum açma ile korunuyorsaERROR_CODE_PREMIUM_ACCOUNT_REQUIREDolarak ayarlayın.PlaybackStatehata mesajını ayarlayın.PlaybackStategeri kalanını olduğu gibi koruyun.
- Kullanıcı, uygulamada bulunmayan içerik istiyor
PlaybackStatehata kodunu uygun şekilde ayarlayın. Örneğin,ERROR_CODE_NOT_AVAILABLE_IN_REGIONkullanın.PlaybackStatehata mesajını ayarlayın.- Oynatmayı duraklatmak için
PlaybackSatedurumunuSTATE_ERRORolarak ayarlayın. Aksi takdirde,PlaybackState'nin geri kalanını olduğu gibi koruyun.
- Kullanıcı, tam eşleşmenin olmadığı içerik istiyor. Örneğin, yalnızca premium katman kullanıcılarının erişebildiği içerikleri isteyen ücretsiz katman kullanıcısı.
- Hata döndürmemenizi ve bunun yerine oynanabilecek benzer bir içerik bulmaya öncelik vermenizi öneririz. Asistan, oynatma başlamadan önce en alakalı sesli yanıtı söyleyecektir.
Amaca yönelik oynatma
Asistan, derin bağlantı içeren bir amaç göndererek ses veya video uygulamasını başlatıp oynatmayı başlatabilir.
Amaç ve derin bağlantısı farklı kaynaklardan gelebilir:
- Asistan bir mobil uygulamayı başlatırken, bağlantı içeren bir izleme işlemi sağlayan işaretlenmiş içeriği almak için Google Arama'yı kullanabilir.
- Asistan bir TV uygulamasını başlatırken uygulamanız, medya içeriği için URI'leri kullanıma sunmak üzere bir TV Arama Sağlayıcısı içermelidir. Asistan, içerik sağlayıcıya bir sorgu gönderir. Bu sorgu, derin bağlantı için bir URI ve isteğe bağlı bir işlem içeren bir amaç döndürmelidir.
Sorgu, Intent'te bir işlem döndürürse Asistan bu işlemi ve URI'yi uygulamanıza geri gönderir. Sağlayıcı bir işlem belirtmediyse Asistan, Intent'e
ACTION_VIEWekler.
Asistan, uygulamanıza gönderdiği amaca EXTRA_START_PLAYBACK ile değer true ekler. Uygulamanız, EXTRA_START_PLAYBACK içeren bir amaç aldığında oynatmaya başlamalıdır.
Etkin durumdayken intent'leri işleme
Kullanıcılar, Asistan'dan önceki bir isteğin içeriği oynatılmaya devam ederken bir şey çalmasını isteyebilir. Bu, uygulamanızın oynatma etkinliği başlatılmış ve etkin durumdayken oynatmayı başlatmak için yeni amaçlar alabileceği anlamına gelir.
Derin bağlantılarla amaçları destekleyen etkinlikler, yeni istekleri işlemek için onNewIntent() geçersiz kılmalıdır.
Asistan, oynatmayı başlatırken uygulamanıza gönderdiği amaca ek işaretler ekleyebilir. Özellikle FLAG_ACTIVITY_CLEAR_TOP veya FLAG_ACTIVITY_NEW_TASK ya da her ikisini de ekleyebilir. Kodunuzun bu işaretleri işlemesi gerekmez ancak Android sistemi bunlara yanıt verir.
Bu durum, önceki URI oynatılmaya devam ederken yeni bir URI ile ikinci bir oynatma isteği geldiğinde uygulamanızın davranışını etkileyebilir. Uygulamanızın bu durumda nasıl yanıt verdiğini test etmeniz önerilir. Durumu simüle etmek için adb komut satırı aracını kullanabilirsiniz (sabit 0x14000000, iki işaretin Boole bit düzeyinde OR işlemidir):
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
Hizmetten oynatma
Uygulamanızda Asistan'dan bağlantılara izin veren bir
media browser service
varsa Asistan, hizmetin
media sessionile iletişim kurarak uygulamayı başlatabilir.
Medya tarayıcı hizmeti hiçbir zaman bir Etkinlik başlatmamalıdır.
Asistan, setSessionActivity() ile tanımladığınız PendingIntent temelinde etkinliğinizi başlatır.
Medya tarayıcı hizmetini başlatırken MediaSession.Token'ı ayarladığınızdan emin olun. Desteklenen oynatma işlemlerini, ilk kullanıma hazırlama işlemi de dahil olmak üzere her zaman ayarlamayı unutmayın. Asistan, ilk oynatma komutunu göndermeden önce medya uygulamanızın oynatma işlemlerini ayarlamasını bekler.
Asistan, bir hizmetten başlamak için medya tarayıcı istemci API'lerini uygular. Uygulamanızın medya oturumunda PLAY işlemi geri çağırmalarını tetikleyen TransportControls çağrıları gerçekleştirir.
Aşağıdaki şemada, Asistan tarafından oluşturulan çağrıların sırası ve ilgili medya oturumu geri çağırmaları gösterilmektedir. (Hazırlama geri çağırmaları yalnızca uygulamanız destekliyorsa gönderilir.) Tüm aramalar eşzamansızdır. Asistan, uygulamanızdan herhangi bir yanıt beklemez.

Kullanıcı, oynatma için sesli komut verdiğinde Asistan kısa bir duyuruyla yanıt verir. Duyuru tamamlanır tamamlanmaz Asistan, PLAY işlemini gerçekleştirir. Belirli bir oynatma durumunu beklemez.
Uygulamanız ACTION_PREPARE_* işlemlerini destekliyorsa Asistan, duyuruyu başlatmadan önce PREPARE işlemini çağırır.
MediaBrowserService'e bağlanma
Uygulamanızı başlatmak için bir hizmeti kullanmak üzere Asistan'ın uygulamanın MediaBrowserService'ine bağlanabilmesi ve MediaSession.Token'ını alabilmesi gerekir. Bağlantı istekleri, hizmetin onGetRoot() yönteminde işlenir. İstekleri işlemek için iki yöntem vardır:
- Tüm bağlantı isteklerini kabul etme
- Yalnızca Asistan uygulamasından gelen bağlantı isteklerini kabul etme
Tüm bağlantı isteklerini kabul etme
Asistan'ın medya oturumunuza komut göndermesine izin vermek için BrowserRoot döndürmeniz gerekir. En kolay yöntem, tüm MediaBrowser uygulamalarının MediaBrowserService'inize bağlanmasına izin vermektir. Null olmayan bir BrowserRoot döndürmelisiniz. Universal Music Player'daki geçerli kod aşağıda verilmiştir:
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... }
Asistan uygulama paketini ve imzasını kabul edin.
Paket adını ve imzasını kontrol ederek Asistan'ın medya tarayıcı hizmetinize bağlanmasına açıkça izin verebilirsiniz. Uygulamanız, MediaBrowserService'inizin onGetRoot yönteminde paket adını alır. Asistan'ın medya oturumunuza komut göndermesine izin vermek için BrowserRoot döndürmeniz gerekir. Evrensel Müzik Çalar örneği, bilinen paket adlarının ve imzaların bir listesini tutar. Google Asistan tarafından kullanılan paket adları ve imzalar aşağıda verilmiştir.
<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>