ExoPlayer অফলাইন প্লেব্যাকের জন্য মিডিয়া ডাউনলোড করার কার্যকারিতা প্রদান করে। বেশিরভাগ ব্যবহারের ক্ষেত্রে, আপনার অ্যাপটি ব্যাকগ্রাউন্ডে থাকা সত্ত্বেও ডাউনলোডগুলি চালিয়ে যাওয়া বাঞ্ছনীয়। এই ব্যবহারের ক্ষেত্রে, আপনার অ্যাপটি DownloadService সাবক্লাস করবে এবং ডাউনলোডগুলি যোগ, অপসারণ এবং নিয়ন্ত্রণ করার জন্য পরিষেবাতে কমান্ড পাঠাবে। নিম্নলিখিত চিত্রটি জড়িত প্রধান ক্লাসগুলি দেখায়।
-
DownloadService: একটিDownloadManagerমোড়ানো এবং এতে কমান্ড ফরোয়ার্ড করে। এই পরিষেবাটিDownloadManagerকে অ্যাপটি ব্যাকগ্রাউন্ডে থাকা অবস্থায়ও চালু রাখতে সাহায্য করে। -
DownloadManager: একাধিক ডাউনলোড পরিচালনা করে,DownloadIndexথেকে (এবং) তাদের অবস্থা লোড (এবং সংরক্ষণ) করে, নেটওয়ার্ক সংযোগের মতো প্রয়োজনীয়তার উপর ভিত্তি করে ডাউনলোড শুরু এবং বন্ধ করে, ইত্যাদি। কন্টেন্ট ডাউনলোড করার জন্য, ম্যানেজার সাধারণতHttpDataSourceথেকে ডাউনলোড করা ডেটা পড়বে এবং এটি একটিCacheএ লিখবে। -
DownloadIndex: ডাউনলোডের অবস্থা বজায় রাখে।
একটি ডাউনলোড পরিষেবা তৈরি করা হচ্ছে
একটি DownloadService তৈরি করতে, এটিকে সাবক্লাস করুন এবং এর বিমূর্ত পদ্ধতিগুলি বাস্তবায়ন করুন:
-
getDownloadManager(): ব্যবহার করার জন্যDownloadManagerফেরত পাঠায়। -
getScheduler(): একটি ঐচ্ছিকSchedulerপ্রদান করে, যা মুলতুবি থাকা ডাউনলোডগুলির অগ্রগতির জন্য প্রয়োজনীয় প্রয়োজনীয়তা পূরণ হলে পরিষেবাটি পুনরায় চালু করতে পারে। ExoPlayer এই বাস্তবায়নগুলি প্রদান করে:-
PlatformScheduler, যা JobScheduler ব্যবহার করে (সর্বনিম্ন API হল 21)। অ্যাপের অনুমতির প্রয়োজনীয়তার জন্য PlatformScheduler javadocs দেখুন। -
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 ইন্সট্যান্টিয়েট করতে হয়, যা আপনার DownloadService এ getDownloadManager() দ্বারা ফেরত পাঠানো যেতে পারে:
কোটলিন
// 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
জাভা
// 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 ব্যবহার করুন । নিচের উদাহরণটি দেখায় কিভাবে একটি ডাউনলোড অনুরোধ তৈরি করতে হয়:
কোটলিন
val downloadRequest = DownloadRequest.Builder(contentId, contentUri).build()
জাভা
DownloadRequest downloadRequest = new DownloadRequest.Builder(contentId, contentUri).build();
এই উদাহরণে, contentId হল কন্টেন্টের জন্য একটি অনন্য শনাক্তকারী। সহজ ক্ষেত্রে, contentUri প্রায়শই contentId হিসাবে ব্যবহার করা যেতে পারে, তবে অ্যাপগুলি তাদের ব্যবহারের ক্ষেত্রে সবচেয়ে উপযুক্ত আইডি স্কিম ব্যবহার করতে স্বাধীন। DownloadRequest.Builder কিছু ঐচ্ছিক সেটারও রয়েছে। উদাহরণস্বরূপ, setKeySetId এবং setData যথাক্রমে DRM এবং কাস্টম ডেটা সেট করতে ব্যবহার করা যেতে পারে যা অ্যাপটি ডাউনলোডের সাথে সংযুক্ত করতে চায়। কন্টেন্টের MIME টাইপ setMimeType ব্যবহার করেও নির্দিষ্ট করা যেতে পারে, যেখানে contentUri থেকে কন্টেন্ট টাইপ অনুমান করা যায় না।
একবার তৈরি হয়ে গেলে, ডাউনলোডটি যোগ করার জন্য অনুরোধটি DownloadService এ পাঠানো যেতে পারে:
কোটলিন
DownloadService.sendAddDownload( context, MyDownloadService::class.java, downloadRequest, /* foreground= */ false )
জাভা
DownloadService.sendAddDownload( context, MyDownloadService.class, downloadRequest, /* foreground= */ false);
এই উদাহরণে, MyDownloadService হল অ্যাপের DownloadService সাবক্লাস, এবং foreground প্যারামিটার নিয়ন্ত্রণ করে যে পরিষেবাটি ফোরগ্রাউন্ডে শুরু হবে কিনা। যদি আপনার অ্যাপটি ইতিমধ্যেই ফোরগ্রাউন্ডে থাকে, তাহলে foreground প্যারামিটারটি সাধারণত false তে সেট করা উচিত কারণ যদি DownloadService নির্ধারণ করে যে এটির কাজ করার আছে তবে এটি নিজেকে ফোরগ্রাউন্ডে রাখবে।
ডাউনলোডগুলি সরানো হচ্ছে
DownloadService এ একটি remove কমান্ড পাঠিয়ে একটি ডাউনলোড সরানো যেতে পারে, যেখানে contentId মুছে ফেলার জন্য ডাউনলোডটি সনাক্ত করে:
কোটলিন
DownloadService.sendRemoveDownload( context, MyDownloadService::class.java, contentId, /* foreground= */ false )
জাভা
DownloadService.sendRemoveDownload( context, MyDownloadService.class, contentId, /* foreground= */ false);
আপনি DownloadService.sendRemoveAllDownloads ব্যবহার করে সমস্ত ডাউনলোড করা ডেটাও মুছে ফেলতে পারেন।
ডাউনলোড শুরু এবং বন্ধ করা
চারটি শর্ত পূরণ হলেই কেবল ডাউনলোডের অগ্রগতি হবে:
- ডাউনলোড বন্ধ করার কোনও কারণ নেই।
- ডাউনলোডগুলি থামানো হয় না।
- ডাউনলোডের অগ্রগতির জন্য প্রয়োজনীয়তাগুলি পূরণ করা হয়েছে। প্রয়োজনীয়তাগুলি অনুমোদিত নেটওয়ার্ক প্রকারের সীমাবদ্ধতাগুলি নির্দিষ্ট করতে পারে, সেইসাথে ডিভাইসটি নিষ্ক্রিয় থাকা উচিত নাকি চার্জারের সাথে সংযুক্ত থাকা উচিত।
- সমান্তরাল ডাউনলোডের সর্বোচ্চ সংখ্যা অতিক্রম করা যাবে না।
এই সমস্ত অবস্থা আপনার DownloadService এ কমান্ড পাঠিয়ে নিয়ন্ত্রণ করা যেতে পারে।
ডাউনলোড বন্ধ করার কারণ নির্ধারণ এবং সাফ করা
এক বা সমস্ত ডাউনলোড বন্ধ হওয়ার কারণ নির্ধারণ করা সম্ভব:
কোটলিন
// 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 )
জাভা
// 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 এ স্থায়ী থাকে, এবং যদি অ্যাপ্লিকেশন প্রক্রিয়াটি বন্ধ করে পরে পুনরায় চালু করা হয় তবে তা বজায় থাকে।
সমস্ত ডাউনলোড থামানো এবং পুনরায় শুরু করা হচ্ছে
সমস্ত ডাউনলোড নিম্নলিখিতভাবে থামানো এবং পুনরায় শুরু করা যেতে পারে:
কোটলিন
// Pause all downloads. DownloadService.sendPauseDownloads( context, MyDownloadService::class.java, /* foreground= */ false ) // Resume all downloads. DownloadService.sendResumeDownloads( context, MyDownloadService::class.java, /* foreground= */ false )
জাভা
// 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 এ একটি কমান্ড পাঠিয়েও এগুলি গতিশীলভাবে পরিবর্তন করা যেতে পারে:
কোটলিন
// Set the download requirements. DownloadService.sendSetRequirements( context, MyDownloadService::class.java, requirements, /* foreground= */ false)
জাভা
// 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 সমস্ত ডাউনলোডের অবস্থা জানতে প্রশ্ন করা যেতে পারে, যার মধ্যে যেগুলি সম্পূর্ণ হয়েছে বা ব্যর্থ হয়েছে সেগুলিও অন্তর্ভুক্ত। DownloadManager.getDownloadIndex() কল করে DownloadIndex পাওয়া যেতে পারে। সমস্ত ডাউনলোডের উপর পুনরাবৃত্তি করে এমন একটি কার্সার DownloadIndex.getDownloads() কল করে পাওয়া যেতে পারে। বিকল্পভাবে, DownloadIndex.getDownload() কল করে একটি একক ডাউনলোডের অবস্থা জানতে প্রশ্ন করা যেতে পারে।
DownloadManager এছাড়াও DownloadManager.getCurrentDownloads() প্রদান করে, যা শুধুমাত্র বর্তমান (অর্থাৎ সম্পূর্ণ না হওয়া বা ব্যর্থ) ডাউনলোডের অবস্থা ফেরত দেয়। এই পদ্ধতিটি বিজ্ঞপ্তি এবং অন্যান্য UI উপাদান আপডেট করার জন্য কার্যকর যা বর্তমান ডাউনলোডের অগ্রগতি এবং স্থিতি প্রদর্শন করে।
ডাউনলোডগুলি শুনছি
বর্তমান ডাউনলোডের অবস্থা পরিবর্তন হলে অবহিত হওয়ার জন্য আপনি DownloadManager এ একজন শ্রোতা যোগ করতে পারেন:
কোটলিন
downloadManager.addListener( object : DownloadManager.Listener { // Override methods of interest here. } )
জাভা
downloadManager.addListener( new DownloadManager.Listener() { // Override methods of interest here. });
একটি সুনির্দিষ্ট উদাহরণের জন্য ডেমো অ্যাপের DownloadTracker ক্লাসে DownloadManagerListener দেখুন।
ডাউনলোড করা কন্টেন্ট চালানো হচ্ছে
ডাউনলোড করা কন্টেন্ট চালানো অনলাইন কন্টেন্ট চালানোর মতোই, তবে ডেটা নেটওয়ার্কের পরিবর্তে ডাউনলোড Cache থেকে পড়া হয়।
ডাউনলোড করা কন্টেন্ট চালানোর জন্য, ডাউনলোড করার জন্য ব্যবহৃত একই Cache ইনস্ট্যান্স ব্যবহার করে একটি CacheDataSource.Factory তৈরি করুন এবং প্লেয়ার তৈরি করার সময় এটি DefaultMediaSourceFactory এ ইনজেক্ট করুন:
কোটলিন
// 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()
জাভা
// 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 থেকে পাওয়া যেতে পারে।
মিডিয়াসোর্স কনফিগারেশন
পূর্ববর্তী উদাহরণটি সমস্ত MediaItem এর প্লেব্যাকের জন্য ডাউনলোড ক্যাশে উপলব্ধ করে। আপনি পৃথক MediaSource ইনস্ট্যান্সের জন্য ডাউনলোড ক্যাশে উপলব্ধ করতে পারেন, যা সরাসরি প্লেয়ারে পাঠানো যেতে পারে:
কোটলিন
val mediaSource = ProgressiveMediaSource.Factory(cacheDataSourceFactory) .createMediaSource(MediaItem.fromUri(contentUri)) player.setMediaSource(mediaSource) player.prepare()
জাভা
ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory) .createMediaSource(MediaItem.fromUri(contentUri)); player.setMediaSource(mediaSource); player.prepare();
অ্যাডাপ্টিভ স্ট্রিম ডাউনলোড এবং প্লে করা হচ্ছে
অ্যাডাপ্টিভ স্ট্রিমগুলিতে (যেমন DASH, SmoothStreaming এবং HLS) সাধারণত একাধিক মিডিয়া ট্র্যাক থাকে। প্রায়শই একাধিক ট্র্যাক থাকে যেখানে একই কন্টেন্ট বিভিন্ন মানের থাকে (যেমন SD, HD এবং 4K ভিডিও ট্র্যাক)। একই ধরণের একাধিক ট্র্যাকও থাকতে পারে যেখানে বিভিন্ন কন্টেন্ট থাকে (যেমন বিভিন্ন ভাষায় একাধিক অডিও ট্র্যাক)।
স্ট্রিমিং প্লেব্যাকের জন্য, কোন ট্র্যাকগুলি চালানো হবে তা বেছে নিতে একটি ট্র্যাক নির্বাচক ব্যবহার করা যেতে পারে। একইভাবে, ডাউনলোডের জন্য, কোন ট্র্যাকগুলি ডাউনলোড করা হবে তা বেছে নিতে একটি DownloadHelper ব্যবহার করা যেতে পারে। একটি DownloadHelper সাধারণ ব্যবহার নিম্নলিখিত পদক্ষেপগুলি অনুসরণ করে:
-
DownloadHelper.Factoryইনস্ট্যান্স ব্যবহার করে একটিDownloadHelperতৈরি করুন। সাহায্যকারী প্রস্তুত করুন এবং কলব্যাকের জন্য অপেক্ষা করুন।কোটলিন
val downloadHelper = DownloadHelper.Factory() .setRenderersFactory(DefaultRenderersFactory(context)) .setDataSourceFactory(dataSourceFactory) .create(MediaItem.fromUri(contentUri)) downloadHelper.prepare(callback)
জাভা
DownloadHelper downloadHelper = new DownloadHelper.Factory() .setRenderersFactory(new DefaultRenderersFactory(context)) .setDataSourceFactory(dataSourceFactory) .create(MediaItem.fromUri(contentUri)); downloadHelper.prepare(callback);
- ঐচ্ছিকভাবে,
getMappedTrackInfoএবংgetTrackSelectionsব্যবহার করে ডিফল্ট নির্বাচিত ট্র্যাকগুলি পরিদর্শন করুন এবংclearTrackSelections,replaceTrackSelectionsএবংaddTrackSelectionব্যবহার করে সমন্বয় করুন। - নির্বাচিত ট্র্যাকগুলির জন্য
getDownloadRequestএ কল করে একটিDownloadRequestতৈরি করুন। উপরে বর্ণিত হিসাবে ডাউনলোড যোগ করার জন্য অনুরোধটি আপনারDownloadServiceএ পাঠানো যেতে পারে। -
release()ব্যবহার করে হেল্পারটি ছেড়ে দিন।
ডাউনলোড করা অ্যাডাপ্টিভ কন্টেন্ট প্লেব্যাকের জন্য প্লেয়ার কনফিগার করা এবং উপরে বর্ণিত MediaItem পাস করা প্রয়োজন।
MediaItem তৈরি করার সময়, MediaItem.localConfiguration.streamKeys DownloadRequest এর সাথে মেলে সেট করতে হবে যাতে প্লেয়ারটি শুধুমাত্র ডাউনলোড করা ট্র্যাকগুলির সাবসেটটি চালানোর চেষ্টা করে। MediaItem তৈরি করতে Download.request.toMediaItem এবং DownloadRequest.toMediaItem ব্যবহার করলে আপনার এই সমস্যাটি সমাধান হবে।