Android Auto ve Android Automotive OS, medya uygulaması içeriğinizi kullanıcılara araçlarında sunmanıza yardımcı olur. Android Auto ve Android Automotive OS'in veya medya tarayıcısı olan başka bir uygulamanın içeriğinizi keşfedip görüntüleyebilmesi için arabalara yönelik bir medya uygulamasının bir medya tarayıcı hizmeti sağlaması gerekir.
Bu kılavuzda, telefonda ses çalan bir medya uygulamanızın olduğu ve medya uygulamanızın Android medya uygulaması mimarisine uygun olduğu varsayılmaktadır.
Bu kılavuzda, uygulamanızın Android Auto veya Android Automotive OS'te çalışması için gereken MediaBrowserService
ve MediaSession
bileşenleri açıklanmaktadır. Temel medya altyapısını tamamladıktan sonra medya uygulamanıza Android Auto için destek ve Android Automotive işletim sistemi için destek ekleyebilirsiniz.
Başlamadan önce
- Android media API dokümanlarını inceleyin.
- Tasarım konusunda rehberlik için Medya uygulamaları oluşturma konusunu inceleyin.
- Bu bölümde listelenen temel terimleri ve kavramları gözden geçirin.
Anahtar terimler ve kavramlar
- Medya tarayıcı hizmeti
- Medya uygulamanız tarafından uygulanan ve
MediaBrowserServiceCompat
API'siyle uyumlu bir Android hizmeti. Uygulamanız, içeriğini göstermek için bu hizmeti kullanıyor. - Medya tarayıcısı
- Medya uygulamaları tarafından medya tarayıcı hizmetlerini keşfetmek ve içeriklerini görüntülemek için kullanılan bir API. Android Auto ve Android Automotive OS, uygulamanızın medya tarayıcısı hizmetini bulmak için bir medya tarayıcısı kullanır.
- Medya öğesi
Medya tarayıcısı, içeriğini
MediaItem
nesnelerinden oluşan bir ağaçta düzenler. Bir medya öğesi, aşağıdaki işaretlerin birine veya her ikisine birden sahip olabilir:FLAG_PLAYABLE
: Öğenin içerik ağacında bir yaprak olduğunu belirtir. Bu öğe; albümdeki bir şarkı, sesli kitaptaki bir bölüm veya podcast'in bir bölümü gibi tek bir ses akışını temsil eder.FLAG_BROWSABLE
: Öğenin içerik ağacında bir düğüm olduğunu ve alt öğeleri olduğunu belirtir. Örneğin, öğe bir albümü temsil eder ve bunun alt öğeleri de albümdeki şarkılardır.
Hem göz atılabilen hem de oynatılabilen bir medya öğesi, oynatma listesi gibi çalışır. Öğenin kendisini seçerek tüm alt öğelerini oynayabilir veya alt öğelerine göz atabilirsiniz.
- Araç için optimize edilmiş
Android Automotive OS tasarım yönergelerine uygun bir Android Automotive OS uygulaması etkinliği. Bu işlemlerin arayüzü Android Automotive OS tarafından çizilmez. Bu nedenle, uygulamanızın tasarım yönergelerine uyduğundan emin olmanız gerekir. Buna tipik olarak, dokunma hedefleri ve yazı tipi boyutlarının büyük olması, gündüz ve gece modları için destek ve daha yüksek kontrast oranları dahildir.
Araç için optimize edilmiş kullanıcı arayüzlerinin görüntülenmesine yalnızca Araba Kullanıcı Deneyimi Kısıtlamaları (CUXR'ler) geçerli değilken izin verilir, çünkü bu arayüzler kullanıcının daha uzun süre dikkat etmesini veya etkileşimde bulunmasını gerektirebilir. CUXR'ler araç durduğunda veya park edildiğinde etkin olmaz, ancak araç hareket halindeyken her zaman etkindir.
Android Auto, medya tarayıcı hizmetinizdeki bilgileri kullanarak araç için optimize edilmiş kendi arayüzünü çizdiğinden Android Auto için etkinlik tasarlamanıza gerek yoktur.
Uygulamanızın manifest dosyalarını yapılandırma
Medya tarayıcı hizmetinizi oluşturabilmek için önce uygulamanızın manifest dosyalarını yapılandırmanız gerekir.
Medya tarayıcı hizmetinizi tanımlama
Hem Android Auto hem de Android Automotive OS, medya öğelerine göz atmak için medya tarayıcı hizmetiniz üzerinden uygulamanıza bağlanır. Android Auto ve Android Automotive OS'in hizmeti keşfetmesine ve uygulamanıza bağlanmasına izin vermek için manifest dosyanızda medya tarayıcısı hizmetinizi tanımlayın.
Aşağıdaki kod snippet'i, manifest dosyanızda medya tarayıcısı hizmetinizi nasıl tanımlayacağınızı gösterir. Bu kodu, Android Automotive OS modülünüzün manifest dosyasına ve telefon uygulamanızın manifest dosyasına ekleyin.
<application>
...
<service android:name=".MyMediaBrowserService"
android:exported="true">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
...
</application>
Uygulama simgelerini belirtin
Android Auto ve Android Automotive OS'in, uygulamanızı sistem kullanıcı arayüzünde temsil etmek için kullanabileceği uygulama simgelerini belirtmeniz gerekir. İki simge türü gereklidir:
- Başlatıcı simgesi
- İlişkilendirme simgesi
Başlatıcı simgesi
Başlatıcı simgesi, başlatıcıda ve simgeler tepsisi gibi sistem kullanıcı arayüzünde uygulamanızı temsil eder. Aşağıdaki manifest beyanını kullanarak araba medya uygulamanızı temsil etmek için mobil uygulamanızdaki simgeyi kullanmak istediğinizi belirtebilirsiniz:
<application
...
android:icon="@mipmap/ic_launcher"
...
/>
Mobil uygulamanızın simgesinden farklı bir simge kullanmak için manifest dosyasında medya tarayıcısı hizmetinizin <service>
öğesinde android:icon
özelliğini ayarlayın:
<application>
...
<service
...
android:icon="@mipmap/auto_launcher"
...
/>
</application>
İlişkilendirme simgesi
İlişkilendirme simgesi, medya içeriğinin öncelikli olduğu yerlerde (ör. medya kartları) kullanılır. Bildirimler için kullanılan küçük simgeyi yeniden kullanmayı düşünün. Bu simge tek renkli olmalıdır. Aşağıdaki manifest beyanını kullanarak uygulamanızı temsil etmek için kullanılacak bir simge belirtebilirsiniz:
<application>
...
<meta-data
android:name="androidx.car.app.TintableAttributionIcon"
android:resource="@drawable/ic_status_icon" />
...
</application>
Medya tarayıcı hizmetinizi oluşturun
MediaBrowserServiceCompat
sınıfını genişleterek bir medya tarayıcısı hizmeti oluşturursunuz. Böylece hem Android Auto hem de Android Automotive OS, hizmetinizi kullanarak şunları yapabilir:
- Kullanıcıya bir menü sunmak için uygulamanızın içerik hiyerarşisine göz atın.
- Ses çalmayı kontrol etmek için uygulamanızın
MediaSessionCompat
nesnesinin jetonunu alın.
Medya tarayıcısı hizmetinizi, diğer istemcilerin uygulamanızdaki medya içeriğine erişebilmesini sağlamak için de kullanabilirsiniz. Bu medya istemcileri, kullanıcının telefonundaki başka uygulamalar veya başka uzak istemciler olabilir.
Medya tarayıcısı hizmeti iş akışı
Bu bölümde, Android Automotive OS ve Android Auto'nun tipik bir kullanıcı iş akışı sırasında medya tarayıcısı hizmetinizle nasıl etkileşimde bulunduğu açıklanmaktadır.
- Kullanıcı, Android Automotive OS veya Android Auto'da uygulamanızı başlatır.
- Android Automotive OS veya Android Auto,
onCreate()
yöntemini kullanarak uygulamanızın medya tarayıcı hizmetiyle iletişim kurar.onCreate()
yöntemini uygularken birMediaSessionCompat
nesnesi ve bunun geri çağırma nesnesi oluşturup kaydetmeniz gerekir. - Android Automotive OS veya Android Auto, içerik hiyerarşinizdeki kök medya öğesini almak için hizmetinizin
onGetRoot()
yöntemini çağırır. Kök medya öğesi görüntülenmez; bunun yerine, uygulamanızdan daha fazla içerik almak için kullanılır. - Android Automotive OS veya Android Auto, kök medya öğesinin alt öğelerini almak için hizmetinizin
onLoadChildren()
yöntemini çağırır. Android Automotive OS ve Android Auto, bu medya öğelerini içerik öğelerinin en üst düzeyi olarak gösterir. Sistemin bu düzeyde ne beklediği hakkında daha fazla bilgi edinmek için bu sayfadaki Kök menüyü yapılandırma bölümüne bakın. - Kullanıcı göz atılabilir bir medya öğesi seçerse hizmetinizin
onLoadChildren()
yöntemi, seçilen menü öğesinin alt öğelerini almak için tekrar çağrılır. - Kullanıcı oynatılabilir bir medya öğesi seçerse Android Automotive OS veya Android Auto, bu işlemi gerçekleştirmek için uygun medya oturumu geri çağırma yöntemini kullanır.
- Uygulamanız tarafından destekleniyorsa kullanıcılar, içeriğinizde de arama yapabilir. Bu durumda Android Automotive OS veya Android Auto, hizmetinizin
onSearch()
yöntemini çağırır.
İçerik hiyerarşinizi oluşturma
Android Auto ve Android Automotive OS, hangi içeriğin kullanılabilir olduğunu öğrenmek için uygulamanızın medya tarayıcı hizmetini arar. Bunu desteklemek için medya tarayıcısı hizmetinizde iki yöntem uygulamanız gerekir: onGetRoot()
ve onLoadChildren()
onGetRoot uygulama
Hizmetinizin onGetRoot()
yöntemi, içerik hiyerarşinizin kök düğümü hakkında bilgi döndürür.
Android Auto ve Android Automotive OS, içeriğinizin geri kalanını onLoadChildren()
yöntemini kullanarak istemek için bu kök düğümü kullanır.
Aşağıdaki kod snippet'i, onGetRoot()
yönteminin basit bir uygulamasını göstermektedir:
Kotlin
override fun onGetRoot( clientPackageName: String, clientUid: Int, rootHints: Bundle? ): BrowserRoot? = // Verify that the specified package is allowed to access your // content. You'll need to write your own logic to do this. if (!isValid(clientPackageName, clientUid)) { // If the request comes from an untrusted package, return null. // No further calls will be made to other media browsing methods. null } else MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, null)
Java
@Override public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) { // Verify that the specified package is allowed to access your // content. You'll need to write your own logic to do this. if (!isValid(clientPackageName, clientUid)) { // If the request comes from an untrusted package, return null. // No further calls will be made to other media browsing methods. return null; } return new MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, null); }
Bu yöntemin daha ayrıntılı bir örneği için GitHub'daki Universal Android Music Player örnek uygulamasında yer alan onGetRoot()
yöntemine bakın.
onGetRoot() için paket doğrulaması ekleme
Hizmetinizin onGetRoot()
yöntemine çağrı yapıldığında çağrı paketi, tanımlayıcı bilgileri hizmetinize iletir. Hizmetiniz bu paketin içeriğinize erişip erişemeyeceğine karar vermek için bu bilgileri kullanabilir. Örneğin, clientPackageName
özelliğini izin verilenler listenizle karşılaştırarak ve paketin APK'sını imzalamak için kullanılan sertifikayı doğrulayarak uygulamanızın içeriğine erişimi onaylanmış paketlerin listesiyle kısıtlayabilirsiniz. Paket doğrulanamıyorsa içeriğinize erişimi reddetmek için null
kodunu döndürün.
Android Auto ve Android Automotive OS gibi sistem uygulamalarının içeriğinize erişmesini sağlamak için, bu sistem uygulamaları onGetRoot()
yöntemini çağırdığında hizmetinizin her zaman boş olmayan bir BrowserRoot
döndürmesi gerekir. Android Automotive OS sistem uygulamasının imzası, arabanın markasına ve modeline bağlı olarak değişebilir. Bu nedenle, tüm sistem uygulamalarındaki bağlantıların Android Automotive OS'i güçlü bir şekilde desteklemesine izin vermeniz gerekir.
Aşağıdaki kod snippet'i, hizmetinizin çağrı paketinin bir sistem uygulaması olduğunu nasıl doğrulayabileceğini gösterir:
fun isKnownCaller(
callingPackage: String,
callingUid: Int
): Boolean {
...
val isCallerKnown = when {
// If the system is making the call, allow it.
callingUid == Process.SYSTEM_UID -> true
// If the app was signed by the same certificate as the platform
// itself, also allow it.
callerSignature == platformSignature -> true
// ... more cases
}
return isCallerKnown
}
Bu kod snippet'i, GitHub'daki Universal Android Music Player örnek uygulamasındaki PackageValidator
sınıfından bir alıntıdır. Hizmetinizin onGetRoot()
yöntemi için paket doğrulamanın nasıl uygulanacağına ilişkin daha ayrıntılı bir örnek görmek üzere bu sınıfa bakın.
Google Asistan'ın sistem uygulamalarına izin vermenin yanı sıra MediaBrowserService
cihazınıza bağlanmasına da izin vermeniz gerekir. Google Asistan'ın, Android Auto ve Android Automotive OS dahil olmak üzere telefon için ayrı paket adları olduğunu unutmayın.
onLoadChildren() işlevini uygulama
Kök düğüm nesnenizi aldıktan sonra Android Auto ve Android Automotive OS, alt düğüm nesnesini almak için kök düğüm nesnesinde onLoadChildren()
yöntemini çağırarak üst düzey bir menü oluşturur. İstemci uygulamaları, alt düğüm nesnelerini kullanarak aynı yöntemi çağırarak alt menüler oluşturur.
İçerik hiyerarşinizdeki her düğüm bir MediaBrowserCompat.MediaItem
nesnesiyle temsil edilir. Bu medya öğelerinin her biri benzersiz bir kimlik dizesiyle tanımlanır. İstemci uygulamaları bu kimlik dizelerini opak jetonlar olarak işler. Bir istemci uygulaması bir alt menüye göz atmak veya bir medya öğesini oynatmak istediğinde jetonu aktarır. Jetonu uygun medya öğesiyle ilişkilendirmekten uygulamanız sorumludur.
Aşağıdaki kod snippet'i, onLoadChildren()
yönteminin basit bir uygulamasını göstermektedir:
Kotlin
override fun onLoadChildren( parentMediaId: String, result: Result<List<MediaBrowserCompat.MediaItem>> ) { // Assume for example that the music catalog is already loaded/cached. val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf() // Check whether this is the root menu: if (MY_MEDIA_ROOT_ID == parentMediaId) { // Build the MediaItem objects for the top level // and put them in the mediaItems list. } else { // Examine the passed parentMediaId to see which submenu we're at // and put the children of that menu in the mediaItems list. } result.sendResult(mediaItems) }
Java
@Override public void onLoadChildren(final String parentMediaId, final Result<List<MediaBrowserCompat.MediaItem>> result) { // Assume for example that the music catalog is already loaded/cached. List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); // Check whether this is the root menu: if (MY_MEDIA_ROOT_ID.equals(parentMediaId)) { // Build the MediaItem objects for the top level // and put them in the mediaItems list. } else { // Examine the passed parentMediaId to see which submenu we're at // and put the children of that menu in the mediaItems list. } result.sendResult(mediaItems); }
Bu yöntemin eksiksiz bir örneği için GitHub'daki Universal Android Music Player örnek uygulamasında yer alan onLoadChildren()
yöntemine bakın.
Kök menüyü yapılandırma
Android Auto ve Android Automotive OS'te, kök menüsünün yapısıyla ilgili belirli kısıtlamalar vardır. Bunlar MediaBrowserService
öğesine kök ipuçları aracılığıyla iletilir. Bu ipuçları, onGetRoot()
'a geçirilen Bundle
bağımsız değişkeni aracılığıyla okunabilir.
Bu ipuçlarının uygulanması, sistemin kök içeriği en uygun şekilde gezinme sekmeleri şeklinde görüntülemesini sağlar. Bu ipuçlarını uygulamazsanız bazı kök içerikler kaldırılabilir veya sistem tarafından keşfedilebilirliği daha düşük olabilir. İki ipucu gönderilir:
- Kök alt öğe sayısıyla ilgili sınır: Çoğu durumda bu sayının dört olmasını bekleyebilirsiniz. Bu da dörtten fazla sekmenin gösterilemeyeceği anlamına gelir.
- Kök alt öğelerde desteklenen işaretler: Bu değerin
MediaItem#FLAG_BROWSABLE
olmasını bekleyebilirsiniz. Bu, yalnızca göz atılabilir öğelerin (oynanabilir öğelerin değil) sekme olarak gösterilebileceği anlamına gelir.
İlgili kök ipuçlarını okumak için aşağıdaki kodu kullanın:
Kotlin
import androidx.media.utils.MediaConstants // Later, in your MediaBrowserServiceCompat. override fun onGetRoot( clientPackageName: String, clientUid: Int, rootHints: Bundle ): BrowserRoot { val maximumRootChildLimit = rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT, /* defaultValue= */ 4) val supportedRootChildFlags = rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS, /* defaultValue= */ MediaItem.FLAG_BROWSABLE) // Rest of method... }
Java
import androidx.media.utils.MediaConstants; // Later, in your MediaBrowserServiceCompat. @Override public BrowserRoot onGetRoot( String clientPackageName, int clientUid, Bundle rootHints) { int maximumRootChildLimit = rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT, /* defaultValue= */ 4); int supportedRootChildFlags = rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS, /* defaultValue= */ MediaItem.FLAG_BROWSABLE); // Rest of method... }
Özellikle de hiyerarşiniz Android Auto ve Android Automotive OS dışındaki MediaBrowser
entegrasyonları arasında farklılık gösteriyorsa içerik hiyerarşinizin mantığını bu ipuçlarının değerlerine göre kollara ayırabilirsiniz.
Örneğin, normalde root oynatılabilir bir öğe gösteriyorsanız bunu, desteklenen flag'ler ipucunun değeri nedeniyle kök göz atılabilir bir öğenin altına yerleştirmek isteyebilirsiniz.
Sekmelerin en iyi şekilde oluşturulmasını sağlamak için kök ipuçlarının yanı sıra uygulanması gereken birkaç ek yönerge vardır:
- Her sekme öğesi için tek renkli, tercihen beyaz, simgeler sağlayın.
- Her sekme öğesi için kısa ama anlamlı etiketler sağlayın. Etiketleri kısa tutmak, dizelerin kısaltılma olasılığını azaltır.
Medya posterini göster
Medya öğelerinin posteri, ContentResolver.SCHEME_CONTENT
veya ContentResolver.SCHEME_ANDROID_RESOURCE
kullanılarak yerel URI olarak iletilmelidir.
Bu yerel URI, uygulamanın kaynaklarında bit eşlem veya çekilebilir bir vektöre çözümlenmelidir. İçerik hiyerarşisindeki öğeleri temsil eden MediaDescriptionCompat
nesneleri için URI'yi setIconUri()
üzerinden geçirin.
Şu anda oynatılan öğeyi temsil eden MediaMetadataCompat
nesneleri için URI'yı aşağıdaki anahtarlardan birini kullanarak putString()
üzerinden geçirin:
MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI
MediaMetadataCompat.METADATA_KEY_ART_URI
MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI
Aşağıdaki adımlarda, bir web URI'sinden resmin nasıl indirileceği ve yerel URI aracılığıyla nasıl gösterileceği açıklanmaktadır. Daha eksiksiz bir örnek için openFile()
uygulamasının uygulamasına ve Universal Android Music Player örnek uygulamasındaki ilgili yöntemlere bakın.
Web URI'sine karşılık gelen bir
content://
URI'sı oluşturun. Medya tarayıcı hizmeti ve medya oturumu, bu içerik URI'sını Android Auto ve Android Automotive OS'e iletir.Kotlin
fun Uri.asAlbumArtContentURI(): Uri { return Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(CONTENT_PROVIDER_AUTHORITY) .appendPath(this.getPath()) // Make sure you trust the URI .build() }
Java
public static Uri asAlbumArtContentURI(Uri webUri) { return new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(CONTENT_PROVIDER_AUTHORITY) .appendPath(webUri.getPath()) // Make sure you trust the URI! .build(); }
ContentProvider.openFile()
uygulamanızda, karşılık gelen URI için bir dosyanın mevcut olup olmadığını kontrol edin. Aksi takdirde resim dosyasını indirip önbelleğe alın. Aşağıdaki kod snippet'i Glide'ı kullanmaktadır.Kotlin
override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? { val context = this.context ?: return null val file = File(context.cacheDir, uri.path) if (!file.exists()) { val remoteUri = Uri.Builder() .scheme("https") .authority("my-image-site") .appendPath(uri.path) .build() val cacheFile = Glide.with(context) .asFile() .load(remoteUri) .submit() .get(DOWNLOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS) cacheFile.renameTo(file) file = cacheFile } return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY) }
Java
@Nullable @Override public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException { Context context = this.getContext(); File file = new File(context.getCacheDir(), uri.getPath()); if (!file.exists()) { Uri remoteUri = new Uri.Builder() .scheme("https") .authority("my-image-site") .appendPath(uri.getPath()) .build(); File cacheFile = Glide.with(context) .asFile() .load(remoteUri) .submit() .get(DOWNLOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS); cacheFile.renameTo(file); file = cacheFile; } return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); }
İçerik sağlayıcılar hakkında daha fazla bilgi için İçerik sağlayıcı oluşturma bölümüne bakın.
İçerik stillerini uygula
Göz atılabilir veya oynatılabilir öğeleri kullanarak içerik hiyerarşinizi oluşturduktan sonra bu öğelerin arabada nasıl görüneceğini belirleyen içerik stilleri uygulayabilirsiniz.
Aşağıdaki içerik stillerini kullanabilirsiniz:
- Liste öğeleri
-
Bu içerik stili, başlıklara ve meta verilere resimlerden daha fazla öncelik verir.
- Izgara öğeleri
-
Bu içerik stili, başlıklara ve meta verilere göre resimlere öncelik verir.
Varsayılan içerik stillerini ayarlama
Medya öğelerinizin görüntülenme şekli için genel varsayılanları, hizmetinizin onGetRoot()
yönteminin BrowserRoot
ekstra paketine belirli sabit değerleri ekleyerek ayarlayabilirsiniz. Android Auto ve Android Automotive OS, bu paketi okur ve uygun stili belirlemek için bu sabit değerleri arar.
Pakette anahtar olarak aşağıdaki ekstralar kullanılabilir:
DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE
: Göz atma ağacındaki tüm göz atılabilir öğeler için bir sunu ipucu belirtir.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE
: Göz atma ağacındaki tüm oynanabilir öğeler için bir sunum ipucu belirtir.
Anahtarlar, bu öğelerin sunumunu etkilemek için aşağıdaki tam sayı sabit değerleriyle eşlenebilir:
DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM
: İlgili öğeler liste öğeleri olarak sunulur.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM
: İlgili öğeler ızgara öğeleri olarak sunulur.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM
: İlgili öğeler "kategori" liste öğeleri olarak sunulur. Bunlar sıradan liste öğeleriyle aynıdır. Tek fark, simgeler küçük olduklarında daha iyi görünmesi nedeniyle öğelerin simgelerinin etrafına kenar boşluklarının uygulanmasıdır. Simgeler, renklenebilir vektör çekilebilir öğeleri olmalıdır. Bu ipucunun yalnızca göz atılabilir öğeler için sağlanması beklenir.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_GRID_ITEM
: İlgili öğeler "kategori" ızgara öğeleri olarak sunulur. Bunlar normal ızgara öğeleriyle aynıdır ancak simgeler küçük olduklarında daha iyi göründüğü için öğelerin simgelerinin etrafına kenar boşlukları uygulanır. Simgeler, renklenebilir vektör çekilebilir öğeleri olmalıdır. Bu ipucunun yalnızca göz atılabilir öğeler için sağlanması beklenir.
Aşağıdaki kod snippet'i, göz atılabilir öğeler için varsayılan içerik stilinin ızgaralara, oynatılabilir öğeler için ise listelere nasıl ayarlanacağını gösterir:
Kotlin
import androidx.media.utils.MediaConstants @Nullable override fun onGetRoot( @NonNull clientPackageName: String, clientUid: Int, @Nullable rootHints: Bundle ): BrowserRoot { val extras = Bundle() extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM) return BrowserRoot(ROOT_ID, extras) }
Java
import androidx.media.utils.MediaConstants; @Nullable @Override public BrowserRoot onGetRoot( @NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) { Bundle extras = new Bundle(); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM); return new BrowserRoot(ROOT_ID, extras); }
Öğe başına içerik stillerini ayarla
Content Style API, hem göz atılabilir medya öğelerinin alt öğeleri için hem de medya öğelerinin varsayılan içerik stilini geçersiz kılmanıza olanak tanır.
Göz atılabilir bir medya öğesinin alt öğeleri için varsayılanı geçersiz kılmak üzere medya öğesinin MediaDescription
bölümünde bir ekstra paket oluşturun ve daha önce bahsedilen ipuçlarını ekleyin. DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE
o öğenin oynanabilir alt öğeleri, DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE
ise söz konusu öğenin
göz atılabilir alt öğeleri için geçerlidir.
Varsayılan değeri belirli bir medya öğesinin alt öğeleri yerine kendisi için geçersiz kılmak istiyorsanız medya öğesinin MediaDescription
bölümünde ekstralar paketi oluşturun ve DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM
anahtarıyla bir ipucu ekleyin.
İlgili öğenin sunumunu belirtmek için daha önce açıklanan değerleri kullanın.
Aşağıdaki kod snippet'i, hem kendisi hem de alt öğeleri için varsayılan içerik stilini geçersiz kılan bir göz atılabilir MediaItem
öğesinin nasıl oluşturulacağını göstermektedir. Kendisini bir kategori listesi öğesi, gözatılabilir alt öğelerini liste öğeleri ve oynanabilir alt öğelerini ızgara öğeleri olarak biçimlendirir:
Kotlin
import androidx.media.utils.MediaConstants private fun createBrowsableMediaItem( mediaId: String, folderName: String, iconUri: Uri ): MediaBrowser.MediaItem { val mediaDescriptionBuilder = MediaDescription.Builder() mediaDescriptionBuilder.setMediaId(mediaId) mediaDescriptionBuilder.setTitle(folderName) mediaDescriptionBuilder.setIconUri(iconUri) val extras = Bundle() extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM) mediaDescriptionBuilder.setExtras(extras) return MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE) }
Java
import androidx.media.utils.MediaConstants; private MediaBrowser.MediaItem createBrowsableMediaItem( String mediaId, String folderName, Uri iconUri) { MediaDescription.Builder mediaDescriptionBuilder = new MediaDescription.Builder(); mediaDescriptionBuilder.setMediaId(mediaId); mediaDescriptionBuilder.setTitle(folderName); mediaDescriptionBuilder.setIconUri(iconUri); Bundle extras = new Bundle(); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM); mediaDescriptionBuilder.setExtras(extras); return new MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE); }
Başlık ipuçlarını kullanarak öğeleri gruplandırma
İlgili medya öğelerini birlikte gruplandırmak için öğe başına bir ipucu kullanırsınız. Bir gruptaki her medya öğesinin, MediaDescription
özelliğinde DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE
anahtarıyla bir eşleme ve aynı dize değeri içeren bir ekstra paket tanımlaması gerekir. Grubun başlığı olarak kullanılan bu dizeyi yerelleştirin.
Aşağıdaki kod snippet'i, "Songs"
alt grup başlığıyla bir MediaItem
öğesini nasıl oluşturacağınızı göstermektedir:
Kotlin
import androidx.media.utils.MediaConstants private fun createMediaItem( mediaId: String, folderName: String, iconUri: Uri ): MediaBrowser.MediaItem { val mediaDescriptionBuilder = MediaDescription.Builder() mediaDescriptionBuilder.setMediaId(mediaId) mediaDescriptionBuilder.setTitle(folderName) mediaDescriptionBuilder.setIconUri(iconUri) val extras = Bundle() extras.putString( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs") mediaDescriptionBuilder.setExtras(extras) return MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), /* playable or browsable flag*/) }
Java
import androidx.media.utils.MediaConstants; private MediaBrowser.MediaItem createMediaItem(String mediaId, String folderName, Uri iconUri) { MediaDescription.Builder mediaDescriptionBuilder = new MediaDescription.Builder(); mediaDescriptionBuilder.setMediaId(mediaId); mediaDescriptionBuilder.setTitle(folderName); mediaDescriptionBuilder.setIconUri(iconUri); Bundle extras = new Bundle(); extras.putString( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs"); mediaDescriptionBuilder.setExtras(extras); return new MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), /* playable or browsable flag*/); }
Uygulamanız, bitişik blok olarak gruplandırmak istediğiniz tüm medya öğelerini geçirmelidir. Örneğin, "Şarkılar" ve "Albümler" adlı iki medya öğesi grubunu bu sırayla görüntülemek istediğinizi ve uygulamanızın beş medya öğesini aşağıdaki sırayla gönderdiğini varsayalım:
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
içeren medya öğesi Aextras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
içeren medya öğesi Bextras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
içeren medya öğesi Cextras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
içeren medya öğesi Dextras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
içeren medya öğesi E
"Şarkılar" grubu ve "Albümler" grubuna ait medya öğeleri bitişik bloklar halinde bir arada tutulmadığından, Android Auto ve Android Automotive OS bunu aşağıdaki dört grup olarak yorumlar:
- Medya öğesini içeren "Şarkılar" adlı Grup 1
- Medya öğesi B'yi içeren "Albümler" adlı Grup 2
- C ve D medya öğelerini içeren "Şarkılar" adlı 3. Grup
- Medya öğesi E içeren "Albümler" adlı Grup 4
Bu öğeleri iki grup halinde görüntülemek için uygulamanızın medya öğelerini aşağıdaki sırayla iletmesi gerekir:
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
içeren medya öğesi Aextras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
içeren medya öğesi Cextras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
içeren medya öğesi Dextras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
içeren medya öğesi Bextras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
içeren medya öğesi E
Ek meta veri göstergelerini göster
Medya tarayıcı ağacındaki ve oynatma sırasında içerikle ilgili bir bakışta bilgi sağlamak için ek meta veri göstergeleri ekleyebilirsiniz. Göz atma ağacında, Android Auto ve Android Automotive OS bir öğeyle ilişkilendirilen ekstraları okur ve hangi göstergelerin gösterileceğini belirlemek için belirli sabit değerleri arar. Medya oynatma sırasında, Android Auto ve Android Automotive OS medya oturumu için meta verileri okur ve görüntülenecek göstergeleri belirlemek için belirli sabit değerleri arar.
Aşağıdaki sabit değerler, hem MediaItem
açıklama ekstralarında hem de MediaMetadata
ekstrada kullanılabilir:
EXTRA_DOWNLOAD_STATUS
: Bir öğenin indirme durumunu belirtir. Bu sabiti anahtar olarak kullanın. Aşağıdaki uzun sabitler olası değerlerdir:STATUS_DOWNLOADED
: Öğe tamamen indirildi.STATUS_DOWNLOADING
: Öğe indiriliyor.STATUS_NOT_DOWNLOADED
: Öğe indirilmemiştir.
METADATA_KEY_IS_EXPLICIT
: Öğenin uygunsuz içerik içerip içermediğini belirtir. Bir öğenin uygunsuz olduğunu belirtmek için bu sabit değeri anahtar, değer olarak uzunMETADATA_VALUE_ATTRIBUTE_PRESENT
kullanın.
Aşağıdaki sabit değerler yalnızca MediaItem
açıklama ekstrasında kullanılabilir:
DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS
: Podcast bölümleri veya sesli kitaplar gibi uzun içeriklerin tamamlanma durumunu gösterir. Bu sabit değeri anahtar olarak kullanın. Aşağıdaki tam sayı sabitleri olası değerlerdir:DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED
: Öğe hiç oynanmadı.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED
: Öğe kısmen oynatılmıştır ve mevcut konum ortada bir yerdedir.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED
: Öğe tamamlandı.
DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
: Uzun içerikteki tamamlanma ilerleme miktarını 0,0 ile 1,0 arasında (ikisi de dahil) çift değer olarak gösterir. Bu ekstra,PARTIALLY_PLAYING
durumu hakkında daha fazla bilgi sağlar. Böylece Android Auto veya Android Automotive OS, ilerleme çubuğu gibi daha anlamlı bir ilerleme göstergesi görüntüler. Bunu ekstra kullanıyorsanız, ilk gösterimden sonra bu göstergeyi nasıl güncel tutacağınızı öğrenmek için bu kılavuzdaki içerik oynatılırken göz atma görünümündeki ilerleme çubuğunu güncelleme bölümüne bakın.
Kullanıcı medyaya göz atma ağacına göz atarken görünen göstergeleri görüntülemek için bu sabit değerlerden birini veya daha fazlasını içeren bir ekstra paket oluşturun ve bu paketi MediaDescription.Builder.setExtras()
yöntemine geçirin.
Aşağıdaki kod snippet'i% 70 tamamlanmış uygunsuz bir medya öğesi için göstergelerin nasıl gösterileceğini göstermektedir:
Kotlin
import androidx.media.utils.MediaConstants val extras = Bundle() extras.putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS, MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED) extras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.7) val description = MediaDescriptionCompat.Builder() .setMediaId(/*...*/) .setTitle(resources.getString(/*...*/)) .setExtras(extras) .build() return MediaBrowserCompat.MediaItem(description, /* flags */)
Java
import androidx.media.utils.MediaConstants; Bundle extras = new Bundle(); extras.putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS, MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED); extras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.7); MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setMediaId(/*...*/) .setTitle(resources.getString(/*...*/)) .setExtras(extras) .build(); return new MediaBrowserCompat.MediaItem(description, /* flags */);
Oynatılmakta olan bir medya öğesine ilişkin göstergeleri görüntülemek amacıyla mediaSession
uygulamanızın MediaMetadataCompat
bölümünde METADATA_KEY_IS_EXPLICIT
veya EXTRA_DOWNLOAD_STATUS
için Long
değerleri bildirebilirsiniz. Oynatma görünümünde DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS
veya DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
göstergelerini görüntüleyemezsiniz.
Aşağıdaki kod snippet'i, oynatma görünümündeki mevcut şarkının uygunsuz ve indirilmiş olduğunun nasıl belirtileceğini gösterir:
Kotlin
import androidx.media.utils.MediaConstants mediaSession.setMetadata( MediaMetadataCompat.Builder() .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, "Song Name") .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "Artist name") .putString( MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, albumArtUri.toString()) .putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) .putLong( MediaDescriptionCompat.EXTRA_DOWNLOAD_STATUS, MediaDescriptionCompat.STATUS_DOWNLOADED) .build())
Java
import androidx.media.utils.MediaConstants; mediaSession.setMetadata( new MediaMetadataCompat.Builder() .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, "Song Name") .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "Artist name") .putString( MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, albumArtUri.toString()) .putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) .putLong( MediaDescriptionCompat.EXTRA_DOWNLOAD_STATUS, MediaDescriptionCompat.STATUS_DOWNLOADED) .build());
İçerik oynatılırken göz atma görünümündeki ilerleme çubuğunu güncelle
Daha önce belirtildiği gibi, göz atma görünümünde kısmen oynatılan içerikler için ilerleme çubuğunu göstermek üzere DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
ekstrasını kullanabilirsiniz. Ancak kullanıcı Android Auto veya Android Automotive OS'ten kısmen oynatılan içeriği oynatmaya devam ederse bu gösterge zaman geçtikçe yanlış hale gelir.
Android Auto ve Android Automotive OS için ilerleme çubuğunu güncel tutmak amacıyla MediaMetadataCompat
ve PlaybackStateCompat
içinde ek bilgiler sağlayarak devam eden içeriği göz atma görünümündeki medya öğelerine bağlayabilirsiniz. Medya öğesinin otomatik olarak güncellenen bir ilerleme çubuğuna sahip olması için aşağıdaki gereksinimlerin karşılanması gerekir:
- Oluşturulduğunda
MediaItem
,DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
değerini 0,0 ile 1,0 arasında (bu değerler dahil) ekstra özellikleriyle göndermelidir. MediaMetadataCompat
,METADATA_KEY_MEDIA_ID
öğesiniMediaItem
öğesine iletilen medya kimliğine eşit bir dize değeriyle göndermelidir.PlaybackStateCompat
,MediaItem
öğesine iletilen medya kimliğine eşit bir dize değeriyle eşlenenPLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID
anahtarıyla birlikte bir ekstra öğe içermelidir.
Aşağıdaki kod snippet'i, geçerli olarak oynatılan öğenin göz atma görünümünde bir öğeye bağlı olduğunun nasıl belirtileceğini gösterir:
Kotlin
import androidx.media.utils.MediaConstants // When the MediaItem is constructed to show in the browse view. // Suppose the item was 25% complete when the user launched the browse view. val mediaItemExtras = Bundle() mediaItemExtras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.25) val description = MediaDescriptionCompat.Builder() .setMediaId("my-media-id") .setExtras(mediaItemExtras) // ...and any other setters. .build() return MediaBrowserCompat.MediaItem(description, /* flags */) // Elsewhere, when the user has selected MediaItem for playback. mediaSession.setMetadata( MediaMetadataCompat.Builder() .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, "my-media-id") // ...and any other setters. .build()) val playbackStateExtras = Bundle() playbackStateExtras.putString( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID, "my-media-id") mediaSession.setPlaybackState( PlaybackStateCompat.Builder() .setExtras(playbackStateExtras) // ...and any other setters. .build())
Java
import androidx.media.utils.MediaConstants; // When the MediaItem is constructed to show in the browse view. // Suppose the item was 25% complete when the user launched the browse view. Bundle mediaItemExtras = new Bundle(); mediaItemExtras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.25); MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setMediaId("my-media-id") .setExtras(mediaItemExtras) // ...and any other setters. .build(); return MediaBrowserCompat.MediaItem(description, /* flags */); // Elsewhere, when the user has selected MediaItem for playback. mediaSession.setMetadata( new MediaMetadataCompat.Builder() .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, "my-media-id") // ...and any other setters. .build()); Bundle playbackStateExtras = new Bundle(); playbackStateExtras.putString( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID, "my-media-id"); mediaSession.setPlaybackState( new PlaybackStateCompat.Builder() .setExtras(playbackStateExtras) // ...and any other setters. .build());
Göz atılabilir arama sonuçlarını göster
Uygulamanız, kullanıcılara arama sorgusu başlattıklarında gösterilen bağlamsal arama sonuçları sağlayabilir. Android Auto ve Android Automotive OS, bu sonuçları arama sorgusu arayüzleri veya oturumda daha önce yapılan sorgulara göre belirlenen fırsatlar aracılığıyla gösterir. Daha fazla bilgi edinmek için bu kılavuzdaki Sesli işlemleri destekleme bölümüne bakın.
Göz atılabilir arama sonuçlarını görüntülemek için hizmetinizin onGetRoot()
yönteminde true
boole ile eşlenen ekstralar paketine BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED
sabit anahtarını ekleyin.
Aşağıdaki kod snippet'i, onGetRoot()
yönteminde desteğin nasıl etkinleştirileceğini gösterir:
Kotlin
import androidx.media.utils.MediaConstants @Nullable fun onGetRoot( @NonNull clientPackageName: String, clientUid: Int, @Nullable rootHints: Bundle ): BrowserRoot { val extras = Bundle() extras.putBoolean( MediaConstants.BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED, true) return BrowserRoot(ROOT_ID, extras) }
Java
import androidx.media.utils.MediaConstants; @Nullable @Override public BrowserRoot onGetRoot( @NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) { Bundle extras = new Bundle(); extras.putBoolean( MediaConstants.BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED, true); return new BrowserRoot(ROOT_ID, extras); }
Arama sonuçları sağlamaya başlamak için medya tarayıcısı hizmetinizde onSearch()
yöntemini geçersiz kılın. Android Auto ve Android Automotive OS, bir kullanıcı arama sorgusu arayüzünü veya "Arama sonuçları" olanağını çağırdığında, kullanıcının arama terimlerini bu yönteme yönlendirir.
Hizmetinizin onSearch()
yönteminden elde edilen arama sonuçlarını, başlık öğelerini kullanarak düzenleyerek daha göz atılabilir hale getirebilirsiniz. Örneğin, uygulamanızda müzik çalarsa arama sonuçlarını
albüm, sanatçı ve şarkılara göre düzenleyebilirsiniz.
Aşağıdaki kod snippet'i, onSearch()
yönteminin basit bir uygulamasını göstermektedir:
Kotlin
fun onSearch(query: String, extras: Bundle) { // Detach from results to unblock the caller (if a search is expensive). result.detach() object:AsyncTask() { internal var searchResponse:ArrayList internal var succeeded = false protected fun doInBackground(vararg params:Void):Void { searchResponse = ArrayList() if (doSearch(query, extras, searchResponse)) { succeeded = true } return null } protected fun onPostExecute(param:Void) { if (succeeded) { // Sending an empty List informs the caller that there were no results. result.sendResult(searchResponse) } else { // This invokes onError() on the search callback. result.sendResult(null) } return null } }.execute() } // Populates resultsToFill with search results. Returns true on success or false on error. private fun doSearch( query: String, extras: Bundle, resultsToFill: ArrayList ): Boolean { // Implement this method. }
Java
@Override public void onSearch(final String query, final Bundle extras, Result<List<MediaItem>> result) { // Detach from results to unblock the caller (if a search is expensive). result.detach(); new AsyncTask<Void, Void, Void>() { List<MediaItem> searchResponse; boolean succeeded = false; @Override protected Void doInBackground(Void... params) { searchResponse = new ArrayList<MediaItem>(); if (doSearch(query, extras, searchResponse)) { succeeded = true; } return null; } @Override protected void onPostExecute(Void param) { if (succeeded) { // Sending an empty List informs the caller that there were no results. result.sendResult(searchResponse); } else { // This invokes onError() on the search callback. result.sendResult(null); } } }.execute() } /** Populates resultsToFill with search results. Returns true on success or false on error. */ private boolean doSearch(String query, Bundle extras, ArrayList<MediaItem> resultsToFill) { // Implement this method. }
Özel Göz Atma İşlemleri
Özel Göz Atma İşlemleri, arabanın medya uygulamasında uygulamanızın MediaItem
nesnelerine özel simgeler ve etiketler eklemenize ve bu işlemlerle kullanıcı etkileşimlerini yönetmenize olanak tanır. Bu, Medya Uygulamasının işlevselliğini "İndir", "Sıraya Ekle", "Radyoyu Çal", "Favori" veya "Kaldır" işlemleri eklemek gibi çeşitli şekillerde genişletmenize olanak tanır.
OEM'nin gösterilmesine izin verdiğinden daha fazla özel işlem varsa kullanıcıya bir taşma menüsü sunulur.
İşleyiş şekli
Her Özel Göz Atma İşlemi şununla tanımlanır:
- İşlem Kimliği (benzersiz dize tanımlayıcısı)
- İşlem Etiketi (kullanıcıya gösterilen metin)
- İşlem Simgesi URI'sı (renk tonu eklenebilen bir vektör çekilebilir öğesi)
BrowseRoot
kapsamında genel olarak bir Özel Tarama İşlemleri listesi tanımlarsınız. Ardından, bu işlemlerin bir alt kümesini tek tek
MediaItem.
Kullanıcı bir Özel Göz Atma İşlemi ile etkileşime geçtiğinde uygulamanız onCustomAction()
üzerinden bir geri arama alır. Ardından, işlemi gerçekleştirebilir ve gerekirse MediaItem
ile ilgili işlem listesini güncelleyebilirsiniz. Bu, "En Beğendiklerim" ve "İndir" gibi
durum bilgili işlemler için yararlıdır. "Radyo Çal" gibi güncelleme gerektirmeyen işlemler için işlem listesini güncellemeniz gerekmez.
Ayrıca, bir göz atma düğümü köküne Özel Göz Atma İşlemleri ekleyebilirsiniz. Bu işlemler, ana araç çubuğunun altındaki ikincil bir araç çubuğunda görüntülenir.
Özel Göz Atma İşlemleri nasıl uygulanır?
Projenize Özel Göz Atma İşlemleri eklemek için şu adımları uygulayın:
MediaBrowserServiceCompat
uygulamanızda iki yöntemi geçersiz kılın:- Çalışma zamanında işlem sınırlarını ayrıştırın:
onGetRoot()
ürününde,rootHints
Bundle
içindeBROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT
anahtarını kullanarak her birMediaItem
için izin verilen maksimum işlem sayısını alın. 0 sınırı, özelliğin sistem tarafından desteklenmediğini gösterir.
- Özel Göz Atma İşlemlerinin genel listesini oluşturun:
- Her işlem için aşağıdaki anahtarlarla bir
Bundle
nesnesi oluşturun: *EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID
: İşlem kimliği *EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL
: İşlem etiketi *EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI
: İşlem simgesi URI'sı * TümBundle
işlemi nesnelerini bir listeye ekleyin.
- Her işlem için aşağıdaki anahtarlarla bir
- Global listeyi
BrowseRoot
cihazınıza ekleyin:BrowseRoot
EkstralardaBundle
, işlem listesiniBROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST
anahtarını kullanarakParcelable
Arraylist
olarak ekleyin.
MediaItem
nesnenize işlemler ekleyin:DESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST
anahtarını kullanarakMediaDescriptionCompat
ekstralarına işlem kimliklerinin listesini dahil ederek bağımsızMediaItem
nesnelerine işlem ekleyebilirsiniz. Bu liste,BrowseRoot
içinde tanımladığınız genel işlem listesinin bir alt kümesi olmalıdır.
- İşlemleri işleme ve döndürme ilerlemesi veya sonuçları döndürme:
onCustomAction
ürününde, işlem kimliğine ve ihtiyacınız olan diğer verilere göre işlemi gerçekleştirin. İşlemi tetikleyenMediaItem
kimliğini,EXTRAS_KEY_CUSTOM_BROWSER_ACTION_MEDIA_ITEM_ID
anahtarını kullanarak ekstralardan öğrenebilirsiniz.- İlerleme veya sonuç paketine
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
anahtarını dahil ederekMediaItem
için işlem listesini güncelleyebilirsiniz.
Özel Göz Atma İşlemleri'ni kullanmaya başlamak için BrowserServiceCompat
üzerinde yapabileceğiniz bazı değişiklikleri aşağıda bulabilirsiniz.
TarayıcıServiceCompat'ı Geçersiz Kıl
MediaBrowserServiceCompat
içinde aşağıdaki yöntemleri geçersiz kılmanız gerekiyor.
public void onLoadItem(String itemId, @NonNull Result<MediaBrowserCompat.MediaItem> result)
public void onCustomAction(@NonNull String action, Bundle extras, @NonNull Result<Bundle> result)
Ayrıştırma işlemi sınırı
Kaç tane Özel Göz Atma İşleminin desteklendiğini kontrol etmeniz gerekir.
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, Bundle rootHints) { rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT, 0) }
Özel Göz Atma İşlemi Oluşturma
Her işlemin ayrı bir Bundle
içinde paketlenmesi gerekir.
- İşlem Kimliği
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID, "<ACTION_ID>")
- İşlem Etiketi
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL, "<ACTION_LABEL>")
- İşlem Simgesi URI'si
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI, "<ACTION_ICON_URI>")
Parceable
ArrayList
için Özel Göz Atma İşlemleri ekleyin
Tüm Özel Tarama İşlemi Bundle
nesnelerini bir ArrayList
içine ekleyin.
private ArrayList<Bundle> createCustomActionsList( CustomBrowseAction browseActions) { ArrayList<Bundle> browseActionsBundle = new ArrayList<>(); for (CustomBrowseAction browseAction : browseActions) { Bundle action = new Bundle(); action.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID, browseAction.mId); action.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL, getString(browseAction.mLabelResId)); action.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI, browseAction.mIcon); browseActionsBundle.add(action); } return browseActionsBundle; }
Özel Göz Atma İşlemi listesini göz atma köküne ekleyin
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, Bundle rootHints) { Bundle browserRootExtras = new Bundle(); browserRootExtras.putParcelableArrayList( BROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST, createCustomActionsList())); mRoot = new BrowserRoot(ROOT_ID, browserRootExtras); return mRoot; }
MediaItem
öğesine işlem ekleyin
MediaDescriptionCompat buildDescription (long id, String title, String subtitle, String description, Uri iconUri, Uri mediaUri, ArrayList<String> browseActionIds) { MediaDescriptionCompat.Builder bob = new MediaDescriptionCompat.Builder(); bob.setMediaId(id); bob.setTitle(title); bob.setSubtitle(subtitle); bob.setDescription(description); bob.setIconUri(iconUri); bob.setMediaUri(mediaUri); Bundle extras = new Bundle(); extras.putStringArrayList( DESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST, browseActionIds); bob.setExtras(extras); return bob.build(); } MediaItem mediaItem = new MediaItem(buildDescription(...), flags);
Derleme onCustomAction
sonucu
- MediaId'yi
Bundle extras
öğesinden ayrıştır:@Override public void onCustomAction( @NonNull String action, Bundle extras, @NonNull Result<Bundle> result){ String mediaId = extras.getString(MediaConstans.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_MEDIA_ITEM_ID); }
- Eşzamansız sonuçlar için sonucu ayırın.
result.detach()
- Derleme sonucu paketi
mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE, mContext.getString(stringRes))
adlı kullanıcıya mesaj- Öğeyi güncelle(bir öğedeki işlemleri güncellemek için kullanın)
mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM, mediaId);
- Oynatma görünümünü aç
//Shows user the PBV without changing the playback state mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_SHOW_PLAYING_ITEM, null);
- Göz Atma Düğümünü Güncelle
//Change current browse node to mediaId mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_BROWSE_NODE, mediaId);
- Hata varsa
result.sendError(resultBundle).
numaralı telefonu arayın - İlerleme durumu güncellenirse
result.sendProgressUpdate(resultBundle)
numaralı telefonu arayın. result.sendResult(resultBundle)
numaralı telefonu arayarak işlemi tamamlayın.
İşlem Durumunu Güncelle
result.sendProgressUpdate(resultBundle)
yöntemini EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
anahtarıyla kullanarak MediaItem
özelliğini, işlemin yeni durumunu yansıtacak şekilde güncelleyebilirsiniz. Bu sayede kullanıcıya işlemin ilerlemesi ve sonucu hakkında gerçek zamanlı geri bildirim sunabilirsiniz.
Örnek: İndirme İşlemi
Aşağıda, üç durumda bir indirme işlemi uygulamak için bu özelliği nasıl kullanabileceğinize ilişkin bir örnek verilmiştir:
- İndir: İşlemin başlangıç durumudur. Kullanıcı bu işlemi seçtiğinde, işlemi "İndiriliyor" olarak değiştirebilir ve kullanıcı arayüzünü güncellemek için
sendProgressUpdate
yöntemini çağırabilirsiniz. - İndiriliyor: Bu durum indirme işleminin devam ettiğini gösterir. Bu durumu, kullanıcıya ilerleme çubuğu veya başka bir gösterge göstermek için kullanabilirsiniz.
- İndirildi: Bu durum, indirme işleminin tamamlandığını gösterir. İndirme işlemi tamamlandığında, "İndiriliyor"u "İndirildi" olarak değiştirebilir ve öğenin yenilenmesi gerektiğini belirtmek için
sendResult
yönteminiEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
anahtarıyla çağırabilirsiniz. AyrıcaEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE
tuşunu kullanarak kullanıcıya bir başarı mesajı gösterebilirsiniz.
Bu yaklaşım, kullanıcıya indirme işlemi ve mevcut durumu hakkında net geri bildirim sağlamanıza olanak tanır. %25, %50, %75 indirme durumlarını göstermek için simgelerle daha fazla ayrıntı ekleyebilirsiniz.
Örnek: Favori İşlem
Başka bir örnek de iki durumu olan favori bir işlemdir:
- Favori: Bu işlem, kullanıcının favoriler listesinde olmayan öğeler için görüntülenir. Kullanıcı bu işlemi seçtiğinde, işlemi "Favorilere Eklendi" ile değiştirebilir ve kullanıcı arayüzünü güncellemek için
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
tuşuylasendResult
öğesini çağırabilirsiniz. - Favorilere eklendi: Bu işlem, kullanıcının favoriler listesindeki öğeler için görüntülenir. Kullanıcı bu işlemi seçtiğinde, işlemi "Favori" ile değiştirebilir ve kullanıcı arayüzünü güncellemek için
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
tuşuylasendResult
numarasını çağırabilirsiniz.
Bu yaklaşım, kullanıcıların favori öğelerini yönetmeleri için net ve tutarlı bir yol sağlar.
Bu örnekler, Özel Göz Atma İşlemlerinin esnekliğini ve arabanın medya uygulamasında gelişmiş bir kullanıcı deneyimi için gerçek zamanlı geri bildirimle çeşitli işlevleri uygulamak üzere bunları nasıl kullanabileceğinizi göstermektedir.
Bu özelliğin tam bir örneği için TestMediaApp
projesine bakabilirsiniz.
Oynatma kontrolünü etkinleştir
Android Auto ve Android Automotive OS, oynatma kontrolü komutlarını hizmetinizin MediaSessionCompat
üzerinden gönderir.
Bir oturum kaydetmeniz ve ilişkili geri çağırma yöntemlerini uygulamanız gerekir.
Medya oturumu kaydetme
Medya tarayıcısı hizmetinizin onCreate()
yönteminde bir MediaSessionCompat
oluşturun, ardından setSessionToken()
yöntemini çağırarak medya oturumunu kaydedin.
Aşağıdaki kod snippet'i, bir medya oturumunun nasıl oluşturulacağını ve kaydedileceğini gösterir:
Kotlin
override fun onCreate() { super.onCreate() ... // Start a new MediaSession. val session = MediaSessionCompat(this, "session tag").apply { // Set a callback object that implements MediaSession.Callback // to handle play control requests. setCallback(MyMediaSessionCallback()) } sessionToken = session.sessionToken ... }
Java
public void onCreate() { super.onCreate(); ... // Start a new MediaSession. MediaSessionCompat session = new MediaSessionCompat(this, "session tag"); setSessionToken(session.getSessionToken()); // Set a callback object that implements MediaSession.Callback // to handle play control requests. session.setCallback(new MyMediaSessionCallback()); ... }
Medya oturumu nesnesini oluşturduğunuzda, oynatma kontrolü isteklerini işlemek için kullanılan bir geri çağırma nesnesi ayarlarsınız. Bu geri çağırma nesnesini, uygulamanız için MediaSessionCompat.Callback
sınıfının bir uygulanmasını sağlayarak oluşturursunuz. Bir sonraki bölümde, bu nesnenin nasıl uygulanacağı açıklanmaktadır.
Oynatma komutlarını uygulama
Bir kullanıcı, uygulamanızdaki bir medya öğesinin oynatılmasını istediğinde Android Automotive OS ve Android Auto, uygulamanızın medya tarayıcısı hizmetinden edindikleri, uygulamanızın MediaSessionCompat
nesnesine ait MediaSessionCompat.Callback
sınıfını kullanır. Bir kullanıcı, oynatmayı duraklatmak veya sonraki parçaya atlamak gibi içerik oynatmayı kontrol etmek istediğinde, Android Auto ve Android Automotive OS, geri çağırma nesnesinin yöntemlerinden birini çağırır.
İçerik oynatma işlemini işlemek için uygulamanızın, soyut MediaSessionCompat.Callback
sınıfını genişletmesi ve uygulamanızın desteklediği yöntemleri uygulaması gerekir.
Uygulamanızın sunduğu içerik türü için anlamlı olan aşağıdaki geri çağırma yöntemlerinin tümünü uygulayın:
onPrepare()
- Medya kaynağı değiştirildiğinde çağrılır. Android Automotive OS, başlatıldıktan hemen sonra da bu yöntemi çağırır. Medya uygulamanız bu yöntemi uygulamalıdır.
onPlay()
- Kullanıcı, belirli bir öğe seçmeden oynamayı seçerse çağrılır. Uygulamanız varsayılan içeriğini oynatmalıdır. Oynatma
onPause()
ile duraklatıldıysa uygulamanız oynatmaya devam eder.Not: Android Automotive OS veya Android Auto, medya tarayıcısı hizmetinize bağlandığında uygulamanız otomatik olarak müzik çalmaya başlamamalıdır. Daha fazla bilgi için ilk oynatma durumunu ayarlama bölümüne bakın.
onPlayFromMediaId()
- Kullanıcı, belirli bir öğeyi oynatmayı seçtiğinde çağrılır. Yöntem, medya tarayıcı hizmetinizin içerik hiyerarşinizdeki medya öğesine atadığı ID'yi geçirir.
onPlayFromSearch()
- Kullanıcı, bir arama sorgusundan oynatmayı seçtiğinde çağrılır. Uygulama, iletilen arama dizesine göre uygun bir seçim yapmalıdır.
onPause()
- Kullanıcı oynatmayı duraklatmayı seçtiğinde çağrılır.
onSkipToNext()
- Kullanıcı bir sonraki öğeye atlamayı seçtiğinde çağrılır.
onSkipToPrevious()
- Kullanıcı bir önceki öğeye atlamayı seçtiğinde çağrılır.
onStop()
- Kullanıcı oynatmayı durdurmayı seçtiğinde çağrılır.
İstediğiniz işlevi sağlamak için uygulamanızda bu yöntemleri geçersiz kılın. İşleviniz uygulamanız tarafından desteklenmeyen bir yöntemi uygulamanıza gerek yoktur. Örneğin, uygulamanız spor yayını gibi canlı bir yayın yayınlıyorsa onSkipToNext()
yöntemini uygulamanız gerekmez. Bunun yerine, varsayılan onSkipToNext()
uygulamasını kullanabilirsiniz.
Uygulamanızın içeriği arabanın hoparlörlerinden çalmak için özel bir mantığa ihtiyacı yoktur. Uygulamanız içerik oynatma isteği aldığında sesi, içeriği kullanıcının telefon hoparlörlerinden veya kulaklığından çaldığı gibi çalabilir. Android Auto ve Android Automotive OS, ses içeriğini aracın hoparlörlerinden çalmak için otomatik olarak araba sistemine gönderir.
Ses içeriği çalma hakkında daha fazla bilgi için bkz. MediaPlayer'a genel bakış, Ses uygulamasına genel bakış ve ExoPlayer genel bakış.
Standart oynatma işlemlerini ayarlama
Android Auto ve Android Automotive OS, oynatma kontrollerini PlaybackStateCompat
nesnesinde etkinleştirilen işlemlere dayalı olarak gösterir.
Varsayılan olarak, uygulamanız aşağıdaki işlemleri desteklemelidir:
Uygulamanız, içeriğiyle alakalı olmaları durumunda aşağıdaki işlemleri de destekleyebilir:
Buna ek olarak, kullanıcı için gösterilebilecek bir oynatma sırası da oluşturabilirsiniz, ancak bu zorunlu değildir. Bunu yapmak için setQueue()
ve setQueueTitle()
yöntemlerini çağırın, ACTION_SKIP_TO_QUEUE_ITEM
işlemini etkinleştirin ve geri çağırmayı onSkipToQueueItem()
tanımlayın.
Ayrıca, şu anda neyin çaldığını belirten Şimdi oynatılıyor simgesi için destek ekleyin. Bunu yapmak için setActiveQueueItemId()
yöntemini çağırın ve sıradaki oynatılan öğenin kimliğini iletin. Bir sıra değişikliği olduğunda setActiveQueueItemId()
uygulamasını güncellemeniz gerekir.
Android Auto ve Android Automotive OS, etkinleştirilen her işlem için ve oynatma sırası için düğmeler görüntüler. Düğmeler tıklandığında sistem, ilgili geri çağırmayı MediaSessionCompat.Callback
üzerinden başlatır.
Kullanılmayan alan ayırın
Android Auto ve Android Automotive OS, kullanıcı arayüzünde ACTION_SKIP_TO_PREVIOUS
ve ACTION_SKIP_TO_NEXT
işlemleri için yer ayırır. Uygulamanız bu işlevlerden birini desteklemiyorsa Android Auto ve Android Automotive OS, oluşturduğunuz özel işlemleri görüntülemek için bu alanı kullanır.
Bu alanları özel işlemlerle doldurmak istemiyorsanız bu alanları, uygulamanız ilgili işlevi desteklemediğinde Android Auto ve Android Automotive OS'in alanı boş bırakması için ayırabilirsiniz. Bunu yapmak için setExtras()
yöntemini, ayrılmış işlevlere karşılık gelen sabit değerler içeren bir ekstra paketle çağırın.
SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT
ACTION_SKIP_TO_NEXT
değerine, SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV
ACTION_SKIP_TO_PREVIOUS
değerine karşılık gelir. Bu sabit değerleri pakette anahtar olarak ve değerleri için true
boole'sini kullanın.
İlk Oynatma Durumunu ayarla
Android Auto ve Android Automotive OS, medya tarayıcı hizmetinizle iletişim kurarken medya oturumunuz, içerik oynatma durumunu PlaybackStateCompat
kullanarak bildirir.
Android Automotive OS veya Android Auto medya tarayıcı hizmetinize bağlandığında uygulamanız otomatik olarak müzik çalmaya başlamamalıdır. Bunun yerine, arabanın durumuna veya kullanıcı işlemlerine göre oynatmayı devam ettirmek veya başlatmak için Android Auto ve Android Automotive OS'e güvenin.
Bunu gerçekleştirmek için medya oturumunuzun ilk PlaybackStateCompat
değerini
STATE_STOPPED
,
STATE_PAUSED
,
STATE_NONE
veya STATE_ERROR
olarak ayarlayın.
Android Auto ve Android Automotive OS'teki medya oturumları yalnızca sürüş süresi boyunca devam ettiği için kullanıcılar bu oturumları sık sık başlatıp durdurur. Sürücüler arasında sorunsuz bir deneyim sunmak için kullanıcının önceki oturum durumunu takip edin. Böylece medya uygulaması bir devam ettirme isteği aldığında kullanıcı, kaldığı yerden (ör. en son oynatılan medya öğesi, PlaybackStateCompat
ve sıra) otomatik olarak devam edebilir.
Özel oynatma işlemleri ekle
Medya uygulamanızın desteklediği diğer işlemleri görüntülemek için özel oynatma işlemleri ekleyebilirsiniz. Alan uygunsa (ve ayrılmamışsa) Android, özel işlemleri aktarım denetimlerine ekler. Aksi takdirde, özel işlemler
taşma menüsünde görüntülenir. Özel işlemler, PlaybackStateCompat
öğesine eklendikleri sırayla görüntülenir.
Standart işlemlerden farklı davranışlar sağlamak için özel işlemleri kullanın. Bunları standart işlemleri değiştirmek veya kopyalamak için kullanmayın.
PlaybackStateCompat.Builder
sınıfında addCustomAction()
yöntemini kullanarak özel işlemler ekleyebilirsiniz.
Aşağıdaki kod snippet'i, özel bir "Radyo kanalı başlat" işleminin nasıl ekleneceğini göstermektedir:
Kotlin
stateBuilder.addCustomAction( PlaybackStateCompat.CustomAction.Builder( CUSTOM_ACTION_START_RADIO_FROM_MEDIA, resources.getString(R.string.start_radio_from_media), startRadioFromMediaIcon ).run { setExtras(customActionExtras) build() } )
Java
stateBuilder.addCustomAction( new PlaybackStateCompat.CustomAction.Builder( CUSTOM_ACTION_START_RADIO_FROM_MEDIA, resources.getString(R.string.start_radio_from_media), startRadioFromMediaIcon) .setExtras(customActionExtras) .build());
Bu yöntemin daha ayrıntılı bir örneği için GitHub'daki Universal Android Music Player örnek uygulamasında yer alan setCustomAction()
yöntemine bakın.
Özel işleminizi oluşturduktan sonra medya oturumunuz onCustomAction()
yöntemini geçersiz kılarak işleme yanıt verebilir.
Aşağıdaki kod snippet'i, uygulamanızın "Radyo kanalı başlat" işlemine nasıl tepki verebileceğini gösterir:
Kotlin
override fun onCustomAction(action: String, extras: Bundle?) { when(action) { CUSTOM_ACTION_START_RADIO_FROM_MEDIA -> { ... } } }
Java
@Override public void onCustomAction(@NonNull String action, Bundle extras) { if (CUSTOM_ACTION_START_RADIO_FROM_MEDIA.equals(action)) { ... } }
Bu yöntemin daha ayrıntılı bir örneği için GitHub'daki Universal Android Music Player örnek uygulamasında yer alan onCustomAction
yöntemine bakın.
Özel işlemler için simgeler
Oluşturduğunuz her özel işlem bir simge kaynağı gerektirir. Arabalardaki uygulamalar pek çok farklı ekran boyutunda ve yoğunlukta çalışabilir. Bu nedenle, sağladığınız simgeler vektör çekilebilir öğeleri olmalıdır. Vektör çekilebilir özelliği, öğeleri ayrıntıyı kaybetmeden ölçeklendirmenize olanak tanır. Vektör çekilebilir özelliği, daha düşük çözünürlüklerde kenar ve köşeleri piksel sınırlarıyla hizalamayı da kolaylaştırır.
Özel bir işlem durum bilgiliyse (örneğin, bir oynatma ayarını açıp kapatıyorsa) farklı durumlar için farklı simgeler sağlar. Böylece kullanıcılar işlemi seçerken bir değişiklik görebilir.
Devre dışı bırakılan işlemler için alternatif simge stilleri sağlayın
Bir özel işlem geçerli bağlam için kullanılamadığında, özel işlem simgesini işlemin devre dışı bırakıldığını gösteren alternatif bir simgeyle değiştirin.
Ses biçimini belirtin
Oynatılan medyanın özel bir ses biçimi kullandığını belirtmek için
bu özelliği destekleyen arabalarda oluşturulacak simgeleri belirtebilirsiniz. Şu anda oynatılan medya öğesinin (MediaSession.setMetadata()
bölümüne iletilen) ekstralar paketindeki KEY_CONTENT_FORMAT_TINTABLE_LARGE_ICON_URI
ve KEY_CONTENT_FORMAT_TINTABLE_SMALL_ICON_URI
özelliklerini ayarlayabilirsiniz. Farklı düzenleri barındıracak şekilde bu ekstraların ikisini de ayarladığınızdan emin olun.
Ayrıca, araç OEM'lerine sesin etkileyici bir görüntü oluşturduğunu ve sürükleyici içeriği etkileyebilecek ses efektleri uygulayıp uygulamayacağına karar verirken çok dikkatli olmaları gerektiğini belirtmek için KEY_IMMERSIVE_AUDIO
ekstrasını ayarlayabilirsiniz.
Şu anda oynatılan öğeden bağlantılar ekleyin
Oynatılan medya öğesini, alt başlığı, açıklaması veya her ikisi de diğer medya öğelerine bağlantı olacak şekilde yapılandırabilirsiniz. Bu, kullanıcının ilgili öğelere (ör. aynı sanatçının diğer şarkılarına, podcast'in diğer bölümlerine vb.) atlamasını sağlar. Araba bu özelliği destekliyorsa kullanıcılar bağlantıya dokunarak ilgili içeriğe göz atabilir.
Bağlantı eklemek için KEY_SUBTITLE_LINK_MEDIA_ID
meta verilerini (altyazıdan bağlantı oluşturmak için) veya KEY_DESCRIPTION_LINK_MEDIA_ID
(açıklamadan bağlantı vermek için) yapılandırın. Ayrıntılar için bu meta veri alanlarının referans belgelerine bakın.
Sesli işlemleri destekleyin
Sürücülere, dikkat dağıtıcı unsurları en aza indiren güvenli ve rahat bir deneyim sunmak için medya uygulamanız sesli işlemleri desteklemelidir. Örneğin, uygulamanız bir medya öğesini çalıyorsa kullanıcı, aracın ekranına bakmadan veya dokunmadan uygulamanıza farklı bir şarkı çalmasını söylemek için"[şarkı adını]çal" diyebilirsiniz. Kullanıcılar direksiyonlarındaki uygun düğmeleri tıklayarak veya "Ok Google" özel kelimelerini söyleyerek sorgu başlatabilir.
Android Auto veya Android Automotive OS bir sesli işlem algılayıp yorumladığında, bu sesli işlem onPlayFromSearch()
üzerinden uygulamaya iletilir.
Bu geri çağırmayı aldığında uygulama, query
dizesiyle eşleşen içeriği bulur ve oynatmayı başlatır.
Kullanıcılar, sorgularında farklı terim kategorileri belirtebilir: tür, sanatçı, albüm, şarkı adı, radyo istasyonu veya şarkı listesi gibi. Arama desteği oluştururken uygulamanız için anlamlı olan tüm kategorileri hesaba katın. Android Auto veya Android Automotive OS, belirli bir sorgunun belirli kategorilere uyduğunu tespit ederse extras
parametresine ekstra ekler ekler. Aşağıdaki ekstralar gönderilebilir:
Kullanıcı arama terimleri belirtmezse Android Auto veya Android Automotive OS tarafından gönderilebilen boş bir query
dizesini hesaba katın.
Örneğin, kullanıcı "Müzik çal" diyorsa. Bu durumda, uygulamanız yakın zamanda çalınan veya yeni önerilen bir parçayı başlatmayı seçebilir.
Arama hızlıca işlenemiyorsa onPlayFromSearch()
içinde engelleme yapmayın.
Bunun yerine, oynatma durumunu STATE_CONNECTING
olarak ayarlayın ve aramayı eşzamansız bir iş parçacığında gerçekleştirin.
Oynatma başladıktan sonra medya oturumu sırasını ilgili içerikle doldurmayı düşünün. Örneğin, kullanıcı bir albümün çalınmasını isterse uygulamanız bu sırayı albümün parça listesiyle doldurabilir. Ayrıca, kullanıcının sorgusuyla eşleşen farklı bir parça seçebilmesi için göz atılabilir arama sonuçları desteği uygulamayı da düşünebilirsiniz.
Android Auto ve Android Automotive, "oynat" sorgularına ek olarak "müziği duraklat" ve "sonraki şarkı" gibi çalma işlemlerini kontrol etmek için sesli sorguları tanır ve bu komutları onPause()
ve onSkipToNext()
gibi uygun medya oturumu geri aramalarıyla eşleştirir.
Uygulamanızda sesle etkinleştirilen oynatma işlemlerini nasıl uygulayacağınızla ilgili ayrıntılı bir örnek için Google Asistan ve medya uygulamaları bölümüne bakın.
Dikkat dağıtıcı önlemler uygulayın
Android Auto kullanılırken kullanıcının telefonu arabasının hoparlörlerine bağlı olduğundan sürücünün dikkatinin dağılmasını önlemek için ek önlemler almanız gerekir.
Arabadaki alarmları bastırın
Android Auto medya uygulamaları, kullanıcı örneğin bir oynat düğmesine basarak oynatmaya başlamadığı sürece sesleri araç hoparlörlerinden çalmaya başlamamalıdır. Medya uygulamanızdan kullanıcı tarafından planlanmış bir alarm bile araç hoparlörlerinden müzik çalmaya başlamamalıdır.
Uygulamanız bu gereksinimi karşılamak için herhangi bir ses çalmadan önce sinyal olarak CarConnection
kullanabilir. Uygulamanız, araba bağlantı türü için LiveData
gözlemleyerek ve CONNECTION_TYPE_PROJECTION
ile aynı olup olmadığını kontrol ederek telefonun bir araba ekranına projeksiyon yapıp yapmadığını kontrol edebilir.
Kullanıcının telefonu projeksiyon yapıyorsa alarmları destekleyen medya uygulamalarının aşağıdakilerden birini yapması gerekir:
- Alarmı devre dışı bırakın.
- Alarmı
STREAM_ALARM
üzerinden çalın ve alarmı devre dışı bırakmak için telefon ekranına bir kullanıcı arayüzü sağlayın.
Medya reklamlarını yönetme
Varsayılan olarak bir ses çalma oturumu sırasında medya meta verileri değiştiğinde Android Auto bir bildirim gösterir. Bir medya uygulaması müzik çalma modundan reklam yayınlamaya geçiş yaptığında, kullanıcıya bildirim göstermesi dikkat dağıtıcı olur. Bu durumda Android Auto'nun bildirim görüntülemesini önlemek için medya meta veri anahtarını METADATA_KEY_IS_ADVERTISEMENT
aşağıdaki kod snippet'inde gösterildiği gibi METADATA_VALUE_ATTRIBUTE_PRESENT
olarak ayarlamanız gerekir:
Kotlin
import androidx.media.utils.MediaConstants override fun onPlayFromMediaId(mediaId: String, extras: Bundle?) { MediaMetadataCompat.Builder().apply { if (isAd(mediaId)) { putLong( MediaConstants.METADATA_KEY_IS_ADVERTISEMENT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) } // ...add any other properties you normally would. mediaSession.setMetadata(build()) } }
Java
import androidx.media.utils.MediaConstants; @Override public void onPlayFromMediaId(String mediaId, Bundle extras) { MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); if (isAd(mediaId)) { builder.putLong( MediaConstants.METADATA_KEY_IS_ADVERTISEMENT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT); } // ...add any other properties you normally would. mediaSession.setMetadata(builder.build()); }
Genel hataları ele alma
Uygulama bir hatayla karşılaştığında, oynatma durumunu STATE_ERROR
olarak ayarlayın ve setErrorMessage()
yöntemini kullanarak bir hata mesajı sağlayın. Hata mesajını ayarlarken kullanabileceğiniz hata kodlarının listesi için PlaybackStateCompat
sayfasına göz atın.
Hata mesajları kullanıcıya yönelik olmalı ve kullanıcının mevcut yerel ayarıyla yerelleştirilmelidir. Ardından Android Auto ve Android Automotive OS, kullanıcıya hata mesajını görüntüleyebilir.
Örneğin, içerik kullanıcının geçerli bölgesinde yoksa hata mesajını ayarlarken ERROR_CODE_NOT_AVAILABLE_IN_REGION
hata kodunu kullanabilirsiniz.
Kotlin
mediaSession.setPlaybackState( PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_ERROR) .setErrorMessage(PlaybackStateCompat.ERROR_CODE_NOT_AVAILABLE_IN_REGION, getString(R.string.error_unsupported_region)) // ...and any other setters. .build())
Java
mediaSession.setPlaybackState( new PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_ERROR) .setErrorMessage(PlaybackStateCompat.ERROR_CODE_NOT_AVAILABLE_IN_REGION, getString(R.string.error_unsupported_region)) // ...and any other setters. .build());
Hata durumları hakkında daha fazla bilgi için Medya oturumu kullanma: Durumlar ve hatalar bölümüne bakın.
Bir Android Auto kullanıcısının bir hatayı çözmek için telefon uygulamanızı açması gerekiyorsa mesajınızda bu kullanıcıya bu bilgiyi sağlayın. Örneğin, hata mesajınızda "Lütfen oturum açın" yerine "[Uygulamanızın adı] uygulamasında oturum açın" ifadesini görebilirsiniz.