Media3 ExoPlayer का इस्तेमाल करके, एक बेसिक मीडिया प्लेयर ऐप्लिकेशन बनाएं

Jetpack Media3, Player इंटरफ़ेस के बारे में बताता है. इसमें वीडियो और ऑडियो फ़ाइलें चलाने की बुनियादी सुविधाएं शामिल होती हैं. Media3 में, ExoPlayer इस इंटरफ़ेस का डिफ़ॉल्ट तौर पर लागू किया गया वर्शन है. हमारा सुझाव है कि ExoPlayer का इस्तेमाल करें, क्योंकि इसमें सुविधाओं का एक पूरा सेट मिलता है. इससे, मीडिया चलाने के ज़्यादातर इस्तेमाल के मामलों को कवर किया जा सकता है. साथ ही, इसे अपनी ज़रूरत के हिसाब से भी बनाया जा सकता है, ताकि इसका इस्तेमाल अन्य मामलों में भी किया जा सके. ExoPlayer, डिवाइस और ओएस के फ़्रैगमेंटेशन को भी एब्सट्रैक्ट करता है, ताकि आपका कोड पूरे Android इकोसिस्टम में एक जैसा काम करे. ExoPlayer में ये सुविधाएं शामिल हैं:

इस पेज पर, मीडिया चलाने वाला ऐप्लिकेशन बनाने के कुछ अहम चरणों के बारे में बताया गया है. ज़्यादा जानकारी के लिए, Media3 ExoPlayer पर हमारी पूरी गाइड देखें.

शुरू करना

शुरू करने के लिए, Jetpack Media3 के ExoPlayer, यूज़र इंटरफ़ेस (यूआई) और सामान्य मॉड्यूल में डिपेंडेंसी जोड़ें:

Kotlin

implementation("androidx.media3:media3-exoplayer:1.11.0")
implementation("androidx.media3:media3-ui:1.11.0")
implementation("androidx.media3:media3-common:1.11.0")

Groovy

implementation "androidx.media3:media3-exoplayer:1.11.0"
implementation "androidx.media3:media3-ui:1.11.0"
implementation "androidx.media3:media3-common:1.11.0"

इस्तेमाल के मामले के हिसाब से, आपको Media3 के अन्य मॉड्यूल की भी ज़रूरत पड़ सकती है. जैसे, DASH फ़ॉर्मैट में स्ट्रीम चलाने के लिए exoplayer-dash मॉड्यूल.

पक्का करें कि आपने 1.11.0 की जगह, लाइब्रेरी का अपना पसंदीदा वर्शन डाला हो. लेटेस्ट वर्शन देखने के लिए, रिलीज़ नोट देखें.

मीडिया प्लेयर बनाना

Media3 की मदद से, Player इंटरफ़ेस के शामिल किए गए वर्शन ExoPlayer का इस्तेमाल किया जा सकता है. इसके अलावा, अपनी ज़रूरत के हिसाब से भी वर्शन बनाया जा सकता है.

ExoPlayer बनाना

ExoPlayer इंस्टेंस बनाने का सबसे आसान तरीका यह है:

Kotlin

val player = ExoPlayer.Builder(context).build()

Java

ExoPlayer player = new ExoPlayer.Builder(context).build();

मीडिया प्लेयर को Activity, Fragment या Service के onCreate() लाइफ़साइकल वाले तरीके में बनाया जा सकता है.

Builder में, पसंद के मुताबिक बनाने के कई विकल्प शामिल होते हैं. जिनमें आपकी दिलचस्पी हो सकती है. जैसे:

Media3, PlayerView यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट उपलब्ध कराता है. इसे अपने ऐप्लिकेशन की लेआउट फ़ाइल में शामिल किया जा सकता है. इस कॉम्पोनेंट में, मीडिया चलाने के कंट्रोल के लिए PlayerControlView, सबटाइटल दिखाने के लिए SubtitleView, और वीडियो रेंडर करने के लिए Surface शामिल होता है.

प्लेयर को तैयार करना

प्लेलिस्ट में मीडिया आइटम जोड़ने के लिए, setMediaItem() और addMediaItem() जैसे तरीकों का इस्तेमाल करें. इसके बाद, मीडिया लोड करने और ज़रूरी संसाधन पाने के लिए, prepare() को कॉल करें.

ऐप्लिकेशन के फ़ोरग्राउंड में आने से पहले, इन चरणों को पूरा न करें. अगर आपका प्लेयर किसी Activity या Fragment में है, तो इसका मतलब है कि एपीआई लेवल 24 और इसके बाद के वर्शन पर, onStart() लाइफ़साइकल वाले तरीके में या एपीआई लेवल 23 और इससे पहले के वर्शन पर, onResume() लाइफ़साइकल वाले तरीके में प्लेयर को तैयार करना. अगर प्लेयर किसी Service में है, तो उसे onCreate() में तैयार किया जा सकता है. लाइफ़साइकल वाले तरीकों को लागू करने के तरीके का उदाहरण देखने के लिए, Exoplayer codelab देखें.

प्लेयर को कंट्रोल करना

प्लेयर के तैयार हो जाने के बाद, उसे कंट्रोल किया जा सकता है. इसके लिए, प्लेयर पर ये तरीके कॉल करें:

  • मीडिया चलाने और रोकने के लिए, play() और pause()
  • मौजूदा मीडिया आइटम में किसी जगह पर जाने के लिए, seekTo()
  • प्लेलिस्ट में नेविगेट करने के लिए, seekToNextMediaItem() और seekToPreviousMediaItem()

PlayerView या PlayerControlView जैसे यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट, प्लेयर से बाइंड होने पर अपडेट हो जाएंगे.

प्लेयर को रिलीज़ करना

मीडिया चलाने के लिए, सीमित संख्या में उपलब्ध संसाधनों की ज़रूरत पड़ सकती है. जैसे, वीडियो डिकोडर. इसलिए, जब प्लेयर की ज़रूरत न हो, तो release() को कॉल करके संसाधन खाली करना ज़रूरी है.

अगर आपका प्लेयर किसी Activity या Fragment में है, तो एपीआई लेवल 24 और इसके बाद के वर्शन पर, onStop() लाइफ़साइकल वाले तरीके में या एपीआई लेवल 23 और इससे पहले के वर्शन पर, onPause() तरीके में प्लेयर को रिलीज़ करें. अगर प्लेयर किसी Service में है, तो उसे onDestroy() में रिलीज़ किया जा सकता है. लाइफ़साइकल वाले तरीकों को लागू करने के तरीके का उदाहरण देखने के लिए, Exoplayer codelab देखें.

मीडिया सेशन की मदद से, मीडिया चलाने की सुविधा को मैनेज करना

Android पर, मीडिया सेशन, प्रोसेस की सीमाओं के बीच मीडिया प्लेयर के साथ इंटरैक्ट करने का एक स्टैंडर्ड तरीका उपलब्ध कराते हैं. मीडिया सेशन को अपने प्लेयर से कनेक्ट करने पर , मीडिया चलाने की सुविधा का विज्ञापन बाहरी तौर पर दिया जा सकता है. साथ ही, बाहरी सोर्स से मीडिया चलाने के निर्देश भी पाए जा सकते हैं . उदाहरण के लिए, मोबाइल और बड़ी स्क्रीन वाले डिवाइसों पर, सिस्टम मीडिया कंट्रोल के साथ इंटिग्रेट करने के लिए.

मीडिया सेशन का इस्तेमाल करने के लिए, Media3 सेशन मॉड्यूल में डिपेंडेंसी जोड़ें:

Kotlin

implementation("androidx.media3:media3-session:1.11.0")

Groovy

implementation "androidx.media3:media3-session:1.11.0"

मीडिया सेशन बनाना

प्लेयर को शुरू करने के बाद, MediaSession बनाया जा सकता है. इसके लिए, यह तरीका अपनाएं:

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 की स्थिति को MediaSession की स्थिति के साथ अपने-आप सिंक करता है. यह Player के किसी भी वर्शन के साथ काम करता है, जिसमें ExoPlayer, CastPlayer या अपनी ज़रूरत के हिसाब से बनाए गए वर्शन शामिल हैं.

अन्य क्लाइंट को कंट्रोल करने की अनुमति देना

क्लाइंट ऐप्लिकेशन, मीडिया सेशन को कंट्रोल करने के लिए, एक मीडिया कंट्रोलर लागू कर सकते हैं. इन अनुरोधों को पाने के लिए, कॉलबैक ऑब्जेक्ट सेट करें जब आप अपना MediaSession बना रहे हों.

जब कोई कंट्रोलर, आपके मीडिया सेशन से कनेक्ट होने वाला होता है, तब onConnect() तरीका कॉल किया जाता है. अनुरोध को स्वीकार करना है या नहीं, यह तय करने के लिए, दिए गए ControllerInfo का इस्तेमाल किया जा सकता है. अनुरोध को स्वीकार करना है या अस्वीकार करना है, यह तय करने के लिए, दिए गए का इस्तेमाल किया जा सकता है. इसका उदाहरण, Media3 सेशन डेमो ऐप्लिकेशन में देखा जा सकता है.

कनेक्ट होने के बाद, कोई कंट्रोलर सेशन को मीडिया चलाने के निर्देश भेज सकता है. इसके बाद, सेशन उन निर्देशों को प्लेयर को सौंप देता है. Player इंटरफ़ेस में तय किए गए, मीडिया चलाने और प्लेलिस्ट के निर्देश, सेशन से अपने-आप मैनेज हो जाते हैं.

अन्य कॉलबैक तरीकों से, उदाहरण के लिए, मीडिया चलाने के कस्टम निर्देशों के अनुरोधों और प्लेलिस्ट में बदलाव करने के अनुरोधों को मैनेज किया जा सकता है. इन कॉलबैक में भी ControllerInfo ऑब्जेक्ट शामिल होता है, ताकि अनुरोध के आधार पर, ऐक्सेस कंट्रोल तय किया जा सके.

बैकग्राउंड में मीडिया चलाना

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

MediaSessionService लागू करना

एक ऐसी क्लास बनाएं जो MediaSessionService को एक्सटेंड करती हो. साथ ही, आपके MediaSession को onCreate() लाइफ़साइकल वाले तरीके में इंस्टैंशिएट करें.

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();
    }
}

अपनी मेनिफ़ेस्ट फ़ाइल में, अपनी Service क्लास का एलान करें. साथ ही, फ़ोरग्राउंड सेवा चलाने के लिए, MediaSessionService इंटेंट फ़िल्टर और FOREGROUND_SERVICE अनुमति का अनुरोध करें:

<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" />

आखिर में, बनाई गई क्लास में, onGetSession() तरीके को बदलें, ताकि क्लाइंट को आपके मीडिया सेशन का ऐक्सेस कंट्रोल किया जा सके. कनेक्शन के अनुरोध को स्वीकार करने के लिए, MediaSession वापस लाएं. अनुरोध को अस्वीकार करने के लिए, null वापस लाएं.

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;
}

अपने यूज़र इंटरफ़ेस (यूआई) से कनेक्ट करना

अब आपका मीडिया सेशन, Activity या Fragment से अलग Service में है. इसलिए, MediaController का इस्तेमाल करके, इन्हें लिंक किया जा सकता है. आपके प्लेयर का यूज़र इंटरफ़ेस (यूआई) इसी में मौजूद होता है. अपने यूज़र इंटरफ़ेस (यूआई) के साथ Activity या Fragment के onStart() तरीके में, अपने MediaSession के लिए SessionToken बनाएं. इसके बाद, MediaController बनाने के लिए, SessionToken का इस्तेमाल करें. MediaController एसिंक्रोनस तरीके से बनता है.

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 इंटरफ़ेस को लागू करता है. इसलिए, मीडिया चलाने की सुविधा को कंट्रोल करने के लिए, play() और pause() जैसे तरीकों का इस्तेमाल किया जा सकता है. अन्य कॉम्पोनेंट की तरह, MediaController को रिलीज़ करना न भूलें. इसके लिए, Activity के onStop() लाइफ़साइकल वाले तरीके में, MediaController.releaseFuture() को कॉल करें.

सूचना पब्लिश करना

फ़ोरग्राउंड सेवाओं को चालू रहने के दौरान, सूचना पब्लिश करनी होती है. A MediaSessionService आपके लिए MediaStyle सूचना अपने-आप बनाएगा. यह सूचना, MediaNotification के फ़ॉर्म में होगी. कस्टम सूचना देने के लिए, MediaNotification.Provider की मदद से या प्रोवाइडर इंटरफ़ेस का कस्टम वर्शन बनाकर, DefaultMediaNotificationProvider.Builder बनाएं. अपने MediaSession में प्रोवाइडर जोड़ें, setMediaNotificationProvider की मदद से.

अपनी कॉन्टेंट लाइब्रेरी का विज्ञापन करना

एक MediaLibraryService, MediaSessionService पर आधारित होता है. इसकी मदद से, क्लाइंट ऐप्लिकेशन, आपके ऐप्लिकेशन से मिले मीडिया कॉन्टेंट को ब्राउज़ कर सकते हैं. क्लाइंट ऐप्लिकेशन, आपके MediaLibraryService के साथ इंटरैक्ट करने के लिए, MediaBrowser लागू करते हैं.

MediaLibraryService को लागू करना, MediaSessionService को लागू करने जैसा ही है. हालांकि, onGetSession() में, MediaSession के बजाय MediaLibrarySession वापस लाना चाहिए. MediaSession.Callback की तुलना में, MediaLibrarySession.Callback में अतिरिक्त तरीके शामिल होते हैं. इनकी मदद से, ब्राउज़र क्लाइंट, आपकी लाइब्रेरी सेवा से मिले कॉन्टेंट में नेविगेट कर सकता है.

MediaSessionService की तरह, अपनी मेनिफ़ेस्ट फ़ाइल में MediaLibraryService का एलान करें. साथ ही, फ़ोरग्राउंड सेवा चलाने के लिए, FOREGROUND_SERVICE अनुमति का अनुरोध करें:

<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" />

ऊपर दिए गए उदाहरण में, MediaLibraryService और पुराने वर्शन के साथ काम करने की सुविधा के लिए, पुराने MediaBrowserService के लिए इंटेंट फ़िल्टर शामिल है. अतिरिक्त इंटेंट फ़िल्टर की मदद से, MediaBrowserCompat एपीआई का इस्तेमाल करने वाले क्लाइंट ऐप्लिकेशन, आपकी Service को पहचान पाते हैं.

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

MediaLibrarySession बनाना

एक MediaLibrarySession, MediaSession एपीआई को एक्सटेंड करके, कॉन्टेंट ब्राउज़ करने के एपीआई जोड़ता है. MediaSession कॉलबैक की तुलना में, MediaLibrarySession कॉलबैक में ये तरीके जोड़े जाते हैं:

  • जब कोई क्लाइंट, कॉन्टेंट ट्री का रूट MediaItem का अनुरोध करता है, तब onGetLibraryRoot()
  • जब कोई क्लाइंट, कॉन्टेंट ट्री में मौजूद MediaItem के चाइल्ड का अनुरोध करता है, तब onGetChildren()
  • onGetSearchResult() जब कोई क्लाइंट, दी गई क्वेरी के लिए, कॉन्टेंट ट्री से खोज नतीजों का अनुरोध करता है, तब

काम के कॉलबैक तरीकों में, एक LibraryParams ऑब्जेक्ट शामिल होगा. इसमें क्लाइंट ऐप्लिकेशन की दिलचस्पी वाले कॉन्टेंट ट्री के टाइप के बारे में अतिरिक्त सिग्नल शामिल होंगे .