CastPlayer দিয়ে শুরু করা

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

অন্যান্য প্ল্যাটফর্মের সাথে কাস্টকে একীভূত করতে, কাস্ট SDK দেখুন।

একটি কাস্ট-সক্ষম ডিভাইস পান

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

বিল্ড নির্ভরতা যোগ করুন

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

কোটলিন

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

খাঁজকাটা

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

আপনার 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>

একটি কাস্টপ্লেয়ার তৈরি করুন

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

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

কোটলিন

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 যোগ করার চারটি উপায় আছে। আপনার অ্যাপের ডিজাইন এবং প্রয়োজনীয়তার উপর নির্ভর করে সেরা পছন্দটি।

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

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

আপনি আপনার প্লেয়ারের UI তে MediaRouteButton Composable যোগ করতে পারেন। আরও তথ্যের জন্য, Compose নির্দেশিকাটি দেখুন।

কোটলিন

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.media3.cast.MediaRouteButton

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

কোটলিন

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 মেনু তৈরি করুন এবং আপনার ActivityonCreateOptionsMenu ওভাররাইড করুন।

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

কোটলিন

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)
    ...
}

জাভা

@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);
    ...
}

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

তুমি তোমার অ্যাক্টিভিটি লেআউট.এক্সএমএল-এ একটি 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 ব্যবহার করুন।

কোটলিন

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) {
    ...
    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 এ এটি নিবন্ধনমুক্ত করুন:

কোটলিন

import androidx.media3.common.DeviceInfo
import androidx.media3.common.Player

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

জাভা

import androidx.media3.common.DeviceInfo;
import androidx.media3.common.Player;

private 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);
}

প্লেব্যাক ইভেন্ট শোনা এবং সাড়া দেওয়ার বিষয়ে আরও তথ্যের জন্য, প্লেয়ার ইভেন্ট গাইড দেখুন।