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ünü tanımlar. ExoPlayer, Media3'te bu arayüzün varsayılan uygulamasıdır. Çoğu oynatma alanını kapsayan kapsamlı bir özellik dizisi sunduğu ve olası ek kullanım alanlarına göre özelleştirilebildiği için ExoPlayer'ı kullanmanızı öneririz. ExoPlayer ayrıca cihaz ve işletim sistemi parçalanmasını da soyutlayarak kodunuzun tüm Android ekosisteminde tutarlı bir şekilde çalışmasını sağlar. 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, UI ve Ortak modüllerine bir bağımlılık ekleyin:

implementation "androidx.media3:media3-exoplayer:1.3.1"
implementation "androidx.media3:media3-ui:1.3.1"
implementation "androidx.media3:media3-common:1.3.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.3.1 öğesini, 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 şu şekildedir:

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, 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 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, medyayı yüklemeye başlamak ve gerekli kaynakları edinmek için prepare() numaralı telefonu çağırın.

Uygulama ön planda olmadan bu adımları uygulamamalısınız. 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 içindeki bir oyuncu için onCreate() kullanarak hazırlayabilirsiniz.

Oynatıcıyı kontrol etme

Oynatıcı hazırlandıktan sonra, oynatıcıda aşağıdakiler 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 uygun şekilde güncellenir.

Oynatıcıyı serbest bırakın

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

Oynatıcınız Activity veya Fragment içindeyse oynatıcıyı API düzeyi 24 ve sonraki sürümlerde onStop() yaşam döngüsü yönteminde ya da API düzeyi 23 ve altında onPause() yönteminde serbest bırakın. Service içinde olan bir oynatıcıyı onDestroy() ürününde serbest bırakabilirsiniz.

Medya oturumuyla oynatmayı yönetme

Android'de medya oturumları, süreç sınırlarının ötesinde bir medya oynatıcıyla etkileşim kurmak için standartlaştırılmış bir yol sağlar. Oynatıcınıza bir medya oturumu bağlamanız, medya oynatma işlemlerinizin harici olarak reklamını yapmanıza ve harici kaynaklardan oynatma komutları almanıza olanak tanır. Örneğin, mobil cihazlar ve büyük ekranlı cihazlarda sistem medya denetimleri ile entegrasyon sağlayabilirsiniz.

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

implementation "androidx.media3:media3-session:1.3.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 durumunu MediaSession durumuyla otomatik olarak senkronize eder. Bu özellik ExoPlayer, CastPlayer veya özel uygulamalar dahil tüm Player uygulamaları ile uyumludur.

Diğer istemcilere denetim izni ver

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

Bir denetleyici, medya oturumunuza bağlanmak üzereyken onConnect() yöntemi çağrılır. İsteği kabul etmeye veya reddetmeye karar vermek için sağlanan ControllerInfo öğesini kullanabilirsiniz. Media3 Oturumu demo uygulamasında bunun bir örneğini görebilirsiniz.

Bağlandıktan sonra kumanda, oturuma oynatma komutları gönderebilir. Ardından oturum, bu komutları oyuncuya delege eder. 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 listesi değiştirme gibi işlemleri yapmanıza olanak tanır. Bu geri çağırma işlevleri benzer şekilde ControllerInfo nesnesi içerir. Böylece erişim denetimini istek bazında belirleyebilirsiniz.

Arka planda medya oynatma

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

MediaSessionService uygulama

MediaSessionService öğesini genişleten bir sınıf oluşturun ve onCreate() yaşam döngüsü yönteminde MediaSession öğenizi ö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'inizde, MediaSessionService intent filtresine sahip Service sınıfınız ve ön plan hizmetini çalıştırmak için FOREGROUND_SERVICE izni 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 bir MediaSession döndürün veya isteği reddetmek için null değerini 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 öğesinin onStart() yönteminde, MediaSession için bir SessionToken oluşturun, ardından bir MediaController oluşturmak için SessionToken öğesini kullanın. 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ü uyguladığından 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 öğesini (ör. Activity için onStop() yaşam döngüsü yöntemi) MediaController.releaseFuture() çağırarak yayınlamayı unutmayın.

Bildirim yayınlama

Etkin durumdayken bildirim yayınlamak için ön plan hizmetleri gereklidir. MediaSessionService sizin için otomatik olarak MediaNotification biçiminde bir MediaStyle bildirim 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ı tanıtma

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 bir MediaBrowser uygular.

MediaLibraryService uygulamak, MediaSessionService uygulamasına benzer. Tek fark, onGetSession() ürününde MediaSession yerine MediaLibrarySession döndürmeniz gerekir. MediaSession.Callback ile karşılaştırıldığında MediaLibrarySession.Callback, bir tarayıcı istemcisinin kitaplık hizmetiniz tarafından sunulan içerikte gezinmesini sağlayan ek yöntemler içerir.

MediaSessionService işlevine benzer şekilde, manifestinizde MediaLibraryService alanını tanımlayın ve bir ön plan hizmetini ç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 bulunmaktadı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ğaçtaki her MediaItem, herhangi bir 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 arayan bir müşteriye geri döndüğünüzde ağaç yalnızca kök MediaItem ve tek düzeyde alt MediaItem düğümünü içerebilir. Farklı bir istemci uygulamasına döndüğünüz ağaç ise daha kapsamlı bir içerik kitaplığını temsil edebilir.

MediaLibrarySession oluşturuluyor

MediaLibrarySession, içerik tarama API'leri eklemek için MediaSession API'yi genişletir. MediaSession geri çağırmasına kıyasla MediaLibrarySession geri çağırma aşağıdaki gibi yöntemler ekler:

  • onGetLibraryRoot() (müşteriler içerik ağacının kök MediaItem'sini istediğinde kullanılır)
  • onGetChildren() (müşteri, içerik ağacındaki bir MediaItem alt öğelerini istediğinde kullanılır)
  • onGetSearchResult() müşteriler belirli bir sorgu için içerik ağacından arama sonuçları istediğinde

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