ExoPlayer की मदद से, मीडिया को ऑफ़लाइन चलाने के लिए डाउनलोड किया जा सकता है. ज़्यादातर मामलों में, ऐप्लिकेशन बैकग्राउंड में होने पर भी डाउनलोड जारी रखने की सुविधा चालू रखना बेहतर होता है. इस्तेमाल के इन उदाहरणों के लिए, आपके ऐप्लिकेशन में DownloadService
सबक्लास होना चाहिए. साथ ही, डाउनलोड जोड़ने, हटाने, और उन्हें कंट्रोल करने के लिए, सेवा को निर्देश भेजने चाहिए. नीचे दिया गया डायग्राम, इसमें शामिल मुख्य क्लास को दिखाता है.
DownloadService
:DownloadManager
को रैप करता है और उस पर निर्देश भेजता है. यह सेवा, ऐप्लिकेशन के बैकग्राउंड में होने पर भीDownloadManager
को चालू रखने की अनुमति देती है.DownloadManager
: यह कई डाउनलोड मैनेज करता है. साथ ही,DownloadIndex
से और उसमें, डाउनलोड की स्थिति को लोड (और सेव) करता है. साथ ही, नेटवर्क कनेक्शन जैसी ज़रूरी शर्तों के आधार पर, डाउनलोड शुरू और बंद करता है. कॉन्टेंट डाउनलोड करने के लिए, मैनेजर आम तौर परHttpDataSource
से डाउनलोड किया जा रहा डेटा पढ़ेगा और उसेCache
में लिखेगा.DownloadIndex
: डाउनलोड की स्थिति को सेव करता है.
DownloadService बनाना
DownloadService
बनाने के लिए, उसे सबक्लास बनाएं और उसके एब्स्ट्रैक्ट तरीके लागू करें:
getDownloadManager()
: इस्तेमाल की जाने वालीDownloadManager
को दिखाता है.getScheduler()
: एक वैकल्पिकScheduler
दिखाता है. यहScheduler
, डाउनलोड की प्रोसेस को फिर से शुरू कर सकता है. ऐसा तब होता है, जब बाकी बचे डाउनलोड की ज़रूरी शर्तें पूरी हो जाती हैं. ExoPlayer में ये सुविधाएं उपलब्ध हैं:PlatformScheduler
, जो JobScheduler का इस्तेमाल करता है (एपीआई कम से कम 21 होना चाहिए). ऐप्लिकेशन की अनुमतियों से जुड़ी ज़रूरी शर्तों के लिए, PlatformScheduler के Javadoc देखें.WorkManagerScheduler
, जो WorkManager का इस्तेमाल करता है.
getForegroundNotification()
: यह फ़ंक्शन, सेवा के फ़ोरग्राउंड में चलने पर दिखाई जाने वाली सूचना दिखाता है. डिफ़ॉल्ट स्टाइल में सूचना बनाने के लिए,DownloadNotificationHelper.buildProgressNotification
का इस्तेमाल किया जा सकता है.
आखिर में, अपनी AndroidManifest.xml
फ़ाइल में सेवा के बारे में बताएं:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>
<application>
<service android:name="com.myapp.MyDownloadService"
android:exported="false"
android:foregroundServiceType="dataSync">
<!-- This is needed for Scheduler -->
<intent-filter>
<action android:name="androidx.media3.exoplayer.downloadService.action.RESTART"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
</application>
इसका उदाहरण देखने के लिए, ExoPlayer के डेमो ऐप्लिकेशन में DemoDownloadService
और AndroidManifest.xml
देखें.
DownloadManager बनाना
नीचे दिए गए कोड स्निपेट में, DownloadManager
को इंस्टैंशिएट करने का तरीका बताया गया है. इसे DownloadService
में getDownloadManager()
से दिखाया जा सकता है:
Kotlin
// Note: This should be a singleton in your app. val databaseProvider = StandaloneDatabaseProvider(context) // A download cache should not evict media, so should use a NoopCacheEvictor. val downloadCache = SimpleCache(downloadDirectory, NoOpCacheEvictor(), databaseProvider) // Create a factory for reading the data from the network. val dataSourceFactory = DefaultHttpDataSource.Factory() // Choose an executor for downloading data. Using Runnable::run will cause each download task to // download data on its own thread. Passing an executor that uses multiple threads will speed up // download tasks that can be split into smaller parts for parallel execution. Applications that // already have an executor for background downloads may wish to reuse their existing executor. val downloadExecutor = Executor(Runnable::run) // Create the download manager. val downloadManager = DownloadManager(context, databaseProvider, downloadCache, dataSourceFactory, downloadExecutor) // Optionally, properties can be assigned to configure the download manager. downloadManager.requirements = requirements downloadManager.maxParallelDownloads = 3
Java
// Note: This should be a singleton in your app. databaseProvider = new StandaloneDatabaseProvider(context); // A download cache should not evict media, so should use a NoopCacheEvictor. downloadCache = new SimpleCache(downloadDirectory, new NoOpCacheEvictor(), databaseProvider); // Create a factory for reading the data from the network. dataSourceFactory = new DefaultHttpDataSource.Factory(); // Choose an executor for downloading data. Using Runnable::run will cause each download task to // download data on its own thread. Passing an executor that uses multiple threads will speed up // download tasks that can be split into smaller parts for parallel execution. Applications that // already have an executor for background downloads may wish to reuse their existing executor. Executor downloadExecutor = Runnable::run; // Create the download manager. downloadManager = new DownloadManager( context, databaseProvider, downloadCache, dataSourceFactory, downloadExecutor); // Optionally, setters can be called to configure the download manager. downloadManager.setRequirements(requirements); downloadManager.setMaxParallelDownloads(3);
इसका उदाहरण देखने के लिए, डेमो ऐप्लिकेशन में DemoUtil
देखें.
डाउनलोड जोड़ना
डाउनलोड की गई किसी फ़ाइल को जोड़ने के लिए, DownloadRequest
बनाएं और उसे अपने
DownloadService
पर भेजें. अडैप्टिव स्ट्रीम के लिए, DownloadRequest
बनाने में मदद पाने के लिए, DownloadHelper
का इस्तेमाल करें. यहां दिए गए उदाहरण में, डाउनलोड का अनुरोध करने का तरीका बताया गया है:
Kotlin
val downloadRequest = DownloadRequest.Builder(contentId, contentUri).build()
Java
DownloadRequest downloadRequest = new DownloadRequest.Builder(contentId, contentUri).build();
इस उदाहरण में, contentId
कॉन्टेंट का यूनीक आइडेंटिफ़ायर है. सामान्य मामलों में, contentUri
का इस्तेमाल अक्सर contentId
के तौर पर किया जा सकता है. हालांकि, ऐप्लिकेशन अपने इस्तेमाल के उदाहरण के हिसाब से, अपनी पसंद के आईडी स्कीम का इस्तेमाल कर सकते हैं. DownloadRequest.Builder
में कुछ वैकल्पिक सेटर भी होते हैं. उदाहरण के लिए, setKeySetId
और setData
का इस्तेमाल, डीआरएम और कस्टम डेटा को सेट करने के लिए किया जा सकता है. ऐप्लिकेशन, डाउनलोड किए गए कॉन्टेंट के साथ इन डेटा को जोड़ना चाहता है. कॉन्टेंट के MIME टाइप की जानकारी, setMimeType
का इस्तेमाल करके भी दी जा सकती है. ऐसा उन मामलों में एक हिंट के तौर पर किया जा सकता है जहां contentUri
से कॉन्टेंट टाइप का पता नहीं चलता.
अनुरोध बनाने के बाद, डाउनलोड जोड़ने के लिए DownloadService
को अनुरोध भेजा जा सकता है:
Kotlin
DownloadService.sendAddDownload( context, MyDownloadService::class.java, downloadRequest, /* foreground= */ false )
Java
DownloadService.sendAddDownload( context, MyDownloadService.class, downloadRequest, /* foreground= */ false);
इस उदाहरण में, MyDownloadService
ऐप्लिकेशन का DownloadService
सबक्लास है और foreground
पैरामीटर यह कंट्रोल करता है कि सेवा को फ़ोरग्राउंड में शुरू किया जाएगा या नहीं. अगर आपका ऐप्लिकेशन पहले से फ़ोरग्राउंड में है, तो foreground
पैरामीटर को सामान्य रूप से false
पर सेट किया जाना चाहिए. इसकी वजह यह है कि DownloadService
खुद को फ़ोरग्राउंड में डाल देगा, अगर उसे लगता है कि उसे काम करना है.
डाउनलोड की गई फ़ाइलें हटाई जा रही हैं
DownloadService
को 'हटाएं' निर्देश भेजकर, किसी डाउनलोड को हटाया जा सकता है. इसमें contentId
, हटाए जाने वाले डाउनलोड की पहचान करता है:
Kotlin
DownloadService.sendRemoveDownload( context, MyDownloadService::class.java, contentId, /* foreground= */ false )
Java
DownloadService.sendRemoveDownload( context, MyDownloadService.class, contentId, /* foreground= */ false);
DownloadService.sendRemoveAllDownloads
की मदद से, डाउनलोड किया गया सारा डेटा भी हटाया जा सकता है.
डाउनलोड शुरू और बंद करना
डाउनलोड सिर्फ़ तब शुरू होगा, जब ये चार शर्तें पूरी होंगी:
- डाउनलोड रुकने की वजह नहीं दी गई है.
- डाउनलोड की प्रोसेस रुक नहीं रही है.
- डाउनलोड की प्रोग्रेस से जुड़ी ज़रूरी शर्तें पूरी हो गई हैं. ज़रूरी शर्तों में, इस्तेमाल किए जा सकने वाले नेटवर्क टाइप से जुड़ी पाबंदियों के साथ-साथ यह भी बताया जा सकता है कि डिवाइस को चार्जर से कनेक्ट किया गया हो या नहीं.
- एक साथ डाउनलोड की जा सकने वाली ज़्यादा से ज़्यादा संख्या से ज़्यादा डाउनलोड न किए जा रहे हों.
इन सभी स्थितियों को कंट्रोल करने के लिए, अपने DownloadService
पर निर्देश भेजें.
डाउनलोड रुकने की वजहें सेट करना और उन्हें मिटाना
एक या सभी डाउनलोड को रोकने की वजह सेट की जा सकती है:
Kotlin
// Set the stop reason for a single download. DownloadService.sendSetStopReason( context, MyDownloadService::class.java, contentId, stopReason, /* foreground= */ false ) // Clear the stop reason for a single download. DownloadService.sendSetStopReason( context, MyDownloadService::class.java, contentId, Download.STOP_REASON_NONE, /* foreground= */ false )
Java
// Set the stop reason for a single download. DownloadService.sendSetStopReason( context, MyDownloadService.class, contentId, stopReason, /* foreground= */ false); // Clear the stop reason for a single download. DownloadService.sendSetStopReason( context, MyDownloadService.class, contentId, Download.STOP_REASON_NONE, /* foreground= */ false);
stopReason
की वैल्यू शून्य के अलावा कोई भी हो सकती है. Download.STOP_REASON_NONE = 0
एक खास वैल्यू है, जिसका मतलब है कि डाउनलोड नहीं रुका है. जिन ऐप्लिकेशन में डाउनलोड रोकने की कई वजहें होती हैं वे अलग-अलग वैल्यू का इस्तेमाल करके, यह ट्रैक कर सकते हैं कि हर डाउनलोड क्यों रोका गया. सभी डाउनलोड के लिए, डाउनलोड रोकने की वजह सेट करने और उसे हटाने का तरीका, किसी एक डाउनलोड के लिए डाउनलोड रोकने की वजह सेट करने और उसे हटाने के तरीके जैसा ही है. हालांकि, contentId
को null
पर सेट किया जाना चाहिए.
अगर डाउनलोड की वजह से डाउनलोड रुकने की वजह शून्य से ज़्यादा है, तो उसकी स्थिति Download.STATE_STOPPED
होगी. स्टॉप की वजहें DownloadIndex
में बनी रहती हैं. इसलिए, अगर ऐप्लिकेशन प्रोसेस बंद हो जाती है और बाद में रीस्टार्ट हो जाता है, तो भी इसे सेव रखा जाता है.
सभी डाउनलोड रोकना और फिर से शुरू करना
सभी डाउनलोड को रोका और फिर से शुरू किया जा सकता है. इसके लिए, यह तरीका अपनाएं:
Kotlin
// Pause all downloads. DownloadService.sendPauseDownloads( context, MyDownloadService::class.java, /* foreground= */ false ) // Resume all downloads. DownloadService.sendResumeDownloads( context, MyDownloadService::class.java, /* foreground= */ false )
Java
// Pause all downloads. DownloadService.sendPauseDownloads(context, MyDownloadService.class, /* foreground= */ false); // Resume all downloads. DownloadService.sendResumeDownloads(context, MyDownloadService.class, /* foreground= */ false);
डाउनलोड रोके जाने पर, उनकी स्थिति Download.STATE_QUEUED
के तौर पर दिखेगी.
स्टॉप की वजहें सेट करने के विपरीत, इस तरीके से किसी भी स्थिति में बदलाव नहीं होता. इससे सिर्फ़ DownloadManager
के रनटाइम की स्थिति पर असर पड़ता है.
डाउनलोड को प्रोसेस करने के लिए ज़रूरी शर्तें सेट करना
Requirements
का इस्तेमाल, उन शर्तों के बारे में बताने के लिए किया जा सकता है जिन्हें पूरा करने के बाद ही, डाउनलोड की प्रोसेस शुरू की जा सकती है. DownloadManager
बनाते समय, DownloadManager.setRequirements()
को कॉल करके ज़रूरी शर्तें सेट की जा सकती हैं. उदाहरण के लिए, ऊपर दिया गया उदाहरण. DownloadService
को कमांड भेजकर भी इन्हें डाइनैमिक तरीके से बदला जा सकता है:
Kotlin
// Set the download requirements. DownloadService.sendSetRequirements( context, MyDownloadService::class.java, requirements, /* foreground= */ false)
Java
// Set the download requirements. DownloadService.sendSetRequirements( context, MyDownloadService.class, requirements, /* foreground= */ false);
अगर ज़रूरी शर्तें पूरी न होने की वजह से डाउनलोड नहीं हो पा रहा है, तो उसकी स्थिति Download.STATE_QUEUED
होगी. DownloadManager.getNotMetRequirements()
की मदद से, उन ज़रूरी शर्तों के बारे में क्वेरी की जा सकती है जो पूरी नहीं की गई हैं.
एक साथ ज़्यादा से ज़्यादा कितने वीडियो डाउनलोड किए जा सकते हैं, यह सेट करना
एक साथ डाउनलोड की जा सकने वाली फ़ाइलों की ज़्यादा से ज़्यादा संख्या सेट करने के लिए, DownloadManager.setMaxParallelDownloads()
को कॉल करें. आम तौर पर, DownloadManager
बनाते समय ऐसा किया जाता है, जैसा कि ऊपर दिए गए उदाहरण में बताया गया है.
जब एक साथ कई फ़ाइलें डाउनलोड करने की तय सीमा पूरी हो जाती है, तो Download.STATE_QUEUED
स्टेटस दिखता है.
डाउनलोड के बारे में क्वेरी करना
DownloadManager
के DownloadIndex
से, सभी डाउनलोड की स्थिति के बारे में जानकारी मांगी जा सकती है. इसमें, डाउनलोड की गई फ़ाइलें भी शामिल हैं. DownloadIndex
पाने के लिए, DownloadManager.getDownloadIndex()
पर कॉल करें. इसके बाद, DownloadIndex.getDownloads()
को कॉल करके, सभी डाउनलोड पर कर्सर घुमाया जा सकता है. इसके अलावा, DownloadIndex.getDownload()
को कॉल करके, किसी एक डाउनलोड की स्थिति के बारे में जानकारी भी पाई जा सकती है.
DownloadManager
से, DownloadManager.getCurrentDownloads()
की जानकारी भी मिलती है. इससे सिर्फ़ डाउनलोड की मौजूदा स्थिति (यानी पूरा नहीं हुआ या पूरा नहीं हो सका) की जानकारी मिलती है. यह तरीका, सूचनाओं और यूज़र इंटरफ़ेस (यूआई) के उन अन्य कॉम्पोनेंट को अपडेट करने के लिए काम आता है जो मौजूदा डाउनलोड की स्थिति और प्रोग्रेस दिखाते हैं.
डाउनलोड किए गए वीडियो सुनना
DownloadManager
में किसी लिसनर को जोड़ा जा सकता है, ताकि मौजूदा डाउनलोड की स्थिति बदलने पर आपको इसकी सूचना मिल सके:
Kotlin
downloadManager.addListener( object : DownloadManager.Listener { // Override methods of interest here. } )
Java
downloadManager.addListener( new DownloadManager.Listener() { // Override methods of interest here. });
उदाहरण के लिए, डेमो ऐप्लिकेशन की DownloadTracker
क्लास में DownloadManagerListener
देखें.
डाउनलोड किया गया कॉन्टेंट चलाया जा रहा है
डाउनलोड किया गया कॉन्टेंट चलाना, ऑनलाइन कॉन्टेंट चलाने जैसा ही है. हालांकि, इसमें डेटा को नेटवर्क से पढ़ने के बजाय, डाउनलोड किए गए Cache
से पढ़ा जाता है.
डाउनलोड किया गया कॉन्टेंट चलाने के लिए, उसी Cache
इंस्टेंस का इस्तेमाल करके CacheDataSource.Factory
बनाएं जिसका इस्तेमाल डाउनलोड करने के लिए किया गया था. साथ ही, प्लेयर बनाते समय इसे DefaultMediaSourceFactory
में इंजेक्ट करें:
Kotlin
// Create a read-only cache data source factory using the download cache. val cacheDataSourceFactory: DataSource.Factory = CacheDataSource.Factory() .setCache(downloadCache) .setUpstreamDataSourceFactory(httpDataSourceFactory) .setCacheWriteDataSinkFactory(null) // Disable writing. val player = ExoPlayer.Builder(context) .setMediaSourceFactory( DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory) ) .build()
Java
// Create a read-only cache data source factory using the download cache. DataSource.Factory cacheDataSourceFactory = new CacheDataSource.Factory() .setCache(downloadCache) .setUpstreamDataSourceFactory(httpDataSourceFactory) .setCacheWriteDataSinkFactory(null); // Disable writing. ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory)) .build();
अगर उसी प्लेयर इंस्टेंस का इस्तेमाल, डाउनलोड नहीं किए गए कॉन्टेंट को चलाने के लिए भी किया जाएगा, तो CacheDataSource.Factory
को रीड-ओनली के तौर पर कॉन्फ़िगर किया जाना चाहिए, ताकि वीडियो चलाने के दौरान उस कॉन्टेंट को भी डाउनलोड न किया जाए.
CacheDataSource.Factory
के साथ प्लेयर को कॉन्फ़िगर करने के बाद, उसे डाउनलोड किए गए कॉन्टेंट को चलाने का ऐक्सेस मिल जाएगा. किसी डाउनलोड को चलाना,
उससे जुड़े MediaItem
को प्लेयर को पास करने जितना आसान हो जाता है. MediaItem
, Download.request.toMediaItem
का इस्तेमाल करके Download
से या DownloadRequest.toMediaItem
का इस्तेमाल करके सीधे DownloadRequest
से लिया जा सकता है.
MediaSource कॉन्फ़िगरेशन
ऊपर दिए गए उदाहरण में, डाउनलोड किए गए कैश मेमोरी को सभी MediaItem
s के लिए चलाने के लिए उपलब्ध कराया गया है. डाउनलोड कैश मेमोरी को अलग-अलग MediaSource
इंस्टेंस के लिए भी उपलब्ध कराया जा सकता है. इसे सीधे प्लेयर को पास किया जा सकता है:
Kotlin
val mediaSource = ProgressiveMediaSource.Factory(cacheDataSourceFactory) .createMediaSource(MediaItem.fromUri(contentUri)) player.setMediaSource(mediaSource) player.prepare()
Java
ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory) .createMediaSource(MediaItem.fromUri(contentUri)); player.setMediaSource(mediaSource); player.prepare();
स्ट्रीम के हिसाब से वीडियो डाउनलोड करना और चलाना
अडैप्टिव स्ट्रीम (जैसे, DASH, SmoothStreaming, और HLS) में आम तौर पर, एक से ज़्यादा मीडिया ट्रैक होते हैं. ऐसे कई ट्रैक होते हैं जिनमें एक जैसा कॉन्टेंट, अलग-अलग क्वालिटी में होता है. जैसे, एसडी, एचडी, और 4K वीडियो ट्रैक. एक ही तरह के कई ट्रैक में अलग-अलग कॉन्टेंट भी हो सकता है. जैसे, अलग-अलग भाषाओं में कई ऑडियो ट्रैक.
स्ट्रीमिंग के दौरान, ट्रैक सिलेक्टर का इस्तेमाल करके यह चुना जा सकता है कि कौनसे ट्रैक चलाए जाएं. इसी तरह, डाउनलोड करने के लिए, DownloadHelper
का इस्तेमाल करके यह चुना जा सकता है कि कौनसे ट्रैक डाउनलोड किए जाएं. DownloadHelper
का सामान्य इस्तेमाल करने के लिए, यह तरीका अपनाएं:
- किसी
DownloadHelper.forMediaItem
तरीके का इस्तेमाल करके,DownloadHelper
बनाएं. हेल्पर को तैयार करें और कॉलबैक का इंतज़ार करें.Kotlin
val downloadHelper = DownloadHelper.forMediaItem( context, MediaItem.fromUri(contentUri), DefaultRenderersFactory(context), dataSourceFactory ) downloadHelper.prepare(callback)
Java
DownloadHelper downloadHelper = DownloadHelper.forMediaItem( context, MediaItem.fromUri(contentUri), new DefaultRenderersFactory(context), dataSourceFactory); downloadHelper.prepare(callback);
- इसके अलावा,
getMappedTrackInfo
औरgetTrackSelections
का इस्तेमाल करके, डिफ़ॉल्ट रूप से चुने गए ट्रैक की जांच करें. साथ ही,clearTrackSelections
,replaceTrackSelections
, औरaddTrackSelection
का इस्तेमाल करके, उनमें बदलाव करें. getDownloadRequest
को कॉल करके, चुने गए ट्रैक के लिएDownloadRequest
बनाएं. ऊपर बताए गए तरीके से, डाउनलोड जोड़ने के लिए अनुरोध को अपनेDownloadService
पर भेजा जा सकता है.release()
का इस्तेमाल करके, हेल्पर को छोड़ें.
डाउनलोड किए गए अडैप्टिव कॉन्टेंट को चलाने के लिए, प्लेयर को कॉन्फ़िगर करना और ऊपर बताए गए तरीके से उससे जुड़ा MediaItem
पास करना ज़रूरी है.
MediaItem
बनाते समय, MediaItem.localConfiguration.streamKeys
को DownloadRequest
में मौजूद ट्रैक से मैच करने के लिए सेट किया जाना चाहिए, ताकि प्लेयर सिर्फ़ डाउनलोड किए गए ट्रैक के सबसेट को चलाने की कोशिश करे. MediaItem
बनाने के लिए,
Download.request.toMediaItem
और DownloadRequest.toMediaItem
का इस्तेमाल करने पर, यह काम आपके लिए हो जाएगा.