AndroidX Media3 taşıma kılavuzu

Şu anda bağımsız com.google.android.exoplayer2 kitaplığını ve androidx.media kullanan uygulamalar androidx.media3 kitaplığına geçmelidir. Gradle derleme dosyalarını, Java ve Kotlin kaynak dosyalarını ve XML düzen dosyalarını ExoPlayer 2.19.1'dan AndroidX Media3 1.1.1'e taşımak için taşıma komut dosyasını kullanın.

Genel Bakış

Taşıma işleminden önce, yeni API'lerin avantajları, taşınacak API'ler ve uygulamanızın projesinin karşılaması gereken ön koşullar hakkında daha fazla bilgi edinmek için aşağıdaki bölümleri inceleyin.

Neden Jetpack Media3'e geçmelisiniz?

  • ExoPlayer'ın yeni adresi burasıdır. com.google.android.exoplayer2 ise kullanımdan kaldırılmıştır.
  • MediaBrowser/MediaController ile bileşenler/işlemler genelinde Player API'ye erişin.
  • MediaSession ve MediaController API'nin genişletilmiş özelliklerini kullanın.
  • Ayrıntılı erişim denetimi ile oynatma özelliklerini bildirme
  • MediaSessionConnector ve PlayerNotificationManager öğelerini kaldırarak uygulamanızı basitleştirin.
  • media-compat istemci API'leriyle geriye dönük uyumlu (MediaBrowserCompat/MediaControllerCompat/MediaMetadataCompat)

AndroidX Media3'e taşınacak medya API'leri

  • ExoPlayer ve uzantıları
    Bu, kullanımdan kaldırılan mediasession modülü hariç eski ExoPlayer projesinin tüm modüllerini içerir. com.google.android.exoplayer2 içindeki paketlere bağlı olan uygulamalar veya modüller, taşıma komut dosyasıyla taşınabilir.
  • MediaSessionConnector (androidx.media:media:1.4.3+'nin androidx.media.* paketlerine bağlı olarak)
    MediaSessionConnector öğesini kaldırın ve bunun yerine androidx.media3.session.MediaSession kullanın.
  • MediaBrowserServiceCompat (androidx.media:media:1.4.3+'nin androidx.media.* paketlerine bağlı olarak)
    androidx.media.MediaBrowserServiceCompat alt sınıflarını androidx.media3.session.MediaLibraryService sınıfına ve MediaBrowserCompat.MediaItem kullanan kodu androidx.media3.common.MediaItem sınıfına taşıyın.
  • MediaBrowserCompat (androidx.media:media:1.4.3+ paketlerine bağlı olarak)
    androidx.media3.common.MediaItem ile androidx.media3.session.MediaBrowser kullanmak için MediaBrowserCompat veya MediaControllerCompat kullanarak istemci kodunu taşıyın.android.support.v4.media.*

Ön koşullar

  1. Projenizin kaynak denetimi altında olduğundan emin olun

    Komut dosyası kullanan taşıma araçları tarafından uygulanan değişiklikleri kolayca geri alabildiğinizden emin olun. Projeniz henüz kaynak denetimi altında değilse şimdi başlamak için iyi bir zaman. Herhangi bir nedenle bunu yapmak istemiyorsanız taşıma işlemine başlamadan önce projenizin yedek kopyasını oluşturun.

  2. Uygulamanızı güncelleme

    • Projenizi ExoPlayer kitaplığının en son sürümünü kullanacak şekilde güncellemenizi ve desteği sonlandırılan yöntemlere yapılan tüm çağrıları kaldırmanızı öneririz. Taşıma işlemi için komut dosyasını kullanmayı planlıyorsanız güncelleme yaptığınız sürümü, komut dosyası tarafından işlenen sürümle eşleştirmeniz gerekir.

    • Uygulamanızın compileSdkVersion değerini en az 32'ye yükseltin.

    • Gradle ve Android Studio Gradle eklentisini yukarıdaki güncellenmiş bağımlılıklarla çalışan yeni bir sürüme yükseltin. Örneğin:

      • Android Gradle eklentisi sürümü: 7.1.0
      • Gradle sürümü: 7.4
    • Yıldız (*) kullanan tüm joker karakterli içe aktarma ifadelerini değiştirin ve tam nitelikli içe aktarma ifadeleri kullanın: Joker karakterli içe aktarma ifadelerini silin ve tam nitelikli ifadeleri içe aktarmak için Android Studio'yu kullanın (F2 - Alt/Enter, F2 - Alt/Enter, ...).

    • com.google.android.exoplayer2.PlayerView'den com.google.android.exoplayer2.StyledPlayerView'ye geçiş yapın. AndroidX Media3'te com.google.android.exoplayer2.PlayerView'e eşdeğer bir öğe olmadığı için bu gereklidir.

ExoPlayer'ı komut dosyası desteğiyle taşıma

Komut dosyası, com.google.android.exoplayer2 paketinden androidx.media3 altındaki yeni paket ve modül yapısına geçişi kolaylaştırır. Komut dosyası, projenizde bazı doğrulama kontrolleri uygular ve doğrulama başarısız olursa uyarılar yazdırır. Aksi takdirde, Java veya Kotlin ile yazılmış bir Android Gradle projesinin kaynaklarında yeniden adlandırılan sınıfların ve paketlerin eşlemelerini uygular.

usage: ./media3-migration.sh [-p|-c|-d|-v]|[-m|-l [-x <path>] [-f] PROJECT_ROOT]
 PROJECT_ROOT: path to your project root (location of 'gradlew')
 -p: list package mappings and then exit
 -c: list class mappings (precedence over package mappings) and then exit
 -d: list dependency mappings and then exit
 -l: list files that will be considered for rewrite and then exit
 -x: exclude the path from the list of file to be changed: 'app/src/test'
 -m: migrate packages, classes and dependencies to AndroidX Media3
 -f: force the action even when validation fails
 -v: print the exoplayer2/media3 version strings of this script
 -h, --help: show this help text

Taşıma komut dosyasını kullanma

  1. Uygulamanızı güncellediğiniz sürüme karşılık gelen GitHub'daki ExoPlayer projesinin etiketinden taşıma komut dosyasını indirin:

    curl -o media3-migration.sh \
      "https://raw.githubusercontent.com/google/ExoPlayer/r2.19.1/media3-migration.sh"
    
  2. Komut dosyasını yürütülebilir hale getirin:

    chmod 744 media3-migration.sh
    
  3. Seçenekler hakkında bilgi edinmek için komut dosyasını --help ile çalıştırın.

  4. Taşıma için seçilen dosyaların listesini görmek için komut dosyasını -l ile çalıştırın (uyarılar olmadan listelemeyi zorunlu kılmak için -f kullanın):

    ./media3-migration.sh -l -f /path/to/gradle/project/root
    
  5. Paketleri, sınıfları ve modülleri Media3 ile eşlemek için komut dosyasını -m ile çalıştırın. Komut dosyasını -m seçeneğiyle çalıştırmak, değişiklikleri seçili dosyalara uygular.

    • Değişiklik yapmadan doğrulama hatasında durma
    ./media3-migration.sh -m /path/to/gradle/project/root
    
    • Zorunlu yürütme

    Komut dosyası ön koşulların ihlal edildiğini tespit ederse taşıma işlemi -f işaretiyle zorunlu kılınabilir:

    ./media3-migration.sh -m -f /path/to/gradle/project/root
    
 # list files selected for migration when excluding paths
 ./media3-migration.sh -l -x "app/src/test/" -x "service/" /path/to/project/root
 # migrate the selected files
 ./media3-migration.sh -m -x "app/src/test/" -x "service/" /path/to/project/root

Komut dosyasını -m seçeneğiyle çalıştırdıktan sonra aşağıdaki manuel adımları tamamlayın:

  1. Komut dosyasının kodunuzu nasıl değiştirdiğini kontrol edin: Bir diff aracı kullanın ve olası sorunları düzeltin (komut dosyasının -f seçeneğini geçmeden ortaya çıkan genel bir sorunu olduğunu düşünüyorsanız hata bildirin).
  2. Projeyi derleyin: ./gradlew clean build komutunu kullanın veya Android Studio'da Dosya > Projeyi Gradle Dosyalarıyla Senkronize Et'i, ardından Derle > Projeyi temizle'yi ve sonra Derle > Projeyi yeniden derle'yi seçin (derlemenizi Android Studio'nun "Derleme - Derleme Çıkışı" sekmesinden izleyin).

Önerilen takip adımları:

  1. Kararsız API'lerin kullanımıyla ilgili hatalar için etkinleştirme sorununu çözün.
  2. Desteği sonlandırılan API çağrılarını değiştirme: Önerilen alternatif API'yi kullanın. Android Studio'da fare imlecini uyarının üzerine getirin ve belirli bir çağrı yerine ne kullanacağınızı öğrenmek için desteği sonlandırılan simgenin JavaDoc'una bakın.
  3. İçe aktarma ifadelerini sıralayın: Projeyi Android Studio'da açın, ardından proje görüntüleyicide bir paket klasörü düğümünü sağ tıklayın ve değiştirilen kaynak dosyaları içeren paketlerde İçe aktarmaları optimize et'i seçin.

MediaSessionConnector yerine androidx.media3.session.MediaSession koyun

Eski MediaSessionCompat dünyasında MediaSessionConnector, oynatıcının durumunu oturumun durumuyla senkronize etmekten ve uygun oynatıcı yöntemlerine yetki verilmesi gereken denetleyicilerden komut almaktan sorumluydu. AndroidX Media3 ile bu işlem, bağlayıcıya gerek kalmadan doğrudan MediaSession tarafından yapılır.

  1. MediaSessionConnector ile ilgili tüm referansları ve kullanımları kaldırın: ExoPlayer sınıflarını ve paketlerini taşımak için otomatik komut dosyasını kullandıysanız komut dosyası, kodunuzu çözümlenemeyenMediaSessionConnector ile ilgili derlenemez bir durumda bırakmış olabilir. Android Studio, uygulamayı derlemeye veya başlatmaya çalıştığınızda bozuk kodu gösterir.

  2. Bağımlılıklarınızı tuttuğunuz build.gradle dosyasına AndroidX Media3 oturum modülüne bir uygulama bağımlılığı ekleyin ve eski bağımlılığı kaldırın:

    implementation "androidx.media3:media3-session:1.11.1"
    
  3. MediaSessionCompat değerini androidx.media3.session.MediaSession ile değiştirin.

  4. Eski MediaSessionCompat oluşturduğunuz kod sitesinde androidx.media3.session.MediaSession.Builder kullanarak MediaSession oluşturun. Oturum oluşturucuyu oluşturmak için oynatıcıyı iletin.

    Kotlin

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

    Java

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

  5. Uygulamanızın gerektirdiği şekilde MySessionCallback yöntemini uygulayın. Bu adım isteğe bağlıdır. Kumandaların oynatıcıya medya öğeleri eklemesine izin vermek istiyorsanız MediaSession.Callback.onAddMediaItems() yöntemini uygulayın. Geriye dönük uyumlu bir şekilde oynatmak için oynatıcıya medya öğeleri ekleyen çeşitli güncel ve eski API yöntemleri sunar. Buna Media3 denetleyicisinin MediaController.set/addMediaItems() yöntemleri ve eski API'nin TransportControls.prepareFrom*/playFrom* yöntemleri dahildir. onAddMediaItems için örnek bir uygulamayı oturum demo uygulamasının PlaybackService bölümünde bulabilirsiniz.

  6. Taşıma işleminden önce oturumunuzu imha ettiğiniz kod sitesinde medya oturumunu serbest bırakın:

    Kotlin

    mediaSession?.run {
      player.release()
      release()
      mediaSession = null
    }

    Java

    if (mediaSession != null) {
      mediaSession.getPlayer().release();
      mediaSession.release();
      mediaSession = null;
    }

Media3'te MediaSessionConnector işlevi

Aşağıdaki tabloda, daha önce MediaSessionConnector içinde uygulanan işlevleri işleyen Media3 API'leri gösterilmektedir.

MediaSessionConnectorAndroidX Media3
CustomActionProvider MediaSession.Callback.onCustomCommand()/ MediaSession.setMediaButtonPreferences()
PlaybackPreparer MediaSession.Callback.onAddMediaItems() (prepare() dahili olarak çağrılır)
QueueNavigator ForwardingSimpleBasePlayer
QueueEditor MediaSession.Callback.onAddMediaItems()
RatingCallback MediaSession.Callback.onSetRating()
PlayerNotificationManager DefaultMediaNotificationProvider/ MediaNotification.Provider

MediaBrowserService ürününü MediaLibraryService ürününe taşıma

AndroidX Media3, MediaBrowserServiceCompat yerine MediaLibraryService sınıfını kullanıma sunar. MediaLibraryService ve üst sınıfı MediaSessionService için JavaDoc, API'ye ve hizmetin eşzamansız programlama modeline iyi bir giriş sağlar.

MediaLibraryService, MediaBrowserService ile geriye dönük uyumludur. MediaBrowserCompat veya MediaControllerCompat kullanan bir istemci uygulaması, MediaLibraryService'ye bağlanırken kod değişikliği olmadan çalışmaya devam eder. Uygulamanızın MediaLibraryService mı yoksa eski MediaBrowserServiceCompat mı kullandığı istemci için şeffaftır.

Hizmet, etkinlik ve harici uygulamaları içeren uygulama bileşeni diyagramı.
Şekil 1: Medya uygulaması bileşenine genel bakış
  1. Geriye dönük uyumluluğun çalışması için AndroidManifest.xml içinde hizmetinizle her iki hizmet arayüzünü de kaydetmeniz gerekir. Bu sayede istemci, hizmetinizi gerekli hizmet arayüzüne göre bulur:

    <service android:name=".MusicService" android:exported="true">
        <intent-filter>
            <action android:name="androidx.media3.session.MediaLibraryService"/>
            <action android:name="android.media.browse.MediaBrowserService" />
        </intent-filter>
    </service>
    
  2. Bağımlılıklarınızı yönettiğiniz build.gradle dosyasında, AndroidX Media3 oturum modülüne bir uygulama bağımlılığı ekleyin ve eski bağımlılığı kaldırın:

    implementation "androidx.media3:media3-session:1.11.1"
    
  3. Hizmetinizi MediaBrowserService yerine MediaLibraryService'den devralacak şekilde değiştirin Daha önce de belirtildiği gibi MediaLibraryService, eski MediaBrowserService ile uyumludur. Bu nedenle, hizmetin istemcilere sunduğu daha geniş API hâlâ aynıdır. Bu nedenle, bir uygulamanın MediaBrowserService uygulamasını uygulamak için gereken mantığın çoğunu koruması ve yeni MediaLibraryService için uyarlaması muhtemeldir.

    Eski MediaBrowserServiceCompat ile karşılaştırıldığında temel farklar şunlardır:

    • Hizmet yaşam döngüsü yöntemlerini uygulayın: Hizmetin kendisinde geçersiz kılınması gereken yöntemler onCreate/onDestroy şeklindedir. Bu yöntemlerde uygulama; kitaplık oturumunu, oynatıcıyı ve diğer kaynakları ayırır/serbest bırakır. Uygulamanın, standart hizmet yaşam döngüsü yöntemlerine ek olarak onCreate içinde oluşturulan MediaLibrarySession değerini döndürmek için onGetSession(MediaSession.ControllerInfo) değerini geçersiz kılması gerekir.

    • MediaLibraryService.MediaLibrarySessionCallback'i uygulama: Oturum oluşturmak için gerçek alan adı API yöntemlerini uygulayan bir MediaLibraryService.MediaLibrarySessionCallback gerekir. Bu nedenle, eski hizmetin API yöntemlerini geçersiz kılmak yerine MediaLibrarySession.Callback yöntemlerini geçersiz kılacaksınız.

      Geri çağırma işlevi daha sonra MediaLibrarySession oluşturmak için kullanılır:

      Kotlin

      mediaLibrarySession = MediaLibrarySession.Builder(context, player, MySessionCallback()).build()

      Java

      mediaLibrarySession =
          new MediaLibrarySession.Builder(context, player, new MySessionCallback()).build();

      API belgelerinde MediaLibrarySessionCallback'in tam API'sini bulun.

    • MediaSession.Callback.onAddMediaItems()'i uygulama: Geri çağırma işlevi onAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>), geriye dönük uyumlu bir şekilde oynatmak üzere oynatıcıya medya öğeleri ekleyen çeşitli mevcut ve eski API yöntemlerini sunar. Buna Media3 denetleyicisinin MediaController.set/addMediaItems() yöntemleri ve eski API'nin TransportControls.prepareFrom*/playFrom* yöntemleri dahildir. Geri çağırmanın örnek bir uygulamasını oturum demo uygulamasının PlaybackService bölümünde bulabilirsiniz.

    • AndroidX Media3, MediaBrowserCompat.MediaItem ve MediaMetadataCompat yerine androidx.media3.common.MediaItem kullanıyor. Kodunuzun eski sınıflara bağlı kısımları buna göre değiştirilmeli veya Media3 MediaItem ile eşlenmelidir.

    • MediaBrowserServiceCompat'nin ayrılabilir Result yaklaşımının aksine, genel eşzamansız programlama modeli Futures olarak değiştirildi. Hizmet uygulamanız, bir sonucu ayırmak yerine eşzamansız bir ListenableFuture döndürebilir veya doğrudan bir değer döndürmek için anında Future döndürebilir.

PlayerNotificationManager'ı kaldırma

MediaLibraryService, medya bildirimlerini otomatik olarak destekler ve MediaLibraryService veya MediaSessionService kullanılırken PlayerNotificationManager kaldırılabilir.

Uygulamalar, onCreate() içinde DefaultMediaNotificationProvider yerine geçecek özel bir MediaNotification.Provider ayarlayarak bildirimi özelleştirebilir. Ardından MediaLibraryService, hizmeti gerektiği gibi ön planda başlatır.

Uygulama, MediaLibraryService.updateNotification() yöntemini geçersiz kılarak bildirim yayınlama ve gerektiğinde ön planda hizmeti başlatma/durdurma işlemlerinin tüm sorumluluğunu üstlenebilir.

MediaBrowser kullanarak istemci kodunu taşıma

AndroidX Media3 ile MediaBrowser, MediaController/Player arayüzlerini uygular ve medya kitaplığına göz atmanın yanı sıra medya oynatmayı kontrol etmek için kullanılabilir. Eski dünyada MediaBrowserCompat ve MediaControllerCompat oluşturmanız gerekiyorduysa Media3'te yalnızca MediaBrowser kullanarak aynı işlemi yapabilirsiniz.

MediaBrowser oluşturulabilir ve hizmete bağlantının kurulması beklenebilir:

Kotlin

scope.launch {
  val sessionToken = SessionToken(context, ComponentName(context, "MusicService"))
  browser =
    MediaBrowser.Builder(context, sessionToken)
      .setListener(BrowserListener())
      .buildAsync()
      .await()
}

Java

SessionToken sessionToken =
    new SessionToken(context, new ComponentName(context, "MusicService"));
ListenableFuture<MediaBrowser> browserFuture =
    new MediaBrowser.Builder(context, sessionToken)
        .setListener(new BrowserListener())
        .buildAsync();

Arka planda oynatmayı kontrol etmek için nasıl MediaController oluşturacağınızı öğrenmek istiyorsanız Medya oturumunda oynatmayı kontrol etme başlıklı makaleyi inceleyin.

Sonraki adımlar ve temizleme

Kararsız API hataları

Media3'e geçtikten sonra, kararsız API kullanımlarıyla ilgili lint hataları görebilirsiniz. Bu API'lerin kullanımı güvenlidir ve lint hataları, yeni ikili program uyumluluk garantilerimizin bir yan ürünüdür. Katı ikili uyumluluğa ihtiyacınız yoksa bu hatalar @OptIn ek açıklamasıyla güvenli bir şekilde gizlenebilir.

Arka plan

ExoPlayer v1 veya v2, sonraki sürümler arasında kitaplığın ikili uyumluluğu hakkında kesin garantiler sağlamaz. ExoPlayer API yüzeyi, uygulamaların oynatmanın neredeyse her yönünü özelleştirmesine olanak tanımak için tasarım gereği çok geniştir. ExoPlayer'ın sonraki sürümlerinde zaman zaman sembollerin yeniden adlandırılması veya başka zarar veren değişiklikler (ör. arayüzlerde yeni zorunlu yöntemler) yapılıyordu. Çoğu durumda bu sorunlar, geliştiricilere kullanımlarını taşıma süresi tanımak için eski sembolün birkaç sürüm boyunca desteğini sonlandırmanın yanı sıra yeni sembolün kullanıma sunulmasıyla azaltıldı ancak bu her zaman mümkün olmadı.

Bu zarar veren değişiklikler, ExoPlayer v1 ve v2 kitaplıklarının kullanıcıları için iki soruna yol açtı:

  1. ExoPlayer sürümüne yükseltme yapılması, kodun derlenmesinin durmasına neden olabilir.
  2. Hem doğrudan hem de bir ara kitaplık aracılığıyla ExoPlayer'a bağlı olan bir uygulamanın, her iki bağımlılığın da aynı sürümde olduğundan emin olması gerekiyordu. Aksi takdirde, ikili program uyumsuzlukları çalışma zamanı kilitlenmelerine neden olabiliyordu.

Media3'teki iyileştirmeler

Media3, API yüzeyinin bir alt kümesi için ikili program uyumluluğunu garanti eder. İkili program uyumluluğunu garanti etmeyen bölümler @UnstableApi ile işaretlenmiştir. Bu ayrımı netleştirmek için kararsız API sembollerinin kullanımları, @OptIn ile ek açıklama eklenmediği sürece lint hatası oluşturur.

ExoPlayer v2'den Media3'e geçiş yaptıktan sonra çok sayıda kararsız API lint hatası görebilirsiniz. Bu durum, Media3'ün ExoPlayer v2'den "daha az kararlı" olduğu izlenimini verebilir. Böyle bir durum söz konusu değildir. Media3 API'nin "kararsız" bölümleri, ExoPlayer v2 API yüzeyinin tamamı ile aynı kararlılık düzeyine sahiptir. Kararlı Media3 API yüzeyinin garantileri ExoPlayer v2'de hiç mevcut değildir. Aradaki tek fark, lint hatasının artık farklı kararlılık seviyeleri konusunda sizi uyarmasıdır.

Kararsız API lint hatalarını işleme

Kararsız API'lerin Java ve Kotlin kullanımlarına @OptIn ile ek açıklama ekleme hakkında ayrıntılı bilgi için bu lint hatalarıyla ilgili sorun giderme bölümüne bakın.

Kullanımdan Kaldırılmış API'ler

Desteği sonlandırılmış API'lere yapılan çağrıların Android Studio'da üstü çizili olduğunu fark edebilirsiniz. Bu tür çağrıları uygun alternatifle değiştirmenizi öneririz. Bunun yerine hangi API'nin kullanılacağını belirten JavaDoc'u görmek için fareyle simgenin üzerine gelin.

Ekran görüntüsü: Desteği sonlandırılan yöntemin alternatifiyle JavaDoc'un nasıl gösterileceği
Şekil 3: Android Studio'daki JavaDoc ipucu, desteği sonlandırılan tüm simgeler için bir alternatif önerir.

Kod örnekleri ve demo uygulamalar