ऐसा अक्सर होता है, जब ऐप्लिकेशन फ़ोरग्राउंड में न होने पर भी मीडिया चलाया जाता है. उदाहरण के लिए, आम तौर पर कोई म्यूज़िक प्लेयर, डिवाइस लॉक होने या किसी दूसरे ऐप्लिकेशन का इस्तेमाल करने के दौरान भी संगीत चलाता रहता है. Media3 लाइब्रेरी, इंटरफ़ेस की एक सीरीज़ उपलब्ध कराती है. इससे बैकग्राउंड में कॉन्टेंट चलाने की सुविधा को चालू किया जा सकता है.
MediaSessionService का इस्तेमाल करना
बैकग्राउंड में वीडियो चलाने की सुविधा चालू करने के लिए, आपको Player
और MediaSession
को अलग Service में शामिल करना होगा.
इससे डिवाइस, मीडिया को तब भी ऐक्सेस कर सकता है, जब आपका ऐप्लिकेशन फ़ोरग्राउंड में न हो.

MediaSessionService
की मदद से, मीडिया सेशन को ऐप्लिकेशन की गतिविधि से अलग चलाया जा सकता हैकिसी सेवा में प्लेयर को होस्ट करते समय, आपको MediaSessionService
का इस्तेमाल करना चाहिए.
इसके लिए, MediaSessionService
को बढ़ाने वाली क्लास बनाएं और उसमें अपना मीडिया सेशन बनाएं.
MediaSessionService
का इस्तेमाल करने से, Google Assistant, सिस्टम मीडिया कंट्रोल, पेरिफ़रल डिवाइसों पर मौजूद मीडिया बटन या Wear OS जैसे कंपैनियन डिवाइसों जैसे बाहरी क्लाइंट आपकी सेवा को ढूंढ सकते हैं, उससे कनेक्ट हो सकते हैं, और प्लेबैक को कंट्रोल कर सकते हैं. इसके लिए, उन्हें आपके ऐप्लिकेशन की यूज़र इंटरफ़ेस (यूआई) गतिविधि को ऐक्सेस करने की ज़रूरत नहीं होती. दरअसल, एक ही MediaSessionService
से एक साथ कई क्लाइंट ऐप्लिकेशन कनेक्ट किए जा सकते हैं. हर ऐप्लिकेशन का अपना MediaSessionService
होता है.MediaController
सेवा की लाइफ़साइकल लागू करना
आपको अपनी सेवा के लिए, लाइफ़साइकल के दो तरीके लागू करने होंगे:
onCreate()
को तब कॉल किया जाता है, जब पहला कंट्रोलर कनेक्ट होने वाला होता है और सेवा शुरू हो जाती है.Player
औरMediaSession
बनाने के लिए, यह सबसे अच्छी जगह है.onDestroy()
को तब कॉल किया जाता है, जब सेवा बंद की जा रही हो. सभी संसाधनों को रिलीज़ किया जाना चाहिए. इनमें प्लेयर और सेशन शामिल हैं.
आपके पास onTaskRemoved(Intent)
को बदलने का विकल्प होता है, ताकि यह तय किया जा सके कि जब उपयोगकर्ता, हाल ही के टास्क से ऐप्लिकेशन को खारिज करता है, तो क्या होता है. डिफ़ॉल्ट रूप से, अगर वीडियो चल रहा है, तो सेवा चालू रहती है. अगर वीडियो नहीं चल रहा है, तो सेवा बंद हो जाती है.
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(); } }
बैकग्राउंड में वीडियो चलाने की सुविधा चालू रखने के बजाय, जब उपयोगकर्ता ऐप्लिकेशन को खारिज कर दे, तब सेवा को बंद किया जा सकता है:
Kotlin
override fun onTaskRemoved(rootIntent: Intent?) { pauseAllPlayersAndStopSelf() }
Java
@Override public void onTaskRemoved(@Nullable Intent rootIntent) { pauseAllPlayersAndStopSelf(); }
onTaskRemoved
को मैन्युअल तरीके से लागू करने के लिए, isPlaybackOngoing()
का इस्तेमाल करके यह देखा जा सकता है कि वीडियो अब भी चल रहा है या नहीं. साथ ही, यह भी देखा जा सकता है कि फ़ोरग्राउंड सेवा शुरू हो गई है या नहीं.
मीडिया सेशन का ऐक्सेस देना
onGetSession()
तरीके को बदलें, ताकि अन्य क्लाइंट को आपकी उस मीडिया सेशन का ऐक्सेस मिल सके जिसे सेवा बनाते समय बनाया गया था.
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; } }
मेनिफ़ेस्ट में सेवा की जानकारी देना
किसी ऐप्लिकेशन को फ़ोरग्राउंड सेवा के तौर पर वीडियो चलाने के लिए, FOREGROUND_SERVICE
और FOREGROUND_SERVICE_MEDIA_PLAYBACK
अनुमतियों की ज़रूरत होती है:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
आपको मेनिफ़ेस्ट में अपनी Service
क्लास का एलान भी करना होगा. इसके लिए, MediaSessionService
का इंटेंट फ़िल्टर और foregroundServiceType
का इस्तेमाल करें, जिसमें mediaPlayback
शामिल हो.
<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
का इस्तेमाल करके वीडियो चलाना
अपने प्लेयर यूज़र इंटरफ़ेस (यूआई) वाले ऐप्लिकेशन की गतिविधि या फ़्रैगमेंट में, MediaController
का इस्तेमाल करके यूज़र इंटरफ़ेस (यूआई) और मीडिया सेशन के बीच लिंक बनाया जा सकता है. आपका यूज़र इंटरफ़ेस (यूआई), मीडिया कंट्रोलर का इस्तेमाल करता है. इससे, सेशन में मौजूद प्लेयर को यूज़र इंटरफ़ेस (यूआई) से निर्देश भेजे जा सकते हैं. MediaController
बनाने और इस्तेमाल करने के बारे में ज़्यादा जानने के लिए, MediaController
बनाना गाइड देखें.
MediaController
के निर्देश मैनेज करना
MediaSession
को कंट्रोलर से निर्देश मिलते हैं. ये निर्देश, MediaSession
के MediaSession.Callback
के ज़रिए मिलते हैं. MediaSession
को शुरू करने पर, MediaSession.Callback
का डिफ़ॉल्ट
इस्तेमाल होता है. यह MediaController
से आपके प्लेयर को भेजी गई सभी
कमांड को अपने-आप हैंडल करता है.
सूचना
MediaSessionService
आपके लिए अपने-आप एक MediaNotification
बनाता है. यह ज़्यादातर मामलों में काम करता है. डिफ़ॉल्ट रूप से, पब्लिश की गई सूचना एक MediaStyle
सूचना होती है. यह आपके मीडिया सेशन की नई जानकारी के साथ अपडेट होती रहती है. साथ ही, इसमें प्लेबैक कंट्रोल दिखते हैं. MediaNotification
को आपके सेशन के बारे में पता होता है. इसका इस्तेमाल, उसी सेशन से कनेक्ट किए गए किसी भी अन्य ऐप्लिकेशन के लिए, वीडियो चलाने की सुविधा को कंट्रोल करने के लिए किया जा सकता है.
उदाहरण के लिए, संगीत स्ट्रीम करने वाला कोई ऐप्लिकेशन MediaSessionService
का इस्तेमाल करके, MediaNotification
बनाएगा. इसमें, मौजूदा मीडिया आइटम का टाइटल, कलाकार, और एल्बम आर्ट दिखेगा. साथ ही, इसमें आपके MediaSession
कॉन्फ़िगरेशन के आधार पर प्लेबैक कंट्रोल भी दिखेंगे.
ज़रूरी मेटाडेटा को मीडिया में दिया जा सकता है या मीडिया आइटम के हिस्से के तौर पर इस स्निपेट में बताया गया है:
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();
सूचना की लाइफ़साइकल
सूचना तब बनाई जाती है, जब Player
की प्लेलिस्ट में MediaItem
इंस्टेंस मौजूद हों.
सूचनाओं से जुड़े सभी अपडेट, Player
और MediaSession
की स्थिति के आधार पर अपने-आप होते हैं.
फ़ोरग्राउंड सेवा चालू होने पर, सूचना को हटाया नहीं जा सकता. सूचना को तुरंत हटाने के लिए, आपको Player.release()
पर कॉल करना होगा या Player.clearMediaItems()
का इस्तेमाल करके प्लेलिस्ट मिटानी होगी.
अगर प्लेयर को 10 मिनट से ज़्यादा समय तक रोका जाता है, बंद किया जाता है या वह काम नहीं करता है और इस दौरान उपयोगकर्ता कोई कार्रवाई नहीं करता है, तो सेवा अपने-आप फ़ोरग्राउंड सेवा की स्थिति से बाहर निकल जाती है. इससे सिस्टम इसे बंद कर सकता है. उपयोगकर्ता को सेवा का लाइफ़साइकल फिर से शुरू करने और बाद में वीडियो चलाना जारी रखने की अनुमति देने के लिए, वीडियो चलाने की सुविधा फिर से शुरू की जा सकती है.
सूचना को पसंद के मुताबिक बनाना
फ़िलहाल चल रहे आइटम के मेटाडेटा को MediaItem.MediaMetadata
में बदलाव करके पसंद के मुताबिक बनाया जा सकता है. अगर आपको किसी मौजूदा आइटम का मेटाडेटा अपडेट करना है, तो Player.replaceMediaItem
का इस्तेमाल करके मेटाडेटा अपडेट किया जा सकता है. इससे वीडियो चलाने में कोई रुकावट नहीं आएगी.
Android Media Controls के लिए, मीडिया बटन की पसंद के मुताबिक सेटिंग करके, सूचना में दिखाए गए कुछ बटन को भी पसंद के मुताबिक बनाया जा सकता है. Android मीडिया कंट्रोल को अपनी पसंद के मुताबिक बनाने के बारे में ज़्यादा जानें.
नोटिफ़िकेशन को और ज़्यादा कस्टमाइज़ करने के लिए, DefaultMediaNotificationProvider.Builder
के साथ MediaNotification.Provider
बनाएं या प्रोवाइडर इंटरफ़ेस का कस्टम तरीके से लागू किया गया वर्शन बनाएं. setMediaNotificationProvider
का इस्तेमाल करके, सेवा देने वाली कंपनी को अपने MediaSessionService
में जोड़ें.
प्लेबैक फिर से शुरू करना
MediaSessionService
बंद होने के बाद और डिवाइस को रीबूट करने के बाद भी, उपयोगकर्ताओं को वीडियो फिर से चलाने की सुविधा दी जा सकती है. इससे उपयोगकर्ता, सेवा को फिर से शुरू कर सकते हैं और वीडियो को वहीं से देख सकते हैं जहां उन्होंने छोड़ा था. डिफ़ॉल्ट रूप से, वीडियो फिर से चलाने की सुविधा बंद होती है. इसका मतलब है कि सेवा चालू न होने पर, उपयोगकर्ता वीडियो फिर से नहीं चला सकता. इस सुविधा के लिए ऑप्ट-इन करने के लिए, आपको मीडिया बटन रिसीवर के बारे में बताना होगा और onPlaybackResumption
तरीके को लागू करना होगा.
Media3 मीडिया बटन रिसीवर को सेट करना
अपने मेनिफ़ेस्ट में MediaButtonReceiver
का एलान करके शुरुआत करें:
<receiver android:name="androidx.media3.session.MediaButtonReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
प्लेबैक फिर से शुरू करने के लिए कॉलबैक लागू करना
जब किसी ब्लूटूथ डिवाइस या Android सिस्टम यूज़र इंटरफ़ेस (यूआई) की फिर से शुरू करने की सुविधा से, कॉन्टेंट को फिर से चलाने का अनुरोध किया जाता है, तब onPlaybackResumption()
कॉलबैक तरीके को कॉल किया जाता है.
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; }
अगर आपने वीडियो चलाने की रफ़्तार, दोहराने का मोड या शफ़ल मोड जैसे अन्य पैरामीटर सेव किए हैं, तो onPlaybackResumption()
एक अच्छी जगह है. यहां इन पैरामीटर के साथ प्लेयर को कॉन्फ़िगर किया जा सकता है. ऐसा तब किया जाता है, जब Media3 प्लेयर तैयार करता है और कॉलबैक पूरा होने पर वीडियो चलाना शुरू करता है.
इस तरीके को बूट टाइम के दौरान कॉल किया जाता है, ताकि डिवाइस के रीबूट होने के बाद Android सिस्टम यूज़र इंटरफ़ेस (यूआई) को फिर से शुरू करने की सूचना बनाई जा सके. रिच नोटिफ़िकेशन के लिए, यह सुझाव दिया जाता है कि मौजूदा आइटम के MediaMetadata
फ़ील्ड में, स्थानीय तौर पर उपलब्ध वैल्यू डालें. जैसे, title
और artworkData
या artworkUri
. ऐसा इसलिए, क्योंकि हो सकता है कि नेटवर्क का ऐक्सेस अभी उपलब्ध न हो. प्लेबैक फिर से शुरू होने की जगह की जानकारी देने के लिए, MediaMetadata.extras
में MediaConstants.EXTRAS_KEY_COMPLETION_STATUS
और MediaConstants.EXTRAS_KEY_COMPLETION_PERCENTAGE
भी जोड़े जा सकते हैं.
कंट्रोलर को बेहतर तरीके से कॉन्फ़िगर करने और पुराने सिस्टम के साथ काम करने की सुविधा
आम तौर पर, ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) में MediaController
का इस्तेमाल, प्लेलिस्ट दिखाने और उसे कंट्रोल करने के लिए किया जाता है. साथ ही, सेशन को Android मीडिया कंट्रोल और मोबाइल या टीवी पर Assistant जैसे बाहरी क्लाइंट के लिए उपलब्ध कराया जाता है. इसके अलावा, इसे स्मार्टवॉच के लिए Wear OS और कारों में Android Auto के लिए भी उपलब्ध कराया जाता है. Media3 सेशन डेमो ऐप्लिकेशन, ऐसे ऐप्लिकेशन का एक उदाहरण है जो इस तरह के उदाहरण को लागू करता है.
ये बाहरी क्लाइंट, लेगसी AndroidX लाइब्रेरी के MediaControllerCompat
या Android प्लैटफ़ॉर्म के android.media.session.MediaController
जैसे एपीआई का इस्तेमाल कर सकते हैं. Media3, लेगसी लाइब्रेरी के साथ पूरी तरह से काम करता है. साथ ही, यह Android प्लैटफ़ॉर्म एपीआई के साथ इंटरऑपरेबिलिटी की सुविधा देता है.
मीडिया सूचना कंट्रोलर का इस्तेमाल करना
यह समझना ज़रूरी है कि लेगसी और प्लैटफ़ॉर्म कंट्रोलर, एक ही स्थिति शेयर करते हैं. साथ ही, कंट्रोलर के हिसाब से यह तय नहीं किया जा सकता कि कौनसी स्थिति दिखेगी. उदाहरण के लिए, उपलब्ध PlaybackState.getActions()
और PlaybackState.getCustomActions()
. इन लेगसी और प्लैटफ़ॉर्म कंट्रोलर के साथ काम करने के लिए, प्लैटफ़ॉर्म मीडिया सेशन में सेट की गई स्थिति को कॉन्फ़िगर करने के लिए, मीडिया सूचना कंट्रोलर का इस्तेमाल किया जा सकता है.
उदाहरण के लिए, कोई ऐप्लिकेशन MediaSession.Callback.onConnect()
को लागू कर सकता है, ताकि प्लैटफ़ॉर्म सेशन के लिए उपलब्ध कमांड और मीडिया बटन की प्राथमिकताओं को सेट किया जा सके. ऐसा इस तरह किया जा सकता है:
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 को कस्टम कमांड भेजने की अनुमति देना
MediaLibraryService
का इस्तेमाल करते समय और मोबाइल ऐप्लिकेशन के साथ Android Auto का इस्तेमाल करने के लिए, Android Auto कंट्रोलर को सही उपलब्ध कमांड की ज़रूरत होती है. ऐसा न होने पर, Media3 उस कंट्रोलर से आने वाली कस्टम कमांड को अस्वीकार कर देगा:
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(); }
सेशन डेमो ऐप्लिकेशन में एक ऑटोमोटिव मॉड्यूल है. इससे यह पता चलता है कि यह ऐप्लिकेशन, Automotive OS के साथ काम करता है. इसके लिए, अलग APK की ज़रूरत होती है.