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 sunduğu ve sahip olabileceğiniz diğer 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 ortadan kaldırarak kodunuzun tüm Android ekosisteminde tutarlı bir şekilde çalışmasını sağlar. ExoPlayer şunları içerir:

Bu sayfada, oynatma uygulaması oluşturmanın temel adımlarından bazıları açıklanmaktadır. Daha fazla bilgi için Media3 ExoPlayer ile ilgili kılavuzlarımızın tamamını inceleyebilirsiniz.

Başlarken

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

Kotlin

implementation("androidx.media3:media3-exoplayer:1.11.1")
implementation("androidx.media3:media3-ui:1.11.1")
implementation("androidx.media3:media3-common:1.11.1")

Modern

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

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

1.11.1 ifadesini kitaplığın tercih ettiğiniz sürümüyle değiştirdiğinizden emin olun. En yeni sürümü görmek için sürüm notlarına göz atabilirsiniz.

Medya oynatıcı oluşturma

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

ExoPlayer oluşturma

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

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 öğesinin onCreate() yaşam döngüsü yönteminde oluşturabilirsiniz.

Builder, ilginizi çekebilecek ç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 PlayerControlView, altyazıları görüntülemek için SubtitleView ve videoyu oluşturmak için Surface öğelerini içerir.

Oynatıcı hazırlanıyor

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

Uygulama ön planda değilken bu adımları gerçekleştirmemelisiniz. Oynatıcınız Activity veya Fragment içindeyse bu, oynatıcıyı API düzeyi 24 ve üzeri sürümlerde onStart() yaşam döngüsü yönteminde veya API düzeyi 23 ve altı sürümlerde onResume() yaşam döngüsü yönteminde hazırlamak anlamına gelir. Service olan bir oyuncu için onCreate() içinde hazırlayabilirsiniz. Yaşam döngüsü yöntemlerinin nasıl uygulanacağına dair bir örnek için Exoplayer codelab'e bakın.

Oynatıcıyı kontrol etme

Oynatıcı hazırlandıktan sonra, oynatıcıda aşağıdaki gibi yöntemleri çağırarak oynatmayı kontrol edebilirsiniz:

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

Oyuncuyu serbest bırakın

Oynatma işlemi, video kod çözücüler gibi sınırlı sayıda bulunan kaynaklar gerektirebilir. Bu nedenle, oynatıcıya artık ihtiyaç duyulmadığında kaynakları serbest bırakmak için oynatıcınızda release() yöntemini çağırmanız önemlidir.

Oynatıcınız Activity veya Fragment içindeyse oynatıcıyı API düzeyi 24 ve üzeri sürümlerde onStop() yaşam döngüsü yönteminde, API düzeyi 23 ve altı sürümlerde ise onPause() yönteminde serbest bırakın. Service içinde olan bir oyuncuyu onDestroy() içinde serbest bırakabilirsiniz. Yaşam döngüsü yöntemlerinin nasıl uygulanacağına dair bir örnek için Exoplayer codelab'e bakın.

Medya oturumuyla oynatmayı yönetme

Android'de medya oturumları, işlem sınırları genelinde bir medya oynatıcıyla etkileşim kurmak için standartlaştırılmış bir yöntem sunar. Oynatıcınıza bir medya oturumu bağladığınızda medya oynatmanızı harici olarak bildirebilir ve harici kaynaklardan oynatma komutları alabilirsiniz. Örneğin, mobil ve büyük ekranlı cihazlarda sistem medya kontrolleriyle entegrasyon yapabilirsiniz.

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

Kotlin

implementation("androidx.media3:media3-session:1.11.1")

Modern

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

Medya oturumu oluşturma

Bir oynatıcıyı aşağıdaki gibi başlattıktan sonra 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 durumunu MediaSession durumuyla otomatik olarak senkronize eder. Bu, ExoPlayer, CastPlayer veya özel bir uygulama dahil olmak üzere tüm Player uygulamalarıyla çalışır.

Diğer istemcilere kontrol izni verme

İstemci uygulamaları, medya oturumunuzun oynatılmasını kontrol etmek için bir medya kumandası uygulayabilir. Bu istekleri almak için MediaSession oluştururken bir callback nesnesi ayarlayın.

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

Bağlantı kurulduktan sonra kumanda, oturuma oynatma komutları gönderebilir. Oturum, 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, özel oynatma komutları ve oynatma listesini değiştirme isteklerini işlemenize olanak tanır. Bu geri çağırmalar da benzer şekilde bir ControllerInfo nesnesi içerir. Böylece erişim denetimini istek bazında belirleyebilirsiniz.

Arka planda medya oynatılıyor

Uygulamanız ön planda değilken medya oynatmaya devam etmek için (örneğin, kullanıcı uygulamanızı açmamış olsa bile müzik, sesli kitap veya podcast oynatmak için) Player ve MediaSession öğelerinizin bir ön plan hizmetinde kapsüllenmesi gerekir. Media3, bu amaçla MediaSessionService arayüzünü sağlar.

MediaSessionService uygulama

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

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 dosyanızda Service sınıfınızı bir MediaSessionService intent filtresiyle tanımlayın 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, 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ğlanma

Medya oturumunuz, oynatıcı kullanıcı arayüzünüzün bulunduğu Activity veya Fragment öğesinden ayrı bir Service öğesinde olduğundan bunları birbirine bağlamak için MediaController kullanabilirsiniz. Kullanıcı arayüzünüzle Activity veya Fragment öğesinin onStart() yönteminde, MediaSession için bir SessionToken oluşturun, ardından SessionToken kullanarak bir MediaController oluşturun. MediaController oluşturma işlemi eşzamansız olarak gerçekleşir.

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 sayede, oynatmayı kontrol etmek için play() ve pause() gibi aynı yöntemleri kullanabilirsiniz. Diğer bileşenlerde olduğu gibi, MediaController artık gerekli olmadığında MediaController.releaseFuture() yöntemini çağırarak Activity'nin onStop() yaşam döngüsü yönteminde serbest bırakmayı unutmayın.

Bildirim yayınlama

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

İçerik kitaplığınızın reklamını yapma

MediaLibraryService, istemci uygulamalarının uygulamanız tarafından sağlanan medya içeriğine göz atmasına izin vererek MediaSessionService üzerine inşa edilir. İstemci uygulamaları, MediaLibraryService ile etkileşim kurmak için MediaBrowser uygular.

MediaLibraryService uygulamak, MediaSessionService uygulamaya benzer. Tek fark, onGetSession() içinde MediaSession yerine MediaLibrarySession döndürmeniz gerekmesidir. 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 gibi, manifest dosyanızda MediaLibraryService öğesini tanımlayın 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 uygulamanızı tanımasını sağlar.

MediaLibrarySession, içerik kitaplığınızı tek bir kök MediaItem ile ağaç yapısında sunmanıza olanak tanır. Ağaçtaki her MediaItem, istediğiniz sayıda alt MediaItem düğümüne sahip olabilir. İstemci uygulamasının isteğine göre farklı bir kök veya farklı bir ağaç sunabilirsiniz. Örneğin, önerilen medya öğelerinin listesini isteyen bir istemciye döndürdüğünüz ağaç yalnızca kök MediaItem ve tek düzey alt MediaItem düğümleri içerebilir. Farklı bir istemci uygulamasına döndürdüğünüz ağaç ise daha eksiksiz bir içerik kitaplığını temsil edebilir.

MediaLibrarySession oluşturma

MediaLibrarySession, içerik tarama API'leri eklemek için MediaSession API'sini genişletir. MediaSession geri çağırma işleviyle karşılaştırıldığında MediaLibrarySession geri çağırma işlevi aşağıdaki gibi yöntemler ekler:

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

İlgili 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.