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

Jetpack Media3, video ve ses dosyalarının oynatılmasına ilişkin temel işlevleri özetleyen bir Player arayüzü tanımlar. ExoPlayer, bu arayüzün Media3'teki varsayılan uygulamasıdır. Çoğu oynatma durumunu kapsayan kapsamlı bir özellik kümesi sunduğu ve olası diğer kullanım alanlarını ele alacak şekilde özelleştirilebilen ExoPlayer'ı kullanmanızı öneririz. ExoPlayer ayrıca cihaz ve işletim sistemi parçalanmasını soyutlayarak kodunuzun tüm Android ekosisteminde tutarlı bir şekilde çalışmasını sağlar. ExoPlayer şunları içerir:

Bu sayfada bir oynatma uygulaması oluşturmanın önemli adımlarından bazıları açıklanmaktadır. Daha fazla ayrıntı için Media3 ExoPlayer'daki tam rehberlerimize gidebilirsiniz.

Başlarken

Başlamak için Jetpack Media3'ün ExoPlayer, Kullanıcı Arayüzü ve Common modüllerine 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 Media3'ten ek modüllere de ihtiyacınız olabilir.

1.3.1 öğesini tercih ettiğiniz kitaplık sürümüyle değiştirmeyi unutmayın. En son sürümü görmek için sürüm notlarına bakabilirsiniz.

Medya oynatıcı oluşturma

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

ExoPlayer Oluşturma

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

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 ürününün onCreate() yaşam döngüsü yöntemini kullanarak oluşturabilirsiniz.

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

Oynatıcıyı hazırlama

Oynatma listesine setMediaItem() ve addMediaItem() gibi yöntemlerle medya öğeleri ekleyin. Ardından medya yüklemeye başlamak ve gerekli kaynakları almak için prepare() numaralı telefonu arayın.

Bu adımları, uygulama ön planda olmadan gerçekleştirmemeniz gerekir. Oynatıcınız Activity veya Fragment kategorisindeyse bu, oynatıcıyı API düzeyi 24 ve sonraki sürümler için onStart() yaşam döngüsü yöntemine ya da API düzeyi 23 ve önceki sürümlerde onResume() yaşam döngüsü yöntemine hazırlama anlamına gelir. Service içinde yer alan bir oyuncu için bunu onCreate() içinde hazırlayabilirsiniz.

Oynatıcıyı kontrol etme

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

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

Oynatıcıyı bırakma

Oynatma için video kod çözücüler gibi sınırlı miktarda kaynaklar gerekebilir. Bu nedenle, oynatıcıya artık ihtiyaç duyulmadığında kaynak açmak için oynatıcınızda release() yöntemini çağırmanız önemlidir.

Oynatıcınız Activity veya Fragment ise oynatıcıyı API düzeyi 24 ve üzeri sürümlerdeki onStop() yaşam döngüsü yönteminde ya da API düzeyi 23 ve önceki sürümlerde onPause() yöntemini kullanarak bırakın. Service içinde yer alan bir oyuncuyu onDestroy() üzerinden yayınlayabilirsiniz.

Medya oturumuyla oynatmayı yönetme

Android'de medya oturumları, medya oynatıcıyla süreç sınırlarının ötesinde etkileşim kurmak için standart bir yol sağlar. Oynatıcınıza bir medya oturumu bağladığınızda medya oynatmanızın reklamını harici olarak yapabilir ve harici kaynaklardan oynatma komutları alabilirsiniz. Örneğin, mobil ve büyük ekranlı cihazlarda sistem medya denetimleriyle entegrasyon yapabilirsiniz.

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 öğesinin durumunu MediaSession ile otomatik olarak senkronize eder. Bu özellik; ExoPlayer, CastPlayer veya özel bir uygulama da dahil olmak üzere tüm Player uygulamalarında çalışır.

Diğer istemcilere kontrol verme

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

Kumanda, medya oturumunuza bağlanmak üzereyken onConnect() yöntemi çağrılır. İsteği kabul etmek veya reddetmek için sağlanan ControllerInfodan yararlanabilirsiniz. Bunun bir örneğini Media3 Oturumu demo uygulamasında görebilirsiniz.

Bağlandıktan sonra kumanda, oturuma oynatma komutları gönderebilir. Daha sonra oturum, bu komutları oyuncuya devreder. 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 şarkı listesini değiştirme isteklerini ele almanıza) olanak tanır. Bu geri çağırma işlevleri 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 (ör. kullanıcı uygulamanız açık değilken bile müzik, sesli kitap veya podcast çalmak) Player ve MediaSession verileriniz bir ön plan hizmetinde kapsüllenmelidir. Media3, bu amaçla MediaSessionService arayüzünü sağlar.

MediaSessionService uygulama

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

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 amaç 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 medya oturumunuza istemci erişimini kontrol etmek için onGetSession() yöntemini geçersiz kılın. Bağlantı isteğini kabul etmek için MediaSession veya isteği reddetmek için null iade edin.

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 bölümünden ayrı bir Service konumunda olduğundan, bunları birbirine bağlamak için MediaController kullanabilirsiniz. Kullanıcı arayüzünüzü kullanarak Activity veya Fragment için onStart() yönteminde MediaSession için bir SessionToken oluşturun, ardından SessionToken kullanarak MediaController oluşturun. MediaController, eşzamansız olarak oluşturulur.

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, MediaController.releaseFuture() yöntemini çağırarak MediaController öğesini artık gerekli olmadığında (ör. Activity için onStop() yaşam döngüsü yöntemi) yayınlamayı 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 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 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 bir MediaSessionService altyapısı üzerine kurulur. İstemci uygulamaları, MediaLibraryService ile etkileşim kurmak için bir MediaBrowser kullanır.

MediaLibraryService uygulamak MediaSessionService uygulamasına benzer, ancak onGetSession() içinde MediaSession yerine bir 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 gezinmesine olanak tanıyan ek yöntemler içerir.

MediaSessionService yönergesine benzer şekilde, manifestinizde MediaLibraryService için bildirimde bulunun ve bir ö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.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 amacıyla eski MediaBrowserService için bir amaç filtresi bulunmaktadır. Ek amaç 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 yayınlamanıza olanak tanır. 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 istemciye döndürdüğünüz ağaç, yalnızca kök MediaItem ve tek bir alt düzey MediaItem düğümlerini 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şturuluyor

MediaLibrarySession, MediaSession API'yi içerik tarama API'leri ekleyecek şekilde genişletir. MediaSession geri çağırma ile karşılaştırıldığında MediaLibrarySession geri çağırma aşağıdaki gibi yöntemler ekler:

  • onGetLibraryRoot() İstemci bir içerik ağacının kök MediaItem kodunu istediğinde
  • onGetChildren() İstemci, içerik ağacındaki bir MediaItem öğesinin alt öğelerini istediğinde
  • onGetSearchResult() İstemci, belirli bir sorgu için içerik ağacından arama sonuçları istediğinde

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