এক্সোপ্লেয়ার অফলাইনে প্লেব্যাকের জন্য মিডিয়া ডাউনলোড করার সুবিধা প্রদান করে। বেশিরভাগ ক্ষেত্রে, আপনার অ্যাপ ব্যাকগ্রাউন্ডে থাকলেও ডাউনলোড চলতে থাকাটা কাম্য। এই ধরনের ব্যবহারের জন্য, আপনার অ্যাপের DownloadService ক্লাসটি সাবক্লাস করা উচিত এবং ডাউনলোড যোগ, অপসারণ ও নিয়ন্ত্রণ করার জন্য সার্ভিসটিতে কমান্ড পাঠানো উচিত। নিচের ডায়াগ্রামটিতে এই কাজে জড়িত প্রধান ক্লাসগুলো দেখানো হয়েছে।
-
DownloadService: একটিDownloadManagerআবৃত করে এবং এর কাছে কমান্ডগুলো প্রেরণ করে। এই সার্ভিসটি অ্যাপটি ব্যাকগ্রাউন্ডে থাকলেওDownloadManagerচালু রাখতে সাহায্য করে। -
DownloadManager: একাধিক ডাউনলোড পরিচালনা করে, একটিDownloadIndexথেকে সেগুলোর অবস্থা লোড (এবং সংরক্ষণ) করে এবং নেটওয়ার্ক সংযোগের মতো প্রয়োজনীয়তার উপর ভিত্তি করে ডাউনলোড শুরু ও বন্ধ করে। কন্টেন্ট ডাউনলোড করার জন্য, ম্যানেজারটি সাধারণত একটিHttpDataSourceথেকে ডাউনলোড করা ডেটা পড়ে এবং তা একটিCacheলিখে রাখে। -
DownloadIndex: ডাউনলোডগুলোর অবস্থা সংরক্ষণ করে।
একটি ডাউনলোড পরিষেবা তৈরি করা
একটি DownloadService তৈরি করতে, এটিকে একটি সাবক্লাস হিসেবে তৈরি করুন এবং এর অ্যাবস্ট্রাক্ট মেথডগুলো ইমপ্লিমেন্ট করুন:
-
getDownloadManager(): ব্যবহৃতব্যDownloadManagerফেরত দেয়। -
getScheduler(): একটি ঐচ্ছিকSchedulerরিটার্ন করে, যা অপেক্ষারত ডাউনলোডগুলো এগিয়ে নিয়ে যাওয়ার জন্য প্রয়োজনীয় শর্ত পূরণ হলে সার্ভিসটি পুনরায় চালু করতে পারে। ExoPlayer নিম্নলিখিত ইমপ্লিমেন্টেশনগুলো প্রদান করে:-
PlatformScheduler, যাJobSchedulerব্যবহার করে (সর্বনিম্ন API হলো 21)। অ্যাপের অনুমতির প্রয়োজনীয়তা জানতেPlatformSchedulerজাভাডকস দেখুন। -
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 থেকে MIME টাইপ অনুমান করা যায় না।
একবার তৈরি হয়ে গেলে, ডাউনলোডটি যোগ করার জন্য অনুরোধটি 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তৈরি করুন। হেল্পারটি প্রস্তুত করুন এবং কলব্যাকের জন্য অপেক্ষা করুন। - ঐচ্ছিকভাবে,
getMappedTrackInfoএবংgetTrackSelectionsব্যবহার করে ডিফল্টরূপে নির্বাচিত ট্র্যাকগুলি পরীক্ষা করুন এবংclearTrackSelections,replaceTrackSelectionsওaddTrackSelectionব্যবহার করে প্রয়োজনীয় পরিবর্তন করুন। -
getDownloadRequestকল করে নির্বাচিত ট্র্যাকগুলির জন্য একটিDownloadRequestতৈরি করুন। পূর্বে বর্ণিত পদ্ধতি অনুযায়ী, ডাউনলোডটি যোগ করার জন্য এই অনুরোধটি আপনারDownloadServiceএ পাঠানো যেতে পারে। -
release()ব্যবহার করে হেল্পারটি রিলিজ করুন।
কোটলিন
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);
পূর্বে বর্ণিত পদ্ধতি অনুযায়ী, ডাউনলোড করা অ্যাডাপ্টিভ কন্টেন্ট প্লেব্যাক করার জন্য প্লেয়ারটি কনফিগার করতে হবে এবং সংশ্লিষ্ট MediaItem পাস করতে হবে।
MediaItem তৈরি করার সময়, MediaItem.localConfiguration.streamKeys অবশ্যই DownloadRequest এর সাথে মিলিয়ে সেট করতে হবে, যাতে প্লেয়ারটি শুধুমাত্র ডাউনলোড করা ট্র্যাকগুলোর একটি উপসেট চালানোর চেষ্টা করে। MediaItem তৈরি করার জন্য Download.request.toMediaItem এবং DownloadRequest.toMediaItem ব্যবহার করলে এই কাজটি আপনার জন্য হয়ে যাবে।