মিডিয়া ডাউনলোড করা

অফলাইনে চালানোর জন্য মিডিয়া ডাউনলোড করার সুবিধা ExoPlayer প্রদান করে। বেশিরভাগ ব্যবহারের ক্ষেত্রে, আপনার অ্যাপ ব্যাকগ্রাউন্ডে থাকলেও ডাউনলোড চলতে থাকলে ভাল হয়। এইসব ব্যবহারের ক্ষেত্রে, আপনার অ্যাপকে DownloadService-এর সাবক্লাস হতে হবে এবং ডাউনলোড যোগ করা, সরানো ও কন্ট্রোল করার জন্য পরিষেবায় কমান্ড পাঠাতে হবে। নিচের ডায়াগ্রামে মূল ক্লাসগুলি দেখানো হয়েছে।

মিডিয়া ডাউনলোড করার ক্লাস। তীরচিহ্নের দিকনির্দেশ থেকে ডেটার
      ফ্লো বোঝা যায়।
ছবি ১. মিডিয়া ডাউনলোড করার ক্লাস। তীরচিহ্ন দিকনির্দেশ ডেটার ফ্লো নির্দেশ করে।
  • DownloadService: DownloadManager-কে র‍্যাপ করে এবং এতে কমান্ড ফরওয়ার্ড করে। অ্যাপ ব্যাকগ্রাউন্ডে থাকলেও, DownloadManager-কে চালু রাখার অনুমতি এই পরিষেবা দেয়।
  • DownloadManager: একাধিক ডাউনলোড ম্যানেজ করে, DownloadIndex থেকে (এবং এতে) সেগুলির স্ট্যাটাস লোড (এবং স্টোর) করে, নেটওয়ার্ক কানেক্টিভিটির মতো প্রয়োজনীয়তার ভিত্তিতে ডাউনলোড শুরু ও বন্ধ করে। কন্টেন্ট ডাউনলোড করতে, ম্যানেজার সাধারণত HttpDataSource থেকে ডাউনলোড করা ডেটা পড়ে, এবং সেটি Cache-এ লেখে।
  • DownloadIndex: ডাউনলোড সংক্রান্ত তথ্য সেভ করে রাখে।

DownloadService তৈরি করা

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 তৈরি করা হচ্ছে

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

জাভা

// 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-এ পাঠান। অ্যাডাপ্টিভ স্ট্রিমের জন্য, DownloadHelper ব্যবহার করে DownloadRequest তৈরি করতে সাহায্য করুন। নিম্নলিখিত উদাহরণ থেকে কীভাবে ডাউনলোড করার অনুরোধ তৈরি করতে হয় তা জানুন:

Kotlin

val downloadRequest = DownloadRequest.Builder(contentId, contentUri).build()

জাভা

DownloadRequest downloadRequest = new DownloadRequest.Builder(contentId, contentUri).build();

এই উদাহরণে, contentId হল কন্টেন্টের অনন্য শনাক্তকারী। contentId-এর পরিবর্তে প্রায়ই contentUri ব্যবহার করা যেতে পারে, তবে অ্যাপগুলি যে আইডি স্কিম তাদের ব্যবহারের ক্ষেত্রে সবচেয়ে উপযুক্ত সেটি ব্যবহার করতে পারে। DownloadRequest.Builder-এ কিছু ঐচ্ছিক সেটারও আছে। যেমন, setKeySetId এবং setData ব্যবহার করে যথাক্রমে DRM এবং কাস্টম ডেটা সেট করা যেতে পারে যা অ্যাপ ডাউনলোড করার সাথে যুক্ত করতে চায়। এছাড়াও, কন্টেন্টের MIME ধরন setMimeType ব্যবহার করে উল্লেখ করা যেতে পারে, এটি এমন ক্ষেত্রে ইঙ্গিত হিসেবে কাজ করে যেখানে MIME ধরন contentUri থেকে অনুমান করা যায় না।

তৈরি করা হয়ে গেলে, DownloadService-এ অনুরোধ পাঠিয়ে ডাউনলোড যোগ করা যেতে পারে:

Kotlin

DownloadService.sendAddDownload(
  context,
  MyDownloadService::class.java,
  downloadRequest,
  /* foreground= */ false,
)

জাভা

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,
)

জাভা

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,
)

জাভা

// 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,
)

জাভা

// 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,
)

জাভা

// 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() প্রদান করে, যা শুধুমাত্র বর্তমান (অর্থাৎ, সম্পূর্ণ বা ব্যর্থ হয়নি) ডাউনলোডের স্ট্যাটাস রিটার্ন করে। এই পদ্ধতিটি বিজ্ঞপ্তি ও অন্যান্য UI কম্পোনেন্ট আপডেট করার জন্য উপযোগী। এটি বর্তমান ডাউনলোডের প্রগ্রেস ও স্ট্যাটাস দেখায়।

ডাউনলোড করা কন্টেন্ট শোনা

বর্তমান ডাউনলোড স্ট্যাটাস পরিবর্তন হলে সেই বিষয়ে বিজ্ঞপ্তি পেতে DownloadManager-এ আপনি একজন লিসনার যোগ করতে পারেন:

Kotlin

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 সেটিতে ইনজেক্ট করুন:

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

জাভা

// 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 পাস করুন। Download.request.toMediaItem ব্যবহার করে Download থেকে অথবা DownloadRequest.toMediaItem ব্যবহার করে সরাসরি DownloadRequest থেকে MediaItem পাওয়া যেতে পারে।

MediaSource কনফিগারেশন

আগের উদাহরণে, সব MediaItemর প্লেব্যাকের জন্য ডাউনলোড ক্যাশে উপলভ্য করা হয়েছে। এছাড়াও, আপনি আলাদা MediaSource ইনস্ট্যান্সের জন্য ডাউনলোড ক্যাশে উপলভ্য করতে পারেন, যা সরাসরি প্লেয়ারে পাস করা যেতে পারে:

Kotlin

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 সাধারণত এইসব ধাপ অনুসরণ করে:

  1. DownloadHelper.Factory ইনস্ট্যান্স ব্যবহার করে DownloadHelper তৈরি করুন। সহায়ক প্রস্তুত করুন এবং কলব্যাকের জন্য অপেক্ষা করুন।
  2. ঐচ্ছিকভাবে, getMappedTrackInfo এবং getTrackSelections ব্যবহার করে ডিফল্ট হিসেবে বেছে নেওয়া ট্র্যাকগুলি চেক করুন এবং clearTrackSelections, replaceTrackSelections ও addTrackSelection ব্যবহার করে অ্যাডজাস্টমেন্ট করুন।
  3. DownloadRequest তৈরি করতে, বেছে নেওয়া ট্র্যাকের জন্য getDownloadRequest কল করুন। আগে যেভাবে বর্ণনা করা হয়েছে সেইভাবে ডাউনলোড যোগ করার জন্য আপনার DownloadService-কে অনুরোধ করা যেতে পারে।
  4. release() ব্যবহার করে হেল্পারকে রিলিজ করুন।

Kotlin

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 ব্যবহার করলে এই বিষয়টি আপনার হয়ে দেখা হবে।