Media3 ExoPlayer kullanarak temel bir medya oynatıcı uygulaması oluşturma

Jetpack Media3, video ve ses dosyalarının oynatılmasıyla ilgili temel işlevleri özetleyen bir Player arayüzü tanımlar. ExoPlayer, Media3'te bu arayüzün varsayılan uygulamasıdır. Çoğu oynatma kullanım alanını kapsayan kapsamlı bir özellik grubu sağladığı ve sahip olabileceğiniz diğer tüm kullanım alanlarını karşılayacak şekilde özelleştirilebildiği için ExoPlayer'ı kullanmanızı öneririz. ExoPlayer, cihaz ve işletim sistemi parçalanmasını da soyutlar. Böylece kodunuz Android ekosisteminin tamamında tutarlı bir şekilde çalışır. ExoPlayer şunları içerir:

Bu sayfada, oynatma uygulaması oluşturmanın bazı önemli adımları açıklanmaktadır. Daha fazla bilgi için Media3 ExoPlayer'daki tam rehberlerimize göz atabilirsiniz.

Başlarken

Başlamak için Jetpack Media3'ün ExoPlayer, kullanıcı arayüzü ve ortak modüllerine bağımlılık ekleyin:

implementation "androidx.media3:media3-exoplayer:1.4.1"
implementation "androidx.media3:media3-ui:1.4.1"
implementation "androidx.media3:media3-common:1.4.1"

Kullanım alanınıza bağlı olarak akışları DASH biçiminde oynatmak için exoplayer-dash gibi ek Media3 modüllerine de ihtiyacınız olabilir.

1.4.1 değerini, kitaplığın tercih ettiğiniz sürümüyle değiştirdiğinizden emin olun. En son sürümü görmek için sürüm notlarına bakabilirsiniz.

Medya oynatıcı oluşturma

Media3 ile, dahil edilen Player arayüzünü (ExoPlayer) kullanabilir veya kendi özel uygulamanızı oluşturabilirsiniz.

ExoPlayer oluşturma

ExoPlayer örneği oluşturmanın en basit yolu şunlardır:

Kotlin

val player = ExoPlayer.Builder(context).build()

Java

ExoPlayer player = new ExoPlayer.Builder(context).build();

Medya oynatıcınızı, bulunduğu Activity, Fragment veya Service alanının onCreate() yaşam döngüsü yöntemini kullanarak oluşturabilirsiniz.

Builder, ilgilenebileceğiniz çeşitli özelleştirme seçenekleri içerir. Örneğin:

Media3, uygulamanızın düzen dosyasına ekleyebileceğiniz bir PlayerView kullanıcı arayüzü bileşeni sağlar. Bu bileşen, oynatma kontrolleri için bir PlayerControlView, altyazıları görüntülemek için SubtitleView ve video oluşturma için Surface içerir.

Oynatıcıyı hazırlama

setMediaItem() ve addMediaItem() gibi yöntemlerle oynatma için oynatma listesine medya öğeleri ekleyin. Ardından, medya yüklemeye başlamak ve gerekli kaynakları edinmek için prepare() işlevini çağırın.

Bu adımları uygulama ön planda olmadan uygulamanız gerekir. Oynatıcınız Activity veya Fragment içindeyse bu, oynatıcıyı API düzeyi 24 ve üstü için onStart() yaşam döngüsü yöntemine veya API düzeyi 23 ve altında onResume() yaşam döngüsü yöntemine hazırlamak anlamına gelir. Service'te bulunan bir oyuncu için onCreate()'te hazırlayabilirsiniz.

Oynatıcıyı kontrol etme

Oynatıcı hazırlandıktan sonra, oynatmayı kontrol etmek için oynatıcıda aşağıdaki gibi yöntemler çağırabilirsiniz:

PlayerView veya PlayerControlView gibi kullanıcı arayüzü bileşenleri, bir oynatıcıya bağlandığında uygun şekilde güncellenir.

Oyuncuyu serbest bırakma

Oynatma işlemi, video kod çözücüler gibi sınırlı kaynaklar gerektirebilir. Bu nedenle, oynatıcıya artık ihtiyaç duyulmadığında kaynakları boşaltmak için oynatıcınızda release() çağrısını yapmanız önemlidir.

Oynatıcınız Activity veya Fragment içindeyse API düzeyi 24 ve sonraki sürümlerde onStop() yaşam döngüsü yöntemini veya API düzeyi 23 ve önceki sürümlerde onPause() yöntemini kullanarak oynatıcıyı yayınlayın. Service içinde olan bir oynatıcıyı onDestroy() üzerinde serbest bırakabilirsiniz.

Oynatma işlemini medya oturumuyla yönetme

Android'de medya oturumları, medya oynatıcıyla işlem sınırları arasında standart bir etkileşim yolu sağlar. Oynatıcınıza bir medya oturumu bağlamak, medya oynatma işleminizin reklamını harici olarak yapmanıza ve harici kaynaklardan oynatma komutları almanıza olanak tanır. Örneğin, mobil cihazlardaki ve büyük ekranlı cihazlardaki sistem medya kontrolleriyle entegrasyon için bu komutları kullanabilirsiniz.

Medya oturumlarını kullanmak için Media3 Session modülüne bağımlılık ekleyin:

implementation "androidx.media3:media3-session:1.4.1"

Medya oturumu oluşturma

Oynatıcıyı başlattıktan sonra aşağıdaki şekilde MediaSession oluşturabilirsiniz:

Kotlin

val player = ExoPlayer.Builder(context).build()
val mediaSession = MediaSession.Builder(context, player).build()

Java

ExoPlayer player = new ExoPlayer.Builder(context).build();
MediaSession mediaSession = new MediaSession.Builder(context, player).build();

Media3, Player öğesinin durumunu MediaSession öğesinin durumuyla otomatik olarak senkronize eder. Bu, ExoPlayer, CastPlayer veya özel bir uygulama da dahil olmak üzere tüm Player uygulamalarında çalışır.

Diğer istemcilere denetim izni ver

İstemci uygulamaları, medya oturumunuzun oynatılmasını kontrol etmek için bir medya denetleyici uygulayabilir. Bu istekleri almak için MediaSession'nizi oluştururken bir geri çağırma nesnesi ayarlayın.

Bir denetleyici, medya oturumunuza bağlanmak üzereyken onConnect() yöntemi çağrılır. İsteği kabul etmek veya reddetmek için sağlanan ControllerInfo simgesini kullanabilirsiniz. Bunun bir örneğini Media3 Session demo uygulamasında bulabilirsiniz.

Bağlandıktan sonra kumanda, oturuma oynatma komutları gönderebilir. Oturum daha sonra bu komutları oynatıcıya iletir. Player arayüzünde tanımlanan oynatma ve oynatma listesi komutları oturum tarafından otomatik olarak işlenir.

Diğer geri çağırma yöntemleri, örneğin özel oynatma komutları ve oynatma listesini değiştirme isteklerini işlemenize olanak tanır. Bu geri çağırmalarda da erişim denetimini istek bazında belirleyebilmeniz için bir ControllerInfo nesnesi bulunur.

Arka planda medya oynatma

Uygulamanız ön planda değilken medya oynatmaya devam etmek için (ör. kullanıcı uygulamanızı açmamışken müzik, sesli kitap veya podcast oynatmak için) Player ve MediaSession, bir ön plan hizmetine yerleştirilmelidir. Media3, bu amaç için MediaSessionService arayüzünü sağlar.

MediaSessionService uygulama

MediaSessionService sınıfını genişleten ve MediaSession sınıfınızı onCreate() yaşam döngüsü yönteminde örnekleyen bir sınıf oluşturun.

Kotlin

class PlaybackService : MediaSessionService() {
    private var mediaSession: MediaSession? = null

    // Create your Player and MediaSession in the onCreate lifecycle event
    override fun onCreate() {
        super.onCreate()
        val player = ExoPlayer.Builder(this).build()
        mediaSession = MediaSession.Builder(this, player).build()
    }

    // Remember to release the player and media session in onDestroy
    override fun onDestroy() {
        mediaSession?.run {
            player.release()
            release()
            mediaSession = null
        }
        super.onDestroy()
    }
}

Java

public class PlaybackService extends MediaSessionService {
    private MediaSession mediaSession = null;

    @Override
    public void onCreate() {
        super.onCreate();
        ExoPlayer player = new ExoPlayer.Builder(this).build();
        mediaSession = new MediaSession.Builder(this, player).build();
    }

    @Override
    public void onDestroy() {
        mediaSession.getPlayer().release();
        mediaSession.release();
        mediaSession = null;
        super.onDestroy();
    }
}

Manifest'inizde, Service sınıfınızı MediaSessionService intent filtresiyle belirtin ve ön plan hizmeti çalıştırmak için FOREGROUND_SERVICE iznini isteyin:

<service
    android:name=".PlaybackService"
    android:foregroundServiceType="mediaPlayback"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.media3.session.MediaSessionService"/>
    </intent-filter>
</service>

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

Son olarak, oluşturduğunuz sınıfta, istemcinin medya oturumunuza erişimini kontrol etmek için onGetSession() yöntemini geçersiz kılın. Bağlantı isteğini kabul etmek için MediaSession, isteği reddetmek için null döndürün.

Kotlin

// This example always accepts the connection request
override fun onGetSession(
    controllerInfo: MediaSession.ControllerInfo
): MediaSession? = mediaSession

Java

@Override
public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) {
  // This example always accepts the connection request
  return mediaSession;
}

Kullanıcı arayüzünüze bağlanılıyor

Medya oturumunuz, oynatıcı kullanıcı arayüzünüzün bulunduğu Activity veya Fragment'den ayrı bir Service içinde olduğuna göre bunları birbirine bağlamak için MediaController kullanabilirsiniz. Kullanıcı arayüzünüzle Activity veya Fragment'nin onStart() yönteminde MediaSession için bir SessionToken oluşturun, ardından SessionToken'ı kullanarak bir MediaController oluşturun. MediaController oluşturma işlemi eşzamanlı değildir.

Kotlin

override fun onStart() {
  val sessionToken = SessionToken(this, ComponentName(this, PlaybackService::class.java))
  val controllerFuture = MediaController.Builder(this, sessionToken).buildAsync()
  controllerFuture.addListener(
    {
        // Call controllerFuture.get() to retrieve the MediaController.
        // MediaController implements the Player interface, so it can be
        // attached to the PlayerView UI component.
        playerView.setPlayer(controllerFuture.get())
      },
    MoreExecutors.directExecutor()
  )
}

Java

@Override
public void onStart() {
  SessionToken sessionToken =
    new SessionToken(this, new ComponentName(this, PlaybackService.class));
  ListenableFuture<MediaController> controllerFuture =
    new MediaController.Builder(this, sessionToken).buildAsync();
  controllerFuture.addListener(() -> {
    // Call controllerFuture.get() to retrieve the MediaController.
    // MediaController implements the Player interface, so it can be
    // attached to the PlayerView UI component.
    playerView.setPlayer(controllerFuture.get());
  }, MoreExecutors.directExecutor())
}

MediaController, Player arayüzünü uygular. Bu nedenle, oynatmayı kontrol etmek için play() ve pause() gibi aynı yöntemleri kullanabilirsiniz. Diğer bileşenlere benzer şekilde, artık gerekli olmadığında MediaController'yi (ör. bir Activity'nin onStop() yaşam döngüsü yöntemi) MediaController.releaseFuture() çağırarak serbest bırakmayı unutmayın.

Bildirim yayınlama

Etkin durumdayken bildirim yayınlamak için ön plan hizmetleri gereklidir. MediaSessionService, sizin için MediaNotification biçiminde otomatik olarak bir MediaStyle bildirimi oluşturur. Özel bildirim sağlamak için DefaultMediaNotificationProvider.Builder ile veya sağlayıcı arayüzünün özel bir uygulamasını oluşturarak bir MediaNotification.Provider oluşturun. setMediaNotificationProvider ile sağlayıcınızı MediaSession hizmetine ekleyin.

İçerik kitaplığınız için reklam verme

MediaLibraryService, istemci uygulamalarının uygulamanız tarafından sağlanan medya içeriğine göz atmasına izin vererek MediaSessionService'yi temel alır. İstemci uygulamaları, MediaLibraryService ile etkileşim kurmak için bir MediaBrowser uygular.

MediaLibraryService uygulamak, MediaSessionService uygulamaya benzer. Tek fark, onGetSession()'de MediaSession yerine MediaLibrarySession döndürmeniz gerektiğidir. MediaSession.Callback ile karşılaştırıldığında MediaLibrarySession.Callback, tarayıcı istemcisinin kitaplık hizmetiniz tarafından sunulan içerikte gezinmesine olanak tanıyan ek yöntemler içerir.

MediaSessionService'e benzer şekilde, manifest'inizde MediaLibraryService'u belirtin ve ön plan hizmeti çalıştırmak için FOREGROUND_SERVICE iznini isteyin:

<service
    android:name=".PlaybackService"
    android:foregroundServiceType="mediaPlayback"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.media3.session.MediaLibraryService"/>
        <action android:name="android.media.browse.MediaBrowserService"/>
    </intent-filter>
</service>

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

Yukarıdaki örnekte hem MediaLibraryService hem de geriye dönük uyumluluk için eski MediaBrowserService için bir intent filtresi yer almaktadır. Ek intent filtresi, MediaBrowserCompat API'yi kullanan istemci uygulamalarının Service öğenizi tanımasını sağlar.

MediaLibrarySession, içerik kitaplığınızı tek bir kök MediaItem ile ağaç yapısında sunmanızı sağlar. Ağdaki her MediaItem öğesinin istediği sayıda alt MediaItem düğümü olabilir. İstemci uygulamasının isteğine bağlı olarak farklı bir kök veya farklı bir ağaç sunabilirsiniz. Örneğin, önerilen medya öğelerinin listesini arayan bir müşteriye döndürdüğünüz ağaç yalnızca kök MediaItem ve tek bir düzeyde alt MediaItem düğümü içerebilir. Ancak farklı bir istemci uygulamasına döndürdüğünüz ağaç daha kapsamlı bir içerik kitaplığını temsil edebilir.

MediaLibrarySession oluşturma

MediaLibrarySession, içeriklere göz atma API'leri eklemek için MediaSession API'yi genişletir. MediaSession geri çağırma yöntemine kıyasla MediaLibrarySession geri çağırma yöntemi aşağıdaki gibi yöntemler ekler:

  • onGetLibraryRoot() Bir istemci, içerik ağacının kökünü MediaItem istediğinde
  • onGetChildren() istemci, içerik ağacındaki bir MediaItem öğesinin alt öğelerini istediğinde
  • onGetSearchResult() Müşteri belirli bir sorgu için içerik ağacından arama sonuçları istediğinde

Alakalı geri çağırma yöntemleri, istemci uygulamasının ilgilendiği içerik ağacı türü hakkında ek sinyaller içeren bir LibraryParams nesnesi içerir.