প্লেয়ার ইন্টারফেস

প্লেয়ার হল আপনার অ্যাপের কম্পোনেন্ট যা মিডিয়া আইটেম প্লেব্যাক করতে সাহায্য করে। Media3 Player ইন্টারফেস সাধারণত প্লেয়ারের মাধ্যমে ম্যানেজ করা কার্যকারিতার জন্য একটি আউটলাইন সেট-আপ করে। এর মধ্যে রয়েছে:

  • প্লেব্যাক কন্ট্রোলকে প্রভাবিত করে, যেমন চালানো, পজ করা এবং খোঁজা
  • বর্তমানে চলছে এমন মিডিয়ার প্রপার্টি কোয়েরি করা, যেমন প্লেব্যাক পজিশন
  • মিডিয়া আইটেমের প্লেলিস্ট/সারি ম্যানেজ করা
  • প্লেব্যাক প্রপার্টি কনফিগার করা, যেমন শাফেল করা, রিপিট করা, স্পিড এবং ভলিউম
  • স্ক্রিনে ভিডিও রেন্ডার করা হচ্ছে

এছাড়াও, Media3 Player ইন্টারফেসের একটি ইমপ্লিমেন্টেশন প্রদান করে, যাকে ExoPlayer বলা হয়।

কম্পোনেন্টের মধ্যে একটি সাধারণ ইন্টারফেস

Media3-এর একাধিক কম্পোনেন্ট Player ইন্টারফেস প্রয়োগ করে, যেমন:

কম্পোনেন্ট বিবরণ ও আচরণ সংক্রান্ত নোট
ExoPlayer একটি মিডিয়া প্লেয়ার API এবং Player ইন্টারফেসের ডিফল্ট ইমপ্লিমেন্টেশন।
MediaController প্লেব্যাক কমান্ড পাঠাতে MediaSession-এর সাথে ইন্টার‍্যাক্ট করে। যদি আপনার Player এবং MediaSession Service-এ থাকে যা Activity বা Fragment থেকে আলাদা যেখানে আপনার প্লেয়ারের UI থাকে, তাহলে আপনি MediaController-কে আপনার UI কম্পোনেন্টের প্লেয়ার হিসেবে অ্যাসাইন করতে পারেন যেমন PlayerView বা Player কম্পোজেবল। প্লেব্যাক ও প্লেলিস্ট মেথড কল আপনার MediaSession-এর মাধ্যমে আপনার Player-এ পাঠানো হয়।
MediaBrowser MediaController-এর অফার করা কার্যকারিতা ছাড়াও, উপলভ্য মিডিয়া কন্টেন্ট ব্রাউজ করতে MediaLibrarySession-এর সাথে ইন্টার‍্যাক্ট করে।
SimpleBasePlayer একটি Player ইমপ্লিমেন্টেশন যা ইমপ্লিমেন্ট করার জন্য পদ্ধতির সংখ্যা কমিয়ে ন্যূনতম করে। আপনি MediaSession-এর সাথে কানেক্ট করতে চান এমন কাস্টম প্লেয়ার ব্যবহার করার সময় সহায়ক।
ForwardingSimpleBasePlayer একটি SimpleBasePlayer সাবক্লাস যা প্লেব্যাক অপারেশনকে অন্য Player-এ ফরওয়ার্ড করার জন্য ডিজাইন করা হয়েছে, একই সাথে SimpleBasePlayer-এর মতো একই সামঞ্জস্যপূর্ণ আচরণ কাস্টমাইজেশনের অনুমতি দেয়। নির্দিষ্ট প্লেব্যাক অপারেশন বন্ধ বা পরিবর্তন করতে এই ক্লাস ব্যবহার করুন।
RemoteCastPlayer রিমোট কাস্ট রিসিভার অ্যাপে প্লেব্যাক কন্ট্রোল করার জন্য Player ইমপ্লিমেন্টেশন।
CastPlayer লোকাল ও রিমোট Cast প্লেব্যাক কন্ট্রোল করার জন্য Player ইমপ্লিমেন্টেশন।

যদিও MediaSession, Player ইন্টারফেস প্রয়োগ করে না, এটি তৈরি করার সময় Player প্রয়োজন হয়। অন্যান্য প্রসেস বা থ্রেড থেকে Player-এ অ্যাক্সেস প্রদান করাই এর উদ্দেশ্য।

Media3 প্লেব্যাক আর্কিটেকচার

আপনার কাছে Player-এর অ্যাক্সেস থাকলে, প্লেব্যাক কমান্ড ইস্যু করতে সরাসরি এর মেথড কল করা উচিত। আপনি নিজের প্লেব্যাক বিজ্ঞাপন করতে এবং MediaSession প্রয়োগ করে এক্সটার্নাল সোর্সকে প্লেব্যাক কন্ট্রোল করার অনুমতি দিতে পারবেন। এইসব এক্সটার্নাল সোর্স MediaController প্রয়োগ করে, যা মিডিয়া সেশনের সাথে কানেক্ট করতে এবং প্লেব্যাক কমান্ডের অনুরোধ ইস্যু করতে সাহায্য করে।

ব্যাকগ্রাউন্ডে মিডিয়া চালানোর সময়, আপনাকে মিডিয়া সেশন ও প্লেয়ারকে MediaSessionService বা MediaLibraryService-এর মধ্যে রাখতে হবে যা ফোরগ্রাউন্ড সার্ভিস হিসেবে চলে। আপনি এটি করলে, আপনার অ্যাপে অ্যাক্টিভিটি থেকে প্লেয়ার আলাদা করতে পারবেন যেটিতে প্লেব্যাক কন্ট্রোলের জন্য UI থাকে। এর জন্য আপনাকে মিডিয়া কন্ট্রোলার ব্যবহার করতে হতে পারে।

Media3 প্লেব্যাক কম্পোনেন্ট কীভাবে মিডিয়া অ্যাপ আর্কিটেকচারে ফিট করে তা ডায়াগ্রামে দেখানো হয়েছে।
ছবি ১: Media3-এর আর্কিটেকচারে Player ইন্টারফেস গুরুত্বপূর্ণ ভূমিকা পালন করে।

প্লেয়ার স্টেট

Player ইন্টারফেস প্রয়োগ করা মিডিয়া প্লেয়ারের স্ট্যাটাসে মূলত ৪টি বিভাগের তথ্য থাকে:

  1. প্লেব্যাক স্টেট
  2. মিডিয়া আইটেমের প্লেলিস্ট
    • প্লেব্যাকের জন্য MediaItemটি ইনস্ট্যান্সের একটি সিকোয়েন্স।
    • getCurrentTimeline()-এর মাধ্যমে ফিরিয়ে আনুন
    • Player ইনস্ট্যান্স প্লেলিস্ট অপারেশন পদ্ধতি প্রদান করতে পারে যেমন যোগ করা বা সরানো একটি MediaItem এবং সুবিধা পদ্ধতি যেমন getCurrentMediaItem().
  3. প্লে/পজ প্রপার্টি, যেমন:
    • playWhenReady: ব্যবহারকারী সম্ভব হলে মিডিয়া চালাতে চান নাকি পজ করে রাখতে চান তার ইঙ্গিত
    • প্লেব্যাক বন্ধ থাকার কারণ: প্লেব্যাক কেন বন্ধ আছে তার ইঙ্গিত, যদি প্রযোজ্য হয়, এমনকি playWhenReady যদি true হয়
    • isPlaying: প্লেয়ার বর্তমানে চলছে কিনা তার ইঙ্গিত, যা শুধুমাত্র true হবে যদি প্লেব্যাক স্টেট STATE_READY হয়, playWhenReady হল true এবং প্লেব্যাক সাপ্রেস করা না হয়
  4. প্লেব্যাক পজিশন, যার মধ্যে রয়েছে:

এছাড়াও, Player ইন্টারফেস উপলভ্য ট্র্যাক, মিডিয়া মেটাডেটা, প্লেব্যাক স্পিড, ভলিউম এবং প্লেব্যাকের অন্যান্য সহায়ক প্রপার্টি অ্যাক্সেস করার অনুমতি দেয়।

পরিবর্তন সম্পর্কে শুনুন

Player-এ পরিবর্তন শোনার জন্য Player.Listener ব্যবহার করুন। কীভাবে লিসেনার তৈরি ও ব্যবহার করতে হয় সেই সম্পর্কে বিস্তারিত জানতে প্লেয়ার ইভেন্ট-এ ExoPlayer ডকুমেন্টেশন দেখুন।

মনে রাখবেন, লিসেনার ইন্টারফেসে সাধারণ প্লেব্যাক প্রগ্রেশন ট্র্যাক করার জন্য কোনও কলব্যাক অন্তর্ভুক্ত থাকে না। প্লেব্যাক প্রোগ্রেস ক্রমাগত মনিটর করতে, যেমন প্রোগ্রেস বার UI সেট-আপ করতে, আপনাকে সঠিক বিরতিতে বর্তমান পজিশন কোয়েরি করতে হবে।

Kotlin

fun checkPlaybackPosition(delayMs: Long): Boolean =
  handler.postDelayed(
    {
      val currentPosition = player.currentPosition
      // Update UI based on currentPosition
      checkPlaybackPosition(delayMs)
    },
    delayMs,
  )

জাভা

boolean checkPlaybackPosition(long delayMs) {
  return handler.postDelayed(
      () -> {
        long currentPosition = player.getCurrentPosition();
        // Update UI based on currentPosition
        checkPlaybackPosition(delayMs);
      },
      delayMs);
}

প্লেব্যাক কন্ট্রোল করুন

Player ইন্টারফেস, স্ট্যাটাস ও কন্ট্রোল প্লেব্যাক ম্যানিপুলেট করার অনেক উপায় অফার করে:

কাস্টম Player প্রয়োগ

কাস্টম প্লেয়ার তৈরি করতে, আপনি Media3-তে অন্তর্ভুক্ত SimpleBasePlayer এক্সটেন্ড করতে পারবেন। এই ক্লাসটি Player ইন্টারফেসের একটি বেস ইমপ্লিমেন্টেশন প্রদান করে যাতে আপনাকে ন্যূনতম সংখ্যক পদ্ধতি ইমপ্লিমেন্ট করতে হয়।

getState() পদ্ধতি ওভাররাইড করে শুরু করুন। এই পদ্ধতি কল করার সময় প্লেয়ারের বর্তমান স্ট্যাটাস পপুলেট করবে, যার মধ্যে এগুলি অন্তর্ভুক্ত:

  • উপলভ্য কমান্ডের সেট
  • প্লেব্যাক প্রপার্টি, যেমন প্লেব্যাক স্ট্যাটাস STATE_READY হলে প্লেয়ার চালানো শুরু করা উচিত কিনা, বর্তমানে চলা মিডিয়া আইটেমের ইন্ডেক্স এবং বর্তমান আইটেমের মধ্যে প্লেব্যাক পজিশন

Kotlin

class CustomPlayer(looper: Looper) : SimpleBasePlayer(looper) {
  override fun getState(): State {
    return State.Builder()
      .setAvailableCommands(Commands.EMPTY) // Set which playback commands the player can handle
      // Configure additional playback properties
      .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST)
      .setCurrentMediaItemIndex(0)
      .setContentPositionMs(0)
      .build()
  }
}

জাভা

private static final class CustomPlayer extends SimpleBasePlayer {
  public CustomPlayer(Looper looper) {
    super(looper);
  }

  @Override
  protected State getState() {
    return new State.Builder()
        .setAvailableCommands(Commands.EMPTY) // Set which playback commands the player can handle
        // Configure additional playback properties
        .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST)
        .setCurrentMediaItemIndex(0)
        .setContentPositionMs(0)
        .build();
  }
}

SimpleBasePlayer এনফোর্স করবে যে State যেন স্টেট ভ্যালুর সঠিক কম্বিনেশন দিয়ে তৈরি করা হয়। এটি লিসেনারদের হ্যান্ডেল করবে এবং লিসেনারদের স্ট্যাটাস পরিবর্তন সম্পর্কে জানাবে। আপনাকে ম্যানুয়ালি কোনও স্টেট আপডেট ট্রিগার করতে হলে, invalidateState() কল করুন।

getState() পদ্ধতি ছাড়াও, আপনাকে শুধু সেইসব পদ্ধতি প্রয়োগ করতে হবে যেগুলি আপনার প্লেয়ারের উপলভ্য বলে ঘোষণা করা কমান্ডের জন্য ব্যবহার করা হয়। আপনি যে কার্যকারিতা প্রয়োগ করতে চান তার সাথে সম্পর্কিত ওভাররাইডযোগ্য হ্যান্ডলার পদ্ধতি খুঁজুন। যেমন, COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM এবং COMMAND_SEEK_TO_NEXT_MEDIA_ITEM-এর মতো অপারেশন সাপোর্ট করতে handleSeek() মেথড ওভাররাইড করুন।

Playerটি প্রয়োগ পরিবর্তন করুন

সম্পূর্ণ কাস্টম Player তৈরি করার পরিবর্তে, আপনি ForwardingSimpleBasePlayer ব্যবহার করে আগে থেকে থাকা Player-এর অবস্থা ও আচরণ পরিবর্তন করতে পারবেন। আরও বিবরণের জন্য কাস্টমাইজেশন পৃষ্ঠায় গাইড দেখুন।