Google Asistan ve medya uygulamaları

Google Asistan, sesli komutlar kullanarak birçok cihazı kontrol etmenizi sağlar. Örneğin: Google Home, telefonunuz ve diğer cihazlar. Dahili olarak hem kendi medya komutlarını anlayabilir ("Beyoncé'den bir şey çal") ve medya denetimleri (ör. duraklatma, atla, ileri sarma, beğenme).

Asistan, bir medya kullanarak Android medya uygulamalarıyla iletişim kurar. oturum açın. Kullanabileceğim intents veya hizmetleri uygulamanızı başlatın ve oynatmaya başlayın. En iyi sonuçlar için uygulamanız bu sayfada açıklanan tüm özellikleri uygulayın.

Medya oturumu kullanma

Her ses ve video uygulaması bir medya oturumu Asistan'ın çalışabilmesi için aktarma kontrollerini içerir.

Asistan yalnızca bu bölümde listelenen işlemleri kullanırken, en iyi uygulama, tüm hazırlık ve oynatma API’lerini diğer uygulamalarla uyumluluk sağlayabilir. Desteklemediğiniz tüm işlemler için medya oturumu geri çağırmaları, ERROR_CODE_NOT_SUPPORTED.

Uygulamanızın içinde bu işaretleri ayarlayarak medya ve aktarım kontrollerini etkinleştirin MediaSession nesne:

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 oturumunda, desteklediği işlemler bildirilmeli ve medya oturumu geri çağırmaları olduğunu unutmayın. Desteklenen işlemlerinizi şurada beyan edin: setActions().

İlgili içeriği oluşturmak için kullanılan Evrensel Android Müzik Çalar örnek proje, medya oturumu hazırlamaya ilişkin iyi bir örnektir.

Oynatma işlemleri

Bir hizmetten oynatmayı başlatmak için medya oturumunda şu PLAY işlemleri ve bunların 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 bunların 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 URI tabanlı işlemleri yalnızca şirketlerde kullanılabilir Google'a sağlayan URI'lar oluşturabilirsiniz. Medya içeriğinizi Google'a açıklama hakkında daha fazla bilgi edinmek için Medya İşlemleri konusuna bakın.

Hazırlık API'leri uygulandığında, sesli komuttan sonraki oynatma gecikmesi azaltılabilir. Oynatmadaki gecikme süresini iyileştirmek isteyen medya uygulamaları, içeriği önbelleğe almaya ve medya oynatmayı hazırlamaya başlamak için ek süre gerekir.

Arama sorgularını ayrıştır

Kullanıcı, "Şu anda caz çal" gibi belirli bir medya öğesini aradığında [uygulama adınız]" veya "[şarkı adı] dinle", onPrepareFromSearch() veya onPlayFromSearch() geri çağırma yöntemi, bir sorgu parametresi ve ekstralar paketi alır.

Uygulamanız aşağıdaki adımları izleyerek sesli arama sorgusunu ayrıştırıp oynatmaya başlamalıdır: için şu adımları izleyin:

  1. Ekstra paketi ve sesli arama sonucunda döndürülen arama sorgusu dizesini kullan tıklayın.
  2. Bu sonuçlara dayalı bir oynatma sırası oluşturun.
  3. Sonuçlardaki en alakalı medya öğesini oynatın.
ziyaret edin.

onPlayFromSearch() yöntemi, sesten daha ayrıntılı bilgi içeren bir extras parametresi alır. arayın. Bu ekstra özellikler, uygulamanızda çalınacak ses içeriğini bulmanıza yardımcı olur. Arama sonuçları bu verileri sağlayamazsa mantığı kullanabilirsiniz. ayrıştırmak ve ham arama sorgusuna göre uygun parçaları emin olun.

Aşağıdaki ekstra özellikler Android Automotive OS ve Android Auto'da desteklenir:

Aşağıdaki kod snippet'i, onPlayFromSearch() MediaSession.Callback uygulama:

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

Ses çalmak için sesli aramanın nasıl uygulanacağıyla ilgili daha ayrıntılı bir örnek için hakkında daha fazla bilgi edinmek için Evrensel Android Müzik Oynatıcı örneklem.

Boş sorguları işleme

Eğer onPrepare(), onPlay(), onPrepareFromSearch() veya onPlayFromSearch() bir arama sorgusu olmadan çağrılırsa, medya uygulamanız "geçerli" medya Mevcut medya yoksa uygulama bir şeyler oynatmaya çalışmalıdır. veya rastgele bir sıradan bir şarkı olarak. Asistan, kullanıcı "[uygulamanızın adı] uygulamasında müzik çal" istediğinde bu API'ler ek bilgiler.

Kullanıcı "[Uygulamanızın adı] uygulamasında müzik çal" dediğinde, Android Automotive OS veya Android Auto, uygulamanızın onPlayFromSearch() numarasını arayarak uygulamanızı başlatmayı ve ses çalmayı dener yöntemidir. Ancak, kullanıcı medya öğesinin adını söylemediği için onPlayFromSearch() yöntemi boş bir sorgu parametresi alır. Bu durumlarda, uygulamanız en son dinlenen bir şarkı gibi bir ses çalarak hemen yanıt verir bir sıra olabilir.

Sesli işlemler için eski desteği beyan etme

Çoğu durumda, yukarıda açıklanan oynatma işlemlerini işlemek, uygulamanızın gereken oynatma işlevselliğini sağlar. Ancak bazı sistemlerde uygulamanızın arama için Intent filtresi içerir. Bu Intent için destek beyan etmeniz gerekir filtre uygulayabilirsiniz.

Bir telefon uygulamasının manifest dosyasına şu kodu ekleyin:

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

Ulaşım denetimleri

Uygulamanızın medya oturumu etkinleştirildikten sonra Asistan sesli komutlar verebilir oynatmayı kontrol etmek ve medya meta verilerini güncellemek için kullanılır. Bunun işe yaraması için kodu, aşağıdaki işlemleri etkinleştirmeli ve ilgili geri aramalar:

İş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ğenme.
ACTION_SET_CAPTIONING_ENABLED onSetCaptioningEnabled(boolean) Altyazıları açın/kapatın.

Not:

  • Arama komutlarının çalışması için PlaybackState, state, position, playback speed, and update time ile güncel olmalıdır. Durum değiştiğinde uygulamanın setPlaybackState() öğesini çağırması gerekir.
  • Medya uygulaması, medya oturumu meta verilerini de güncel tutmalıdır. Bu, "Hangi şarkı çalıyor?" gibi soruları destekler. Geçerli alanlar (parça başlığı, sanatçı ve ad gibi) değiştiğinde uygulama setMetadata() işlevini çağırmalıdır.
  • MediaSession.setRatingType(), uygulamanın desteklediği puan türünü belirtecek şekilde ayarlanmalıdır ve uygulamanın onSetRating() uygulamasını uygulaması gerekir. Uygulama derecelendirmeyi desteklemiyorsa derecelendirme türü RATING_NONE olarak ayarlanmalıdır.

Desteklediğiniz sesli işlemler büyük olasılıkla içerik türüne göre değişiklik gösterir.

İçerik Türü Gerekli İşlemler
Müzik

Desteklenmesi gerekenler: Oynat, Duraklat, Durdur, Sonrakine atla ve Öncekine Atla

Şunun için destek şiddetle önerilir:: Ara

Podcast

Desteklenmelidir: Oynat, Duraklat, Durdur ve Sar

Şunun için destek önerin:: Sonrakine Atla ve Öncekine Atla

Sesli kitap Desteklenmelidir: Oynat, Duraklat, Durdur ve Sar
Radyo Desteklenmelidir: Oynat, Duraklat ve Durdur
Haberler Desteklenmesi gerekenler: Oynat, Duraklat, Durdur, Sonrakine atla ve Öncekine Atla
Video

Desteklenmesi gerekenler: Oynat, Duraklat, Durdur, Sar, Geri Sar ve İleri Sar

Şunun için önemle tavsiye edilir:: Sonrakine Atla ve Öncekine Atla

Yukarıda listelenen işlemlerin çoğunu ürün teklifleriniz için desteklemeniz gerekir ancak diğer eylemlere de incelikle yanıt vermelidir. Örneğin yalnızca önceki öğeye geri dönebilme olanağı varsa, bu artışa Ücretsiz katman kullanıcısı, Asistan'dan önceki öğeye dönmesini isterse hata mesajı verir. Daha fazla bilgi için hata işleme bölümüne bakın.

Deneyebileceğiniz sesli sorgularla ilgili örnek

Aşağıdaki tabloda, içe aktarılırken kullanmanız gereken bazı örnek sorgular uygulamanızı test edin:

MediaSession Geri Çağırması Kullanılacak “Ok Google” ifadesi
onPlay()

"Oyna".

"Devam ettir."

onPlayFromSearch()
onPlayFromUri()
Müzik

"(uygulama adı) uygulamasında müzik veya şarkı çal." Bu boş bir sorgu.

"(Uygulama adı) üzerinde (şarkı | sanatçı | albüm | tür | oynatma listesi) çal."

Radyo "(uygulama adı) uygulamasında (frekt | istasyon) çal."
Sesli kitap

"(uygulama adı) uygulamasında sesli kitabımı oku."

"(uygulama adı) üzerinde (sesli kitap) oku."

Podcasts "(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 git."

"## dakika geri git."

Yok ( MediaMetadata güncellendi) "Çalan ne?"

Hatalar

Asistan, medya oturumundaki hataları oluştuğunda işler ve kullanıcılara öğreteceğim. Medya oturumunuzun aktarım durumunu güncellediğinden ve hatası kodunu PlaybackState doğru şekilde ekleyin, medya oturumuna gidin. Asistan tarafından döndürülen tüm hata kodlarını tanır. getErrorCode().

Yaygın olarak yanlış işlenen vakalar

Aşağıda, ele aldığınızdan emin olmanız gereken hata durumlarıyla ilgili bazı örnekler verilmiştir: şekilde değiştirebilirsiniz:

  • Kullanıcının oturum açması gerekiyor
    • PlaybackState hata kodunu ERROR_CODE_AUTHENTICATION_EXPIRED olarak ayarlayın.
    • PlaybackState hata mesajını ayarlayın.
    • Oynatma için gerekirse PlaybackState durumunu STATE_ERROR olarak ayarlayın. Aksi takdirde PlaybackState öğesinin kalan kısmını olduğu gibi saklar.
  • Kullanıcı, kullanılamayan bir işlem istiyor
    • PlaybackState hata kodunu uygun şekilde ayarlayın. Örneğin, PlaybackState - ERROR_CODE_NOT_SUPPORTED İşlem desteklenmiyorsa veya ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED oturum açma korumalı olduğundan emin olun.
    • PlaybackState hata mesajını ayarlayın.
    • PlaybackState öğesinin geri kalanını olduğu gibi saklayın.
  • Kullanıcı, uygulamada bulunmayan içerikleri istiyor
    • PlaybackState hata kodunu uygun şekilde ayarlayın. Örneğin, şunu kullanın: ERROR_CODE_NOT_AVAILABLE_IN_REGION.
    • PlaybackState hata mesajını ayarlayın.
    • Oynatmayı kesintiye uğratmak için PlaybackSate durumunu STATE_ERROR olarak ayarlayın. Aksi takdirde PlaybackState geri kalanını olduğu gibi saklar.
  • Kullanıcı, tam eşlemenin mevcut olmadığı içerikleri ister. Örneğin, ücretsiz katman kullanıcısı, yalnızca premium seviyedeki kullanıcılara sunulan içerikleri isteyebilir.
    • Hata döndürmenizi ve bunun yerine hataya öncelik vermenizi öneririz. benzer bir şey buluyor olabilirsiniz. Konuşmayı en çok Asistan yapar alakalı sesli yanıta ekleyebilirsiniz.

Bir amaçla oynatma

Asistan bir ses veya video uygulaması başlatabilir ve derin bağlantı ile test edin.

Amaç ve derin bağlantısı farklı kaynaklardan gelebilir:

  • Asistan şu durumda: bir mobil uygulama başlatırken, işaretlenmiş içeriği almak için Google aramayı kullanabilir bağlantı içeren bir izleme işlemi sağlar.
  • Asistan bir TV uygulamasını başlatırken uygulamanızda bir TV Arama Sağlayıcısı medya içeriğinin URI'larını açığa çıkarmak için kullanılır. Asistan, derin bağlantı ve derin bağlantı için URI içeren bir intent döndürmesi gereken içerik sağlayıcı isteğe bağlı bir işlemdir. Sorgu, intent'de bir işlem döndürürse Asistan bu işlemi ve URI'yı uygulamanıza geri gönderir. Sağlayıcı işlem yaparsanız Asistan, Intent'e ACTION_VIEW ekler.

Asistan, true değeriyle ekstra EXTRA_START_PLAYBACK ekler ile ilişkilendirmeniz gerekir. Uygulamanız şu işlemi gerçekleştirdiğinde çalmaya başlar: EXTRA_START_PLAYBACK ile bir intent alır.

Etkin durumdayken amaçları işleme

Kullanıcılar, uygulamanız oynatılırken Asistan'dan bir şey çalmasını isteyebilir göz atmayı unutmayın. Bu, uygulamanızın şu an için yeni intent'ler alabileceği anlamına gelir: oynatma etkinliği başlatılmış ve etkin durumdayken oynatmayı başlatır.

Derin bağlantılar içeren amaçları destekleyen etkinlikler, onNewIntent(). yeni istekleri ele alacağız.

Asistan, çalmaya başlarken başka değişiklikler işaretler ile ilişkilendirmeniz gerekir. Özellikle, FLAG_ACTIVITY_CLEAR_TOP veya FLAG_ACTIVITY_NEW_TASK veya her ikisi. Kodunuz Android sistemi bu işaretleri işlemesi gerekmiyorsa Android sistemi bunlara yanıt verir. Bu, yeni bir URI içeren ikinci bir oynatma isteği geldiğinde uygulamanızın davranışını etkileyebilir önceki URI çalmaya devam eder. Uygulamanızın bu durumda nasıl tepki verdiğini test etmek iyi bir fikirdir. adb komutunu kullanabilirsiniz satır aracını kullanarak durumu simüle edin (sabit 0x14000000 değeri, iki işaretin bit tabanlı VEYA boole değeridir):

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

Bir hizmetten oynatma

Uygulamanızda media browser service. Asistan'dan bağlantılara izin veren bir e-posta alırsınız, Asistan, hizmetin ana makinesiyle iletişim kurarak uygulamayı başlatabilir. media session. Medya tarayıcı hizmeti hiçbir zaman bir Etkinlik başlatmamalıdır. Asistan, tanımladığınız PendingIntent öğesine göre Etkinliğinizi başlatır setSessionActivity() ile ifade edebilirsiniz.

Oturumunuzu açarken MediaSession.Token medya tarayıcı hizmetini başlatın. Desteklenen oynatma işlemlerini ayarlamayı unutmayın her zaman çalışır. Buna başlatma sırasında da dahildir. Asistan, medya içeriklerinizi bekler Asistan ilk oynatmayı göndermeden önce oynatma işlemlerini ayarlamak için komutunu kullanın.

Asistan, bir hizmetten başlamak için medya tarayıcısı istemci API'lerini uygular. Cihazınızda PLAY işlemi geri çağırmalarını tetikleyen TransportControls çağrılarını gerçekleştirir. uygulamanın medya oturumundan emin olun.

Aşağıdaki şemada, Asistan ve medya oturumu geri çağırmaları olduğunu unutmayın. (Hazırlama geri çağırmaları yalnızca (uygulamanız destekliyorsa).) Tüm çağrılar eşzamansızdır. Asistan şunları yapmaz: uygulamanızdan yanıt gelmesini bekleyin.

Oynatmayı medya oturumuyla başlatma

Kullanıcı çalmak için bir sesli komut verdiğinde Asistan kısa bir duyuruyla yanıt verir. Duyuru tamamlanır tamamlanmaz Asistan bir OYNAT işlemi yayınlar. Belirli bir oynatma durumu için beklemez.

Uygulamanız ACTION_PREPARE_* işlemlerini destekliyorsa Asistan, duyuruyu başlatmadan önce PREPARE işlemini çağırır.

MediaTarayıcı Hizmeti'ne bağlanma

Bir hizmeti kullanarak uygulamanızı başlatmak için Asistan'ın uygulamanın MediaTarayıcı Hizmeti'ne bağlanabilmesi ve MediaSession.Token'ını alır. Bağlantı istekleri, hizmetin onGetRoot(). yöntemidir. İstekleri yönetmenin iki yolu vardır:

  • Tüm bağlantı isteklerini kabul et
  • Yalnızca Asistan uygulamasından gelen bağlantı isteklerini kabul et
ziyaret edin.

Tüm bağlantı isteklerini kabul et

Asistan'ın medya oturumunuza komut göndermesine izin vermek için BrowserRoot döndürmeniz gerekir. En kolay yol, tüm MediaTarayıcı uygulamalarının MediaTarayıcıHizmetinize bağlanmasına izin vermektir. Boş olmayan bir BrowserRoot döndürmeniz gerekir. İşte Universal Music Player'dan alınan geçerli kod:

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 uygulaması paketini ve imzayı kabul edin

Asistan'ın paket adını ve imzasını kontrol ederek medya tarayıcısı hizmetinize bağlanmasına açıkça izin verebilirsiniz. Uygulamanız, MediaTarayıcıHizmeti'nizin onGetRoot yönteminde paket adını alır. Asistan'ın medya oturumunuza komut göndermesine izin vermek için BrowserRoot döndürmeniz gerekir. İlgili içeriği oluşturmak için kullanılan Evrensel Müzik Çalar örneği, bilinen paket adlarının ve imzaların bir listesini içerir. Aşağıda, Google Asistan tarafından kullanılan paket adları ve imzalar 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>