Bir uygulama ön planda değilken medyayı oynatmak genellikle istenir. Örneğin, müzik çalarlar genellikle kullanıcı cihazını kilitlediğinde veya başka bir uygulama kullanırken müzik çalmaya devam eder. Media3 kitaplığı, arka planda oynatmayı desteklemenize olanak tanıyan bir dizi arayüz sağlar.
MediaSessionService kullanma
Arka planda oynatmayı etkinleştirmek için Player
ve MediaSession
öğelerini ayrı bir Service içinde bulundurmanız gerekir.
Bu sayede, uygulamanız ön planda olmasa bile cihaz medya sunmaya devam edebilir.

MediaSessionService
, medya oturumunun uygulamanın etkinliğinden ayrı olarak çalışmasına olanak tanırBir oyuncuyu hizmet içinde barındırırken MediaSessionService
kullanmanız gerekir.
Bunu yapmak için MediaSessionService
sınıfını genişleten bir sınıf oluşturun ve medya oturumunuzu bu sınıfın içinde oluşturun.
MediaSessionService
kullanıldığında Google Asistan, sistem medya kontrolleri, çevre birimlerindeki medya düğmeleri veya Wear OS gibi yardımcı cihazlar gibi harici istemciler, uygulamanızın kullanıcı arayüzü etkinliğine hiç erişmeden hizmetinizi keşfedebilir, hizmetinize bağlanabilir ve oynatmayı kontrol edebilir. Hatta aynı anda aynı MediaSessionService
öğesine bağlı birden fazla istemci uygulaması olabilir ve her uygulamanın kendi MediaController
öğesi bulunur.
Hizmet yaşam döngüsünü uygulama
Hizmetinizin iki yaşam döngüsü yöntemini uygulamanız gerekir:
onCreate()
, ilk kumanda bağlanmak üzereyken ve hizmet oluşturulup başlatıldığında çağrılır.Player
veMediaSession
oluşturmak için en iyi yerdir.onDestroy()
, hizmet durdurulurken çağrılır. Oyuncu ve oturum dahil tüm kaynakların serbest bırakılması gerekir.
İsteğe bağlı olarak, kullanıcının uygulamayı son görevlerden kapattığında ne olacağını özelleştirmek için onTaskRemoved(Intent)
değerini geçersiz kılabilirsiniz. Varsayılan olarak, oynatma devam ediyorsa hizmet çalışmaya devam eder, aksi takdirde durdurulur.
Kotlin
class PlaybackService : MediaSessionService() { private var mediaSession: MediaSession? = null // Create your player and media session 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; // Create your Player and MediaSession in the onCreate lifecycle event @Override public void onCreate() { super.onCreate(); ExoPlayer player = new ExoPlayer.Builder(this).build(); mediaSession = new MediaSession.Builder(this, player).build(); } // Remember to release the player and media session in onDestroy @Override public void onDestroy() { mediaSession.getPlayer().release(); mediaSession.release(); mediaSession = null; super.onDestroy(); } }
Arka planda oynatmaya devam etmek yerine, kullanıcı uygulamayı kapattığında hizmeti durdurabilirsiniz:
Kotlin
override fun onTaskRemoved(rootIntent: Intent?) { pauseAllPlayersAndStopSelf() }
Java
@Override public void onTaskRemoved(@Nullable Intent rootIntent) { pauseAllPlayersAndStopSelf(); }
onTaskRemoved
'nın diğer tüm manuel uygulamaları için, oynatmanın devam edip etmediğini ve ön plan hizmetinin başlatılıp başlatılmadığını kontrol etmek üzere isPlaybackOngoing()
kullanabilirsiniz.
Medya oturumuna erişim sağlama
Hizmet oluşturulduğunda oluşturulan medya oturumunuza diğer istemcilerin erişebilmesi için onGetSession()
yöntemini geçersiz kılın.
Kotlin
class PlaybackService : MediaSessionService() { private var mediaSession: MediaSession? = null // [...] lifecycle methods omitted override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaSession? = mediaSession }
Java
public class PlaybackService extends MediaSessionService { private MediaSession mediaSession = null; // [...] lifecycle methods omitted @Override public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) { return mediaSession; } }
Hizmeti manifestte bildirin
Bir uygulamanın oynatma ön plan hizmetini çalıştırmak için FOREGROUND_SERVICE
ve FOREGROUND_SERVICE_MEDIA_PLAYBACK
izinleri gerekir:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
Ayrıca, manifest dosyasında Service
sınıfınızı MediaSessionService
intent filtresi ve mediaPlayback
içeren bir foregroundServiceType
ile birlikte beyan etmeniz gerekir.
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService"/>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
MediaController
kullanarak oynatmayı kontrol etme
Oynatıcı kullanıcı arayüzünüzü içeren Etkinlik veya Parçada, MediaController
kullanarak kullanıcı arayüzü ile medya oturumunuz arasında bir bağlantı oluşturabilirsiniz. Kullanıcı arayüzünüz, oturumdaki oynatıcıya komut göndermek için medya denetleyicisini kullanır. MediaController
oluşturma ve kullanma hakkında ayrıntılı bilgi için MediaController
oluşturma rehberine bakın.
Herkese açık kullanıcı adı MediaController
komutları
MediaSession
, MediaSession.Callback
aracılığıyla kontrol cihazından komut alır. MediaSession
başlatıldığında, MediaSession.Callback
için varsayılan bir uygulama oluşturulur. Bu uygulama, MediaController
öğesinin oynatıcınıza gönderdiği tüm komutları otomatik olarak işler.
Bildirim
MediaSessionService
, çoğu durumda işe yarayacak bir MediaNotification
oluşturur. Yayınlanan bildirim, varsayılan olarak medya oturumunuzdaki en son bilgilerle güncellenen ve oynatma kontrollerini gösteren bir MediaStyle
bildirimidir. MediaNotification
, oturumunuzu bilir ve aynı oturuma bağlı diğer uygulamalarda oynatmayı kontrol etmek için kullanılabilir.
Örneğin, MediaSessionService
kullanan bir müzik akışı uygulaması, MediaSession
yapılandırmanıza göre oynatma kontrollerinin yanı sıra, çalınan mevcut medya öğesinin başlığını, sanatçısını ve albüm kapağını gösteren bir MediaNotification
oluşturur.
Gerekli meta veriler medyada sağlanabilir veya aşağıdaki snippet'te gösterildiği gibi medya öğesinin bir parçası olarak beyan edilebilir:
Kotlin
val mediaItem = MediaItem.Builder() .setMediaId("media-1") .setUri(mediaUri) .setMediaMetadata( MediaMetadata.Builder() .setArtist("David Bowie") .setTitle("Heroes") .setArtworkUri(artworkUri) .build() ) .build() mediaController.setMediaItem(mediaItem) mediaController.prepare() mediaController.play()
Java
MediaItem mediaItem = new MediaItem.Builder() .setMediaId("media-1") .setUri(mediaUri) .setMediaMetadata( new MediaMetadata.Builder() .setArtist("David Bowie") .setTitle("Heroes") .setArtworkUri(artworkUri) .build()) .build(); mediaController.setMediaItem(mediaItem); mediaController.prepare(); mediaController.play();
Bildirim yaşam döngüsü
Bildirim, oynatma listesinde Player
MediaItem
örneği olduğunda oluşturulur.
Tüm bildirim güncellemeleri, Player
ve MediaSession
durumuna göre otomatik olarak gerçekleşir.
Ön plan hizmeti çalışırken bildirim kaldırılamaz. Bildirimi hemen kaldırmak için Player.release()
numaralı telefonu aramanız veya Player.clearMediaItems()
simgesini kullanarak oynatma listesini temizlemeniz gerekir.
Oynatıcı, 10 dakikadan uzun süre duraklatılır, durdurulur veya başarısız olursa ve kullanıcı etkileşimi olmazsa hizmet, sistem tarafından yok edilebilmesi için otomatik olarak ön plan hizmeti durumundan çıkarılır. Kullanıcının hizmet yaşam döngüsünü yeniden başlatmasına ve daha sonra oynatmaya devam etmesine izin vermek için oynatmaya devam etme özelliğini uygulayabilirsiniz.
Bildirim özelleştirme
Şu anda oynatılan öğeyle ilgili meta veriler, MediaItem.MediaMetadata
değiştirilerek özelleştirilebilir. Mevcut bir öğenin meta verilerini güncellemek istiyorsanız Player.replaceMediaItem
simgesini kullanarak oynatmayı kesintiye uğratmadan meta verileri güncelleyebilirsiniz.
Android medya kontrolleri için özel medya düğmesi tercihleri ayarlayarak bildirimde gösterilen düğmelerden bazılarını da özelleştirebilirsiniz. Android'de medya kontrollerini özelleştirme hakkında daha fazla bilgi edinin.
Bildirimi daha da özelleştirmek için DefaultMediaNotificationProvider.Builder
ile MediaNotification.Provider
oluşturun veya sağlayıcı arayüzünün özel bir uygulamasını oluşturun. setMediaNotificationProvider
ile sağlayıcınızı MediaSessionService
'ya ekleyin.
Oynatmaya devam etme
MediaSessionService
sonlandırıldıktan ve cihaz yeniden başlatıldıktan sonra bile, kullanıcılara hizmeti yeniden başlatıp oynatmaya kaldıkları yerden devam etmelerini sağlamak için oynatmaya devam etme seçeneği sunulabilir. Oynatmaya devam etme özelliği varsayılan olarak devre dışıdır. Bu nedenle, hizmetiniz çalışmıyorken kullanıcı oynatmaya devam edemez. Bu özelliği etkinleştirmek için bir medya düğmesi alıcısı bildirmeniz ve onPlaybackResumption
yöntemini uygulamanız gerekir.
Media3 medya düğmesi alıcısını bildirme
Manifestinizde MediaButtonReceiver
öğesini beyan ederek başlayın:
<receiver android:name="androidx.media3.session.MediaButtonReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
Oynatmayı devam ettirme geri çağırmasını uygulama
Oynatmaya devam etme isteği bir Bluetooth cihazı veya Android Sistem Kullanıcı Arayüzü devam ettirme özelliği tarafından gönderildiğinde onPlaybackResumption()
geri çağırma yöntemi çağrılır.
Kotlin
override fun onPlaybackResumption( mediaSession: MediaSession, controller: ControllerInfo ): ListenableFuture<MediaItemsWithStartPosition> { val settable = SettableFuture.create<MediaItemsWithStartPosition>() scope.launch { // Your app is responsible for storing the playlist, metadata (like title // and artwork) of the current item and the start position to use here. val resumptionPlaylist = restorePlaylist() settable.set(resumptionPlaylist) } return settable }
Java
@Override public ListenableFuture<MediaItemsWithStartPosition> onPlaybackResumption( MediaSession mediaSession, ControllerInfo controller ) { SettableFuture<MediaItemsWithStartPosition> settableFuture = SettableFuture.create(); settableFuture.addListener(() -> { // Your app is responsible for storing the playlist, metadata (like title // and artwork) of the current item and the start position to use here. MediaItemsWithStartPosition resumptionPlaylist = restorePlaylist(); settableFuture.set(resumptionPlaylist); }, MoreExecutors.directExecutor()); return settableFuture; }
Oynatma hızı, tekrar modu veya karıştırma modu gibi başka parametreler sakladıysanız onPlaybackResumption()
, geri çağırma tamamlandığında Media3 oynatıcıyı hazırlayıp oynatmaya başlamadan önce oynatıcıyı bu parametrelerle yapılandırmak için iyi bir yerdir.
Bu yöntem, cihaz yeniden başlatıldıktan sonra Android sistem kullanıcı arayüzü devam ettirme bildirimini oluşturmak için önyükleme sırasında çağrılır. Zengin bildirim için, ağ erişimi henüz kullanılamıyor olabileceğinden mevcut öğenin MediaMetadata
gibi alanlarını title
ve artworkData
veya artworkUri
yerel olarak kullanılabilen değerlerle doldurmanız önerilir. Oynatma konumunun devam ettirileceğini belirtmek için MediaMetadata.extras
öğesine MediaConstants.EXTRAS_KEY_COMPLETION_STATUS
ve MediaConstants.EXTRAS_KEY_COMPLETION_PERCENTAGE
simgelerini de ekleyebilirsiniz.
Gelişmiş kumanda yapılandırması ve geriye dönük uyumluluk
Sık karşılaşılan bir senaryo, oynatmayı kontrol etmek ve oynatma listesini göstermek için uygulama kullanıcı arayüzünde MediaController
kullanmaktır. Aynı zamanda oturum; Android'deki medya kontrolleri, mobil cihazlarda veya TV'de Asistan, kol saatlerinde Wear OS ve arabalarda Android Auto gibi harici istemcilere de sunulur. Media3 oturum demo uygulaması bu tür bir senaryoyu uygulayan bir uygulamaya örnektir.
Bu harici istemciler, eski AndroidX kitaplığının MediaControllerCompat
veya Android platformunun android.media.session.MediaController
gibi API'leri kullanabilir. Media3, eski kitaplıkla tamamen geriye dönük uyumludur ve Android platform API'siyle birlikte çalışabilir.
Medya bildirimi denetleyicisini kullanma
Bu eski ve platform denetleyicilerinin aynı durumu paylaştığını ve görünürlüğün denetleyiciye göre özelleştirilemediğini (örneğin, kullanılabilir PlaybackState.getActions()
ve PlaybackState.getCustomActions()
) anlamak önemlidir. Bu eski ve platform denetleyicileriyle uyumluluk için platform medya oturumunda ayarlanan durumu yapılandırmak üzere medya bildirimi denetleyicisini kullanabilirsiniz.
Örneğin, bir uygulama, kullanılabilir komutları ve medya düğmesi tercihlerini özellikle platform oturumu için aşağıdaki şekilde ayarlamak üzere MediaSession.Callback.onConnect()
uygulamasını sağlayabilir:
Kotlin
override fun onConnect( session: MediaSession, controller: MediaSession.ControllerInfo ): ConnectionResult { if (session.isMediaNotificationController(controller)) { val sessionCommands = ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon() .add(customCommandSeekBackward) .add(customCommandSeekForward) .build() val playerCommands = ConnectionResult.DEFAULT_PLAYER_COMMANDS.buildUpon() .remove(COMMAND_SEEK_TO_PREVIOUS) .remove(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM) .remove(COMMAND_SEEK_TO_NEXT) .remove(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM) .build() // Custom button preferences and commands to configure the platform session. return AcceptedResultBuilder(session) .setMediaButtonPreferences( ImmutableList.of( createSeekBackwardButton(customCommandSeekBackward), createSeekForwardButton(customCommandSeekForward)) ) .setAvailablePlayerCommands(playerCommands) .setAvailableSessionCommands(sessionCommands) .build() } // Default commands with default button preferences for all other controllers. return AcceptedResultBuilder(session).build() }
Java
@Override public ConnectionResult onConnect( MediaSession session, MediaSession.ControllerInfo controller) { if (session.isMediaNotificationController(controller)) { SessionCommands sessionCommands = ConnectionResult.DEFAULT_SESSION_COMMANDS .buildUpon() .add(customCommandSeekBackward) .add(customCommandSeekForward) .build(); Player.Commands playerCommands = ConnectionResult.DEFAULT_PLAYER_COMMANDS .buildUpon() .remove(COMMAND_SEEK_TO_PREVIOUS) .remove(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM) .remove(COMMAND_SEEK_TO_NEXT) .remove(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM) .build(); // Custom button preferences and commands to configure the platform session. return new AcceptedResultBuilder(session) .setMediaButtonPreferences( ImmutableList.of( createSeekBackwardButton(customCommandSeekBackward), createSeekForwardButton(customCommandSeekForward))) .setAvailablePlayerCommands(playerCommands) .setAvailableSessionCommands(sessionCommands) .build(); } // Default commands with default button preferences for all other controllers. return new AcceptedResultBuilder(session).build(); }
Android Auto'nun özel komutlar göndermesine izin verme
MediaLibraryService
kullanırken ve mobil uygulamayla Android Auto'yu desteklemek için Android Auto denetleyicisinin uygun komutlara sahip olması gerekir. Aksi takdirde Media3, bu denetleyiciden gelen özel komutları reddeder:
Kotlin
override fun onConnect( session: MediaSession, controller: MediaSession.ControllerInfo ): ConnectionResult { val sessionCommands = ConnectionResult.DEFAULT_SESSION_AND_LIBRARY_COMMANDS.buildUpon() .add(customCommandSeekBackward) .add(customCommandSeekForward) .build() if (session.isMediaNotificationController(controller)) { // [...] See above. } else if (session.isAutoCompanionController(controller)) { // Available session commands to accept incoming custom commands from Auto. return AcceptedResultBuilder(session) .setAvailableSessionCommands(sessionCommands) .build() } // Default commands for all other controllers. return AcceptedResultBuilder(session).build() }
Java
@Override public ConnectionResult onConnect( MediaSession session, MediaSession.ControllerInfo controller) { SessionCommands sessionCommands = ConnectionResult.DEFAULT_SESSION_COMMANDS .buildUpon() .add(customCommandSeekBackward) .add(customCommandSeekForward) .build(); if (session.isMediaNotificationController(controller)) { // [...] See above. } else if (session.isAutoCompanionController(controller)) { // Available commands to accept incoming custom commands from Auto. return new AcceptedResultBuilder(session) .setAvailableSessionCommands(sessionCommands) .build(); } // Default commands for all other controllers. return new AcceptedResultBuilder(session).build(); }
Oturum demo uygulamasında, ayrı bir APK gerektiren Automotive OS desteğini gösteren bir otomotiv modülü bulunur.