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

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

<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-কে স্থানীয় প্লেয়ার ইনস্ট্যান্স হিসেবে সেট করুন। আপনি তারপর মিডিয়া বিজ্ঞপ্তি বা লক স্ক্রিন বিজ্ঞপ্তি থেকে আপনার মোবাইল ও কাস্ট করার সুবিধা চালু থাকা ডিভাইসের মধ্যে মিডিয়া প্লেব্যাক পরিবর্তন করতে পারবেন। আউটপুট রুট লোকাল থেকে রিমোট বা রিমোট থেকে লোকালে পরিবর্তিত হলে, প্লেয়ার ট্রান্সফার ম্যানেজ করার জন্য Media3 Output Switcher ফিচার ব্যবহার করে।

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

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

প্লেয়ারে একটি কম্পোজযোগ্য MediaRouteButton যোগ করুন

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

@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 সেট করার পরে, প্লেয়ারে Cast বোতাম দেখানোর জন্য একটি 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-কে ভিউ হিসেবে যোগ করুন

আপনার activity_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);
}

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