CastPlayer ব্যবহার শুরু করা

CastPlayer হল একটি Jetpack Media3 Player ইমপ্লিমেন্টেশন যা লোকাল প্লেব্যাক এবং রিমোট কাস্ট-চালু ডিভাইসে কাস্টিং, দুটিই সাপোর্ট করে। CastPlayer আপনার অ্যাপে কাস্ট করার কার্যকারিতা যোগ করা সহজ করে এবং লোকাল ও রিমোট প্লেব্যাকের মধ্যে নির্বিঘ্নে পরিবর্তন করার জন্য সমৃদ্ধ ফিচার প্রদান করে। আপনার মিডিয়া অ্যাপে কীভাবে CastPlayer ইন্টিগ্রেট করবেন তা এই নির্দেশিকা থেকে জানতে পারবেন।

অন্যান্য প্ল্যাটফর্মের সাথে Cast ইন্টিগ্রেট করতে, Cast SDK দেখুন।

Cast-সক্ষম ডিভাইস কিনুন

CastPlayer পরীক্ষা করতে, আপনার একটি Cast-সক্ষম ডিভাইস প্রয়োজন। বিকল্পের মধ্যে Android TV, Chromecast, স্মার্ট স্পিকার ও স্মার্ট ডিসপ্লে অন্তর্ভুক্ত। আপনার ডিভাইস সেট-আপ করা আছে কিনা এবং সেটি আপনার ডেভেলপমেন্ট মোবাইলের মতো একই ওয়াই-ফাই নেটওয়ার্কে কানেক্ট করা আছে কিনা তা যাচাই করুন।

বিল্ড ডিপেন্ডেন্সি যোগ করুন

CastPlayer ব্যবহার করা শুরু করতে, আপনার অ্যাপ মডিউলের build.gradle ফাইলে AndroidX Media3 এবং CastPlayer ডিপেন্ডেন্সি যোগ করুন।

Kotlin

implementation("androidx.media3:media3-exoplayer:1.11.1")
implementation("androidx.media3:media3-ui:1.11.1")
implementation("androidx.media3:media3-session:1.11.1")
implementation("androidx.media3:media3-cast:1.11.1")

গ্ৰুভি

implementation "androidx.media3:media3-exoplayer:1.11.1"
implementation "androidx.media3:media3-ui:1.11.1"
implementation "androidx.media3:media3-session:1.11.1"
implementation "androidx.media3:media3-cast:1.11.1"

আপনার CastPlayer কনফিগার করুন

CastPlayer কনফিগার করতে, বিকল্প প্রদানকারীর সাথে আপনার AndroidManifest.xml ফাইল আপডেট করুন।

বিকল্প প্রদানকারী

CastPlayer-এর আচরণ কনফিগার করার জন্য একটি বিকল্প প্রদানকারী প্রয়োজন। প্রাথমিক সেট-আপের জন্য, আপনি DefaultCastOptionsProvider আপনার AndroidManifest.xml ফাইলে যোগ করে ব্যবহার করতে পারেন। এটি ডিফল্ট সেটিংস ব্যবহার করে, যার মধ্যে ডিফল্ট রিসিভার অ্যাপ্লিকেশন অন্তর্ভুক্ত।

<application>
  ...
  <meta-data
    android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
    android:value="androidx.media3.cast.DefaultCastOptionsProvider" />
  ...
</application>

কনফিগারেশন কাস্টমাইজ করতে, আপনার নিজস্ব কাস্টম OptionsProvider প্রয়োগ করুন। কীভাবে করবেন তা জানতে CastOptions গাইড দেখুন।

মিডিয়া ট্রান্সফারের জন্য প্রাপক যোগ করুন

আপনার ম্যানিফেস্টে MediaTransferReceiver যোগ করলে, সিস্টেম UI নেটওয়ার্কে Cast-সক্ষম ডিভাইস খুঁজে পায় এবং অ্যাপ অ্যাক্টিভিটি না খুলেই মিডিয়া রি-রুট করে। যেমন, কোনও ব্যবহারকারী মিডিয়া বিজ্ঞপ্তি থেকে আপনার অ্যাপের মিডিয়া চালানো ডিভাইস পরিবর্তন করতে পারেন।

<application>
  ...
  <receiver android:name="androidx.mediarouter.media.MediaTransferReceiver" />
  ...
</application>

CastPlayer তৈরি করা

Cast-এর মাধ্যমে রিমোট প্লেব্যাকের জন্য, আপনার অ্যাপের প্লেব্যাক ম্যানেজ করার ক্ষমতা থাকা উচিত, এমনকি ব্যবহারকারী আপনার অ্যাপ থেকে কোনও অ্যাক্টিভিটির সাথে ইন্টার‍্যাক্ট না করলেও, যেমন সিস্টেম মিডিয়া বিজ্ঞপ্তির মাধ্যমে। এই কারণে, আপনাকে MediaSessionService বা MediaLibraryService-এর মতো কোনও পরিষেবায় ExoPlayer (লোকাল প্লেব্যাকের জন্য) এবং CastPlayer (রিমোট প্লেব্যাকের জন্য) ইনস্ট্যান্স তৈরি করতে হবে। প্রথমে, আপনার ExoPlayer ইনস্ট্যান্স তৈরি করুন এবং তারপর আপনার CastPlayer ইনস্ট্যান্স তৈরি করার সময়, ExoPlayer-কে লোকাল প্লেয়ার ইনস্ট্যান্স হিসেবে সেট করুন। তারপর আপনি মিডিয়া বিজ্ঞপ্তি বা লক স্ক্রিন বিজ্ঞপ্তি থেকে আপনার মোবাইল ও Cast-চালু ডিভাইসের মধ্যে মিডিয়া প্লেব্যাক পাল্টাতে পারবেন। আউটপুট রুট লোকাল থেকে রিমোটে বা রিমোট থেকে লোকালে পরিবর্তন হলে, প্লেয়ার ট্রান্সফার ম্যানেজ করতে Media3 আউটপুট সুইচার ফিচার ব্যবহার করে।

বিজ্ঞপ্তিতে আউটপুট সুইচার UI দেখানো স্ক্রিনশট।
ছবি ১: (ক) মিডিয়া বিজ্ঞপ্তিতে ডিভাইস চিপ (খ) ডিভাইস চিপে ট্যাপ করলে Cast-সক্ষম ডিভাইস দেখানো হয় (গ) লক স্ক্রিন বিজ্ঞপ্তিতে ডিভাইস চিপ

Kotlin

override fun onCreate() {
  super.onCreate()

  val exoPlayer = ExoPlayer.Builder(context).build()
  val castPlayer = CastPlayer.Builder(context).setLocalPlayer(exoPlayer).build()

  mediaSession = MediaSession.Builder(context, castPlayer).build()
}

জাভা

@Override
public void onCreate() {
  super.onCreate();

  ExoPlayer exoPlayer = new ExoPlayer.Builder(context).build();
  CastPlayer castPlayer = new CastPlayer.Builder(context).setLocalPlayer(exoPlayer).build();

  mediaSession =
      new MediaSession.Builder(/* context= */ context, /* player= */ castPlayer).build();
}

UI এলিমেন্ট যোগ করুন

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

MediaRouteButton সেট করুন

আপনার অ্যাক্টিভিটির UI-তে MediaRouteButton যোগ করার চারটি উপায় আছে। আপনার অ্যাপের ডিজাইন ও প্রয়োজনীয়তার উপর নির্ভর করে সেরা বিকল্প বেছে নিন।

  • Compose UI: একটি বোতাম কম্পোজেবল যোগ করুন।
  • Views UI:
    • অ্যাপ বার মেনুতে বোতাম যোগ করুন।
    • PlayerView-এর মধ্যে বোতাম যোগ করুন।
    • স্ট্যান্ডার্ড View হিসেবে বোতাম যোগ করুন।
UI-তে MediaRouteButton দেখানো স্ক্রিনশট।
ছবি ২: (ক) মেনু বারে MediaRouteButton, (খ) ভিউ হিসেবে, (গ) PlayerView-তে এবং (ঘ) Cast-চালু থাকা ডিভাইসের ডায়ালগ।

প্লেয়ারে কম্পোজেবল MediaRouteButton যোগ করা

আপনি প্লেয়ারের UI-তে MediaRouteButton কম্পোজেবল যোগ করতে পারবেন। আরও তথ্যের জন্য, Compose গাইড দেখুন।

@Composable
fun PlayerComposeView(player: Player, modifier: Modifier = Modifier) {
  var controlsVisible by remember { mutableStateOf(false) }

  Box(
    modifier = modifier.clickable { controlsVisible = true },
    contentAlignment = Alignment.Center,
  ) {
    PlayerSurface(player = player, modifier = modifier)
    AnimatedVisibility(visible = controlsVisible, enter = fadeIn(), exit = fadeOut()) {
      Box(modifier = Modifier.fillMaxSize()) {
        MediaRouteButton(modifier = Modifier.align(Alignment.TopEnd))
        PrimaryControls(player = player, modifier = Modifier.align(Alignment.Center))
      }
    }
  }
}

@Composable
fun PrimaryControls(player: Player, modifier: Modifier = Modifier) {
  // ...
}

PlayerView-তে MediaRouteButton যোগ করুন

আপনি সরাসরি PlayerView-এর UI কন্ট্রোলের মধ্যে MediaRouteButton যোগ করতে পারবেন। আপনার PlayerView-এর প্লেয়ার হিসেবে MediaController সেট করার পরে, প্লেয়ারে কাস্ট বোতাম দেখানোর জন্য MediaRouteButtonViewProvider প্রদান করুন।

Kotlin

override fun onStart() {
  super.onStart()

  playerView.player = mediaController
  playerView.setMediaRouteButtonViewProvider(MediaRouteButtonViewProvider())
}

জাভা

@Override
public void onStart() {
  super.onStart();

  playerView.setPlayer(mediaController);
  playerView.setMediaRouteButtonViewProvider(new MediaRouteButtonViewProvider());
}

অ্যাপ বার মেনুতে MediaRouteButton যোগ করুন

অ্যাপ বার মেনুতে MediaRouteButton সেট-আপ করতে, একটি XML মেনু তৈরি করুন এবং আপনার Activity-এ onCreateOptionsMenu ওভাররাইড করুন।

<menu xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:app="http://schemas.android.com/apk/res-auto">
  <item android:id="@+id/media_route_menu_item"
    android:title="@string/media_route_menu_title"
    app:showAsAction="always"
    app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"/>
</menu>

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
  // ...
  menuInflater.inflate(R.menu.sample_media_route_button_menu, menu)
  val menuItemFuture: ListenableFuture<MenuItem> =
    MediaRouteButtonFactory.setUpMediaRouteButton(context, menu, R.id.media_route_menu_item)
  Futures.addCallback(
    menuItemFuture,
    object : FutureCallback<MenuItem> {
      override fun onSuccess(menuItem: MenuItem) {
        // Do something with the menu item.
      }

      override fun onFailure(t: Throwable) {
        // Handle the failure.
      }
    },
    executor,
  )
  // ...
  return true
}

জাভা

@Override
public boolean onCreateOptionsMenu(Menu menu) {
  // ...
  getMenuInflater().inflate(R.menu.sample_media_route_button_menu, menu);
  ListenableFuture<MenuItem> menuItemFuture =
      MediaRouteButtonFactory.setUpMediaRouteButton(context, menu, R.id.media_route_menu_item);
  Futures.addCallback(
      menuItemFuture,
      new FutureCallback<MenuItem>() {
        @Override
        public void onSuccess(MenuItem menuItem) {
          // Do something with the menu item.
        }

        @Override
        public void onFailure(Throwable t) {
          // Handle the failure.
        }
      },
      executor);
  // ...
  return true;
}

MediaRouteButton-কে ভিউ হিসেবে যোগ করুন

আপনার অ্যাক্টিভিটি layout.xml-এ MediaRouteButton সেট-আপ করতে পারবেন।

  <androidx.mediarouter.app.MediaRouteButton
      android:id="@+id/media_route_button"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:mediaRouteButtonTint="@android:color/white" />

MediaRouteButton-এর সেট-আপ সম্পূর্ণ করতে, আপনার Activity কোডে Media3 Cast MediaRouteButtonFactory ব্যবহার করুন।

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)

  findViewById<MediaRouteButton>(R.id.media_route_button)?.also {
    val unused = MediaRouteButtonFactory.setUpMediaRouteButton(context, it)
  }
}

জাভা

@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  // ...
  MediaRouteButton button = findViewById(R.id.media_route_button);
  ListenableFuture<Void> setUpFuture =
      MediaRouteButtonFactory.setUpMediaRouteButton(context, button);
}

অ্যাক্টিভিটি লিসেনার

মিডিয়া প্লেব্যাক লোকেশনে পরিবর্তন শোনার জন্য আপনার Activity-এ একটি Player.Listener তৈরি করুন। playbackType-এর মান PLAYBACK_TYPE_LOCAL এবং PLAYBACK_TYPE_REMOTE-এর মধ্যে পরিবর্তিত হলে, আপনি প্রয়োজন অনুযায়ী UI অ্যাডজাস্ট করতে পারবেন। মেমরি লিক আটকাতে এবং আপনার অ্যাপ যখন দেখা যাবে শুধুমাত্র তখনই লিসনার অ্যাক্টিভিটি সীমাবদ্ধ করতে, onStart-এ লিসনার রেজিস্টার করুন এবং onStop-এ এটি আনরেজিস্টার করুন:

Kotlin

private val playerListener: Player.Listener =
  object : Player.Listener {
    override fun onDeviceInfoChanged(deviceInfo: DeviceInfo) {
      if (deviceInfo.playbackType == DeviceInfo.PLAYBACK_TYPE_LOCAL) {
        // Add UI changes for local playback.
      } else if (deviceInfo.playbackType == DeviceInfo.PLAYBACK_TYPE_REMOTE) {
        // Add UI changes for remote playback.
      }
    }
  }

override fun onStart() {
  super.onStart()
  mediaController.addListener(playerListener)
}

override fun onStop() {
  super.onStop()
  mediaController.removeListener(playerListener)
}

জাভা

private final Player.Listener playerListener =
    new Player.Listener() {
      @Override
      public void onDeviceInfoChanged(DeviceInfo deviceInfo) {
        if (deviceInfo.playbackType == DeviceInfo.PLAYBACK_TYPE_LOCAL) {
          // Add UI changes for local playback.
        } else if (deviceInfo.playbackType == DeviceInfo.PLAYBACK_TYPE_REMOTE) {
          // Add UI changes for remote playback.
        }
      }
    };

@Override
protected void onStart() {
  super.onStart();
  mediaController.addListener(playerListener);
}

@Override
protected void onStop() {
  super.onStop();
  mediaController.removeListener(playerListener);
}

প্লেব্যাক ইভেন্ট শোনা ও তার উত্তর দেওয়ার ব্যাপারে আরও তথ্য পেতে, প্লেয়ার ইভেন্ট নির্দেশিকা দেখুন।