আপনার Android অ্যাপে Cast ইন্টিগ্রেট করুন

Android Sender SDK ব্যবহার করে আপনার Android প্রেরক অ্যাপে কীভাবে Google Cast সহায়তা যোগ করবেন তা এই ডেভেলপার নির্দেশিকায় বর্ণনা করা হয়েছে।

মোবাইল ডিভাইস বা ল্যাপটপ হল প্রেরক যা প্লেব্যাক নিয়ন্ত্রণ করে এবং Google Cast ডিভাইস হল প্রাপক যা টিভিতে কন্টেন্ট দেখায়।

প্রেরক ফ্রেমওয়ার্ক বলতে Cast ক্লাস লাইব্রেরি বাইনারি এবং রানটাইমে প্রেরকের কাছে উপলভ্য সংশ্লিষ্ট রিসোর্সকে বোঝায়। প্রেরক অ্যাপ বা Cast অ্যাপ বলতে এমন অ্যাপকে বোঝায় যা প্রেরকের ডিভাইসেও চলছে। ওয়েব রিসিভার অ্যাপ বলতে Cast-চালু করা ডিভাইসে চলা HTML অ্যাপ্লিকেশনকে বোঝায়।

প্রেরক ফ্রেমওয়ার্ক অ্যাসিঙ্ক্রোনাস কলব্যাক ডিজাইন ব্যবহার করে প্রেরক অ্যাপকে ইভেন্ট সম্পর্কে জানায় এবং Cast অ্যাপ লাইফ সাইকেলের বিভিন্ন অবস্থার মধ্যে ট্রানজিশন করে।

অ্যাপ ফ্লো

নিম্নলিখিত ধাপগুলি প্রেরক Android অ্যাপের জন্য সাধারণ হাই-লেভেল এক্সিকিউশন ফ্লো বর্ণনা করে:

  • Cast ফ্রেমওয়ার্ক অটোমেটিক MediaRouter Activity লাইফসাইকেলের উপর ভিত্তি করে ডিভাইস খোঁজা শুরু করে।
  • ব্যবহারকারী কাস্ট করার বোতামে ক্লিক করলে, ফ্রেমওয়ার্কটি খুঁজে পাওয়া কাস্ট ডিভাইসের তালিকা সহ কাস্ট ডায়ালগ দেখায়।
  • ব্যবহারকারী কোনও Cast ডিভাইস বেছে নিলে, ফ্রেমওয়ার্ক Cast ডিভাইসে Web Receiver অ্যাপ চালু করার চেষ্টা করে।
  • ফ্রেমওয়ার্ক, প্রেরক অ্যাপে কলব্যাক ইনভোক করে যাতে কনফার্ম করা যায় যে Web Receiver অ্যাপ চালু করা হয়েছে।
  • ফ্রেমওয়ার্কটি প্রেরক এবং Web Receiver অ্যাপের মধ্যে একটি কমিউনিকেশন চ্যানেল তৈরি করে।
  • ফ্রেমওয়ার্কটি ওয়েব রিসিভারে মিডিয়া প্লেব্যাক লোড ও নিয়ন্ত্রণ করতে কমিউনিকেশন চ্যানেল ব্যবহার করে।
  • ফ্রেমওয়ার্কটি প্রেরক এবং ওয়েব রিসিভারের মধ্যে মিডিয়া প্লেব্যাক স্ট্যাটাস সিঙ্ক করে: ব্যবহারকারী প্রেরক UI অ্যাকশন করলে, ফ্রেমওয়ার্কটি সেই মিডিয়া কন্ট্রোল অনুরোধগুলি ওয়েব রিসিভারে পাঠায় এবং ওয়েব রিসিভার মিডিয়া স্ট্যাটাস আপডেট পাঠালে, ফ্রেমওয়ার্কটি প্রেরক UI-এর স্ট্যাটাস আপডেট করে।
  • ব্যবহারকারী Cast ডিভাইস থেকে ডিসকানেক্ট করার জন্য Cast বোতামে ক্লিক করলে, ফ্রেমওয়ার্ক Web Receiver থেকে প্রেরক অ্যাপ ডিসকানেক্ট করবে।

Google Cast Android SDK-তে সব ক্লাস, পদ্ধতি ও ইভেন্টের সম্পূর্ণ তালিকা দেখতে, Android-এর জন্য Google Cast Sender API রেফারেন্স দেখুন। আপনার Android অ্যাপে Cast যোগ করার ধাপগুলি নিম্নলিখিত বিভাগে কভার করা হয়েছে।

Android ম্যানিফেস্ট কনফিগার করুন

আপনার অ্যাপের AndroidManifest.xml ফাইলে Cast SDK-এর জন্য নিম্নলিখিত এলিমেন্ট কনফিগার করতে হবে:

uses-sdk

Cast SDK-তে কাজ করে এমন ন্যূনতম ও টার্গেট Android API লেভেল সেট করুন। বর্তমানে ন্যূনতম API লেভেল ২৪ এবং টার্গেট API লেভেল ৩৫।

<uses-sdk
        android:minSdkVersion="24"
        android:targetSdkVersion="35" />

android:theme

Android SDK-এর ন্যূনতম ভার্সনের উপর ভিত্তি করে আপনার অ্যাপের থিম সেট করুন। যেমন, আপনি যদি নিজের থিম প্রয়োগ না করেন, তাহলে ললিপপের আগের কোনও Android SDK ভার্সন টার্গেট করার সময় Theme.AppCompat-এর কোনও ভেরিয়েন্ট ব্যবহার করা উচিত।

<application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.AppCompat" >
       ...
</application>

কাস্ট কনটেক্সট শুরু করুন

ফ্রেমওয়ার্কে একটি গ্লোবাল সিঙ্গেলটন অবজেক্ট, CastContext আছে, যা ফ্রেমওয়ার্কের সব ইন্টার‍্যাকশন সমন্বয় করে।

CastContext সিঙ্গলটন শুরু করার জন্য প্রয়োজনীয় বিকল্প প্রদান করতে আপনার অ্যাপকে অবশ্যই OptionsProvider ইন্টারফেস প্রয়োগ করতে হবে। OptionsProvider-এ CastOptions-এর একটি ইনস্ট্যান্স রয়েছে যাতে ফ্রেমওয়ার্কের আচরণকে প্রভাবিত করে এমন বিকল্প রয়েছে। এর মধ্যে সবচেয়ে গুরুত্বপূর্ণ হল ওয়েব রিসিভার অ্যাপ্লিকেশন আইডি, যা ডিসকভারি ফলাফল ফিল্টার করতে এবং কাস্ট সেশন শুরু হলে ওয়েব রিসিভার অ্যাপ চালু করতে ব্যবহার করা হয়।

Kotlin
class CastOptionsProvider : OptionsProvider {
    override fun getCastOptions(context: Context): CastOptions {
        return Builder()
            .setReceiverApplicationId(context.getString(R.string.app_id))
            .build()
    }

    override fun getAdditionalSessionProviders(context: Context): List<SessionProvider>? {
        return null
    }
}
Java
public class CastOptionsProvider implements OptionsProvider {
    @Override
    public CastOptions getCastOptions(Context context) {
        CastOptions castOptions = new CastOptions.Builder()
            .setReceiverApplicationId(context.getString(R.string.app_id))
            .build();
        return castOptions;
    }
    @Override
    public List<SessionProvider> getAdditionalSessionProviders(Context context) {
        return null;
    }
}

প্রেরক অ্যাপের AndroidManifest.xml ফাইলে মেটাডেটা ফিল্ড হিসেবে আপনাকে অবশ্যই প্রয়োগ করা OptionsProvider-এর সম্পূর্ণ নাম ঘোষণা করতে হবে:

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

CastContext.getSharedInstance() কল করা হলে CastContext লেজি ইনিশিয়ালাইজ করা হয়।

Kotlin
class MyActivity : FragmentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        val castContext = CastContext.getSharedInstance(this)
    }
}
Java
public class MyActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        CastContext castContext = CastContext.getSharedInstance(this);
    }
}

Cast UX উইজেট

Cast ফ্রেমওয়ার্ক এমন উইজেট প্রদান করে যা Cast ডিজাইন চেকলিস্টের সাথে সামঞ্জস্যপূর্ণ:

  • ইন্ট্রোডাক্টরি ওভারলে: ফ্রেমওয়ার্ক একটি কাস্টম ভিউ প্রদান করে, IntroductoryOverlay, যা প্রথমবার রিসিভার উপলভ্য হলে ব্যবহারকারীর মনোযোগ কাস্ট করার বোতামের দিকে আকর্ষণ করার জন্য দেখানো হয়। প্রেরক অ্যাপ শিরোনাম টেক্সটের টেক্সট ও অবস্থান কাস্টমাইজ করতে পারে।

  • কাস্ট করার বোতাম: কাস্ট ডিভাইস উপলভ্য থাকুক বা না থাকুক, কাস্ট করার বোতাম দেখা যায়। ব্যবহারকারী প্রথমবার কাস্ট করার বোতামে ক্লিক করলে, একটি কাস্ট ডায়ালগ দেখানো হয় যেখানে খুঁজে পাওয়া ডিভাইসের তালিকা থাকে। ডিভাইস কানেক্ট করা থাকাকালীন ব্যবহারকারী কাস্ট করার বোতামে ক্লিক করলে, এটি বর্তমান মিডিয়া মেটাডেটা (যেমন, শিরোনাম, রেকর্ডিং স্টুডিওর নাম এবং থাম্বনেল ছবি) দেখায় অথবা ব্যবহারকারীকে কাস্ট ডিভাইস থেকে ডিসকানেক্ট করার অনুমতি দেয়। "কাস্ট করার বোতাম"-কে কখনও কখনও "কাস্ট করার আইকন" হিসেবে উল্লেখ করা হয়।

  • মিনি কন্ট্রোলার: ব্যবহারকারী কন্টেন্ট কাস্ট করার সময় বর্তমান কন্টেন্ট পৃষ্ঠা থেকে নেভিগেট করে অন্য পৃষ্ঠায় চলে গেলে অথবা প্রেরক অ্যাপে অন্য স্ক্রিনে কন্ট্রোলার বড় করলে, স্ক্রিনের নিচে মিনি কন্ট্রোলার দেখানো হয়। এর ফলে ব্যবহারকারী বর্তমানে কাস্ট করা মিডিয়া মেটাডেটা দেখতে এবং প্লেব্যাক কন্ট্রোল করতে পারেন।

  • এক্সপ্যান্ডেড কন্ট্রোলার: ব্যবহারকারী কন্টেন্ট কাস্ট করার সময়, মিডিয়া বিজ্ঞপ্তি বা মিনি কন্ট্রোলারে ক্লিক করলে, এক্সপ্যান্ডেড কন্ট্রোলার চালু হয়, যা বর্তমানে চলা মিডিয়া মেটাডেটা দেখায় এবং মিডিয়া প্লেব্যাক নিয়ন্ত্রণ করার জন্য একাধিক বোতাম প্রদান করে।

  • বিজ্ঞপ্তি: শুধুমাত্র Android-এ উপলভ্য। ব্যবহারকারী কন্টেন্ট কাস্ট করার সময় প্রেরক অ্যাপ থেকে নেভিগেট করে বেরিয়ে এলে, মিডিয়া বিজ্ঞপ্তি দেখানো হয় যাতে বর্তমানে কাস্ট করা মিডিয়া মেটাডেটা ও প্লেব্যাক কন্ট্রোল দেখা যায়।

  • লক স্ক্রিন: শুধুমাত্র Android-এ। ব্যবহারকারী কন্টেন্ট কাস্ট করার সময় লক স্ক্রিনে নেভিগেট করলে (অথবা ডিভাইসের সময়সীমা শেষ হয়ে গেলে), মিডিয়া লক স্ক্রিন কন্ট্রোল দেখানো হয় যা বর্তমানে কাস্ট করা মিডিয়া মেটাডেটা এবং প্লেব্যাক কন্ট্রোল দেখায়।

আপনার অ্যাপে কীভাবে এইসব উইজেট যোগ করবেন তার বিবরণ নিম্নলিখিত গাইডে দেওয়া আছে।

কাস্ট করার বোতাম যোগ করুন

Android MediaRouter API-কে এমনভাবে ডিজাইন করা হয়েছে যাতে সেকেন্ডারি ডিভাইসে মিডিয়া ডিসপ্লে ও প্লেব্যাক করা যায়। যেসব Android অ্যাপ MediaRouter API ব্যবহার করে, সেগুলির ইউজার ইন্টারফেসে কাস্ট করার বোতাম থাকা উচিত, যাতে ব্যবহারকারীরা কাস্ট ডিভাইসের মতো সেকেন্ডারি ডিভাইসে মিডিয়া চালানোর জন্য মিডিয়া রুট বেছে নিতে পারেন।

ফ্রেমওয়ার্কের মাধ্যমে Cast button হিসেবে MediaRouteButton যোগ করা খুব সহজ হয়ে যায়। আপনাকে প্রথমে একটি মেনু আইটেম বা একটি MediaRouteButton যোগ করতে হবে xml ফাইলে যা আপনার মেনুকে সংজ্ঞায়িত করে এবং ব্যবহার করে CastButtonFactory ফ্রেমওয়ার্কের সাথে এটি তারের জন্য।

// To add a Cast button, add the following snippet.
// menu.xml
<item
    android:id="@+id/media_route_menu_item"
    android:title="@string/media_route_menu_title"
    app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
    app:showAsAction="always" />
Kotlin
// Then override the onCreateOptionMenu() for each of your activities.
// MyActivity.kt
override fun onCreateOptionsMenu(menu: Menu): Boolean {
    super.onCreateOptionsMenu(menu)
    menuInflater.inflate(R.menu.main, menu)
    CastButtonFactory.setUpMediaRouteButton(
        applicationContext,
        menu,
        R.id.media_route_menu_item
    )
    return true
}
Java
// Then override the onCreateOptionMenu() for each of your activities.
// MyActivity.java
@Override public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    getMenuInflater().inflate(R.menu.main, menu);
    CastButtonFactory.setUpMediaRouteButton(getApplicationContext(),
                                            menu,
                                            R.id.media_route_menu_item);
    return true;
}

তারপর, আপনার Activity যদি FragmentActivity থেকে ইনহেরিট করে, তাহলে আপনি লেআউটে MediaRouteButton যোগ করতে পারবেন।

// activity_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:gravity="center_vertical"
   android:orientation="horizontal" >

   <androidx.mediarouter.app.MediaRouteButton
       android:id="@+id/media_route_button"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_weight="1"
       android:mediaRouteTypes="user"
       android:visibility="gone" />

</LinearLayout>
Kotlin
// MyActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_layout)

    mMediaRouteButton = findViewById<View>(R.id.media_route_button) as MediaRouteButton
    CastButtonFactory.setUpMediaRouteButton(applicationContext, mMediaRouteButton)

    mCastContext = CastContext.getSharedInstance(this)
}
Java
// MyActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_layout);

   mMediaRouteButton = (MediaRouteButton) findViewById(R.id.media_route_button);
   CastButtonFactory.setUpMediaRouteButton(getApplicationContext(), mMediaRouteButton);

   mCastContext = CastContext.getSharedInstance(this);
}

থিম ব্যবহার করে কাস্ট করার বোতামের চেহারা সেট করতে, কাস্ট করার বোতাম কাস্টমাইজ করুন দেখুন।

ডিভাইস ডিসকভারি কনফিগার করুন

ডিভাইস খোঁজার বিষয়টি সম্পূর্ণভাবে CastContext ম্যানেজ করে। CastContext শুরু করার সময়, প্রেরক অ্যাপ Web Receiver অ্যাপ্লিকেশন আইডি নির্দিষ্ট করে এবং CastOptions-এ supportedNamespaces সেট করার মাধ্যমে ঐচ্ছিকভাবে নেমস্পেস ফিল্টারিংয়ের অনুরোধ করতে পারে। CastContext ইন্টার্নালি MediaRouter-এর রেফারেন্স হোল্ড করে এবং নিম্নলিখিত শর্তে ডিসকভারি প্রসেস শুরু করবে:

  • ডিভাইস খোঁজার লেটেন্সি ও ব্যাটারির ব্যবহার ব্যালেন্স করার জন্য ডিজাইন করা অ্যালগরিদমের ভিত্তিতে, প্রেরক অ্যাপ ফোরগ্রাউন্ডে প্রবেশ করলে, মাঝে মাঝে অটোমেটিক খোঁজা শুরু হবে।
  • Cast ডায়ালগ খোলা আছে।
  • Cast SDK একটি Cast সেশন ফিরিয়ে আনার চেষ্টা করছে।

কাস্ট ডায়ালগ বন্ধ হয়ে গেলে বা প্রেরক অ্যাপ ব্যাকগ্রাউন্ডে চলে গেলে, খোঁজার প্রসেস বন্ধ হয়ে যাবে।

Kotlin
class CastOptionsProvider : OptionsProvider {
    companion object {
        const val CUSTOM_NAMESPACE = "urn:x-cast:custom_namespace"
    }

    override fun getCastOptions(appContext: Context): CastOptions {
        val supportedNamespaces: MutableList<String> = ArrayList()
        supportedNamespaces.add(CUSTOM_NAMESPACE)

        return CastOptions.Builder()
            .setReceiverApplicationId(context.getString(R.string.app_id))
            .setSupportedNamespaces(supportedNamespaces)
            .build()
    }

    override fun getAdditionalSessionProviders(context: Context): List<SessionProvider>? {
        return null
    }
}
Java
class CastOptionsProvider implements OptionsProvider {
    public static final String CUSTOM_NAMESPACE = "urn:x-cast:custom_namespace";

    @Override
    public CastOptions getCastOptions(Context appContext) {
        List<String> supportedNamespaces = new ArrayList<>();
        supportedNamespaces.add(CUSTOM_NAMESPACE);

        CastOptions castOptions = new CastOptions.Builder()
            .setReceiverApplicationId(context.getString(R.string.app_id))
            .setSupportedNamespaces(supportedNamespaces)
            .build();
        return castOptions;
    }

    @Override
    public List<SessionProvider> getAdditionalSessionProviders(Context context) {
        return null;
    }
}

সেশন ম্যানেজমেন্ট কীভাবে কাজ করে

Cast SDK-তে Cast সেশনের ধারণাটি চালু করা হয়েছে, যার মাধ্যমে কোনও ডিভাইসে কানেক্ট করা, ওয়েব রিসিভার অ্যাপ চালু করা (বা তাতে যোগ দেওয়া), সেই অ্যাপে কানেক্ট করা এবং মিডিয়া কন্ট্রোল চ্যানেল শুরু করার ধাপগুলি একত্রিত করা হয়। Cast সেশন এবং ওয়েব রিসিভার লাইফ সাইকেল সম্পর্কে আরও জানতে অ্যাপ্লিকেশন লাইফ সাইকেল গাইড দেখুন।

সেশনগুলি SessionManager ক্লাস দ্বারা পরিচালিত হয়, যা আপনার অ্যাপ CastContext.getSessionManager()-এর মাধ্যমে অ্যাক্সেস করতে পারে। Session ক্লাসের সাবক্লাস দিয়ে স্বতন্ত্র সেশন দেখানো হয়। যেমন, CastSession কাস্ট ডিভাইসের সাথে সেশন দেখায়। আপনার অ্যাপ SessionManager.getCurrentCastSession()-এর মাধ্যমে বর্তমানে অ্যাক্টিভ Cast সেশন অ্যাক্সেস করতে পারবে।

আপনার অ্যাপ SessionManagerListener ক্লাস ব্যবহার করে সেশন ইভেন্ট মনিটর করতে পারে, যেমন তৈরি করা, সাসপেন্ড করা, আবার শুরু করা এবং বন্ধ করা। সেশন অ্যাক্টিভ থাকার সময় অস্বাভাবিক/হঠাৎ বন্ধ হয়ে গেলে, ফ্রেমওয়ার্ক অটোমেটিক আবার চালু করার চেষ্টা করে।

MediaRouter ডায়ালগ থেকে ব্যবহারকারীর জেসচারের ভিত্তিতে সেশন অটোমেটিক তৈরি ও বন্ধ করা হয়।

Cast শুরু করার সময় হওয়া সমস্যা আরও ভালোভাবে বুঝতে, অ্যাপ CastContext#getCastReasonCodeForCastStatusCode(int) ব্যবহার করে সেশন শুরু করার সময় হওয়া সমস্যাকে CastReasonCodes-এ কনভার্ট করতে পারে। মনে রাখবেন যে সেশন শুরু করার সময় কিছু সমস্যা (যেমন CastReasonCodes#CAST_CANCELLED) হওয়া স্বাভাবিক এবং এগুলি সমস্যা হিসেবে লগ করা উচিত নয়।

সেশনের জন্য স্ট্যাটাস পরিবর্তন সম্পর্কে আপনাকে সচেতন হতে হলে, আপনি SessionManagerListener প্রয়োগ করতে পারেন। এই উদাহরণটি Activity-এ CastSession-এর উপলভ্যতা শোনে।

Kotlin
class MyActivity : Activity() {
    private var mCastSession: CastSession? = null
    private lateinit var mCastContext: CastContext
    private lateinit var mSessionManager: SessionManager
    private val mSessionManagerListener: SessionManagerListener<CastSession> =
        SessionManagerListenerImpl()

    private inner class SessionManagerListenerImpl : SessionManagerListener<CastSession?> {
        override fun onSessionStarting(session: CastSession?) {}

        override fun onSessionStarted(session: CastSession?, sessionId: String) {
            invalidateOptionsMenu()
        }

        override fun onSessionStartFailed(session: CastSession?, error: Int) {
            val castReasonCode = mCastContext.getCastReasonCodeForCastStatusCode(error)
            // Handle error
        }

        override fun onSessionSuspended(session: CastSession?, reason Int) {}

        override fun onSessionResuming(session: CastSession?, sessionId: String) {}

        override fun onSessionResumed(session: CastSession?, wasSuspended: Boolean) {
            invalidateOptionsMenu()
        }

        override fun onSessionResumeFailed(session: CastSession?, error: Int) {}

        override fun onSessionEnding(session: CastSession?) {}

        override fun onSessionEnded(session: CastSession?, error: Int) {
            finish()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mCastContext = CastContext.getSharedInstance(this)
        mSessionManager = mCastContext.sessionManager
        mSessionManager.addSessionManagerListener(mSessionManagerListener, CastSession::class.java)
    }

    override fun onResume() {
        super.onResume()
        mCastSession = mSessionManager.currentCastSession
    }

    override fun onDestroy() {
        super.onDestroy()
        mSessionManager.removeSessionManagerListener(mSessionManagerListener, CastSession::class.java)
    }
}
Java
public class MyActivity extends Activity {
    private CastContext mCastContext;
    private CastSession mCastSession;
    private SessionManager mSessionManager;
    private SessionManagerListener<CastSession> mSessionManagerListener =
            new SessionManagerListenerImpl();

    private class SessionManagerListenerImpl implements SessionManagerListener<CastSession> {
        @Override
        public void onSessionStarting(CastSession session) {}
        @Override
        public void onSessionStarted(CastSession session, String sessionId) {
            invalidateOptionsMenu();
        }
        @Override
        public void onSessionStartFailed(CastSession session, int error) {
            int castReasonCode = mCastContext.getCastReasonCodeForCastStatusCode(error);
            // Handle error
        }
        @Override
        public void onSessionSuspended(CastSession session, int reason) {}
        @Override
        public void onSessionResuming(CastSession session, String sessionId) {}
        @Override
        public void onSessionResumed(CastSession session, boolean wasSuspended) {
            invalidateOptionsMenu();
        }
        @Override
        public void onSessionResumeFailed(CastSession session, int error) {}
        @Override
        public void onSessionEnding(CastSession session) {}
        @Override
        public void onSessionEnded(CastSession session, int error) {
            finish();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mCastContext = CastContext.getSharedInstance(this);
        mSessionManager = mCastContext.getSessionManager();
        mSessionManager.addSessionManagerListener(mSessionManagerListener, CastSession.class);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mCastSession = mSessionManager.getCurrentCastSession();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mSessionManager.removeSessionManagerListener(mSessionManagerListener, CastSession.class);
    }
}

স্ট্রিম ট্রান্সফার করার ফিচার

সেশন স্টেট সংরক্ষণ করা হল স্ট্রিম ট্রান্সফারের ভিত্তি, যেখানে ব্যবহারকারীরা ভয়েস কমান্ড, Google Home অ্যাপ বা স্মার্ট ডিসপ্লে ব্যবহার করে বিভিন্ন ডিভাইসে বর্তমান অডিও ও ভিডিও স্ট্রিম ট্রান্সফার করতে পারবেন। একটি ডিভাইসে (সোর্স) মিডিয়া চলা বন্ধ হয়ে যায় এবং অন্য ডিভাইসে (ডেস্টিনেশন) চালু থাকে। লেটেস্ট ফার্মওয়্যার সহ যেকোনও Cast ডিভাইস স্ট্রিম ট্রান্সফারের সোর্স বা ডেস্টিনেশন হিসেবে কাজ করতে পারে।

স্ট্রিম ট্রান্সফার বা এক্সপ্যানশনের সময় নতুন ডেস্টিনেশন ডিভাইস পেতে, CastSession#addCastListener ব্যবহার করে Cast.Listener রেজিস্টার করুন। তারপর onDeviceNameChanged কলব্যাকের সময় CastSession#getCastDevice() নম্বরে কল করুন।

আরও তথ্যের জন্য ওয়েব রিসিভারে স্ট্রিম ট্রান্সফার করার ফিচার দেখুন।

অটোমেটিক আবার কানেক্ট করা

ফ্রেমওয়ার্ক একটি ReconnectionService প্রদান করে যা প্রেরক অ্যাপের মাধ্যমে চালু করা যেতে পারে যাতে অনেক সূক্ষ্ম কর্নার কেসে আবার কানেক্ট করার বিষয়টি ম্যানেজ করা যায়, যেমন:

  • সাময়িকভাবে ওয়াই-ফাই কানেকশন চলে গেলে তা আগের অবস্থায় ফিরিয়ে আনা
  • ডিভাইস স্লিপ মোড থেকে রিকভার করুন
  • অ্যাপ ব্যাকগ্রাউন্ডে চলে যাওয়ার সমস্যা থেকে রিকভার করা
  • অ্যাপ ক্র্যাশ করলে রিকভার করুন

এই পরিষেবা সাধারণত চালু করা থাকে এবং CastOptions.Builder থেকে বন্ধ করা যেতে পারে।

আপনার গ্রেডেল ফাইলে অটো-মার্জ চালু করা থাকলে, এই পরিষেবা আপনার অ্যাপের ম্যানিফেস্টে অটোমেটিক মার্জ করা যেতে পারে।

মিডিয়া সেশন থাকলে ফ্রেমওয়ার্ক পরিষেবা শুরু করবে এবং মিডিয়া সেশন শেষ হলে পরিষেবা বন্ধ করে দেবে।

মিডিয়া কন্ট্রোল কীভাবে কাজ করে

Cast ফ্রেমওয়ার্ক Cast 2.x থেকে RemoteMediaPlayer ক্লাসকে বাতিল করে নতুন ক্লাস RemoteMediaClient ব্যবহার করে, যা আরও সুবিধাজনক API-এর সেটে একই কার্যকারিতা প্রদান করে এবং GoogleApiClient-এ পাস করার প্রয়োজন হয় না।

আপনার অ্যাপ মিডিয়া নেমস্পেস সাপোর্ট করে এমন কোনও ওয়েব রিসিভার অ্যাপের সাথে CastSession তৈরি করলে, ফ্রেমওয়ার্কের মাধ্যমে অটোমেটিক RemoteMediaClient-এর একটি ইনস্ট্যান্স তৈরি হবে; আপনার অ্যাপ CastSession ইনস্ট্যান্সে getRemoteMediaClient() পদ্ধতি কল করে এটি অ্যাক্সেস করতে পারবে।

RemoteMediaClient-এর সব পদ্ধতি যা ওয়েব রিসিভারকে অনুরোধ পাঠায়, তা একটি PendingResult অবজেক্ট রিটার্ন করবে যা সেই অনুরোধ ট্র্যাক করতে ব্যবহার করা যেতে পারে।

এটি আশা করা হচ্ছে যে RemoteMediaClient-এর ইনস্ট্যান্স আপনার অ্যাপের একাধিক অংশ এবং ফ্রেমওয়ার্কের কিছু ইন্টার্নাল কম্পোনেন্ট, যেমন পারসিস্টেন্ট মিনি কন্ট্রোলার এবং বিজ্ঞপ্তি পরিষেবা শেয়ার করতে পারে। সেই উদ্দেশ্যে, এই ইনস্ট্যান্স RemoteMediaClient.Listener-এর একাধিক ইনস্ট্যান্সের রেজিস্ট্রেশন সাপোর্ট করে।

মিডিয়া মেটাডেটা সেট করুন

MediaMetadata ক্লাসটি আপনি Cast করতে চান এমন একটি মিডিয়া আইটেম সম্পর্কে তথ্য উপস্থাপন করে। নিম্নলিখিত উদাহরণটি একটি সিনেমার নতুন MediaMetadata ইনস্ট্যান্স তৈরি করে এবং শিরোনাম, সাবটাইটেল এবং দুটি ছবি সেট করে।

Kotlin
val movieMetadata = MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE)

movieMetadata.putString(MediaMetadata.KEY_TITLE, mSelectedMedia.getTitle())
movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, mSelectedMedia.getStudio())
movieMetadata.addImage(WebImage(Uri.parse(mSelectedMedia.getImage(0))))
movieMetadata.addImage(WebImage(Uri.parse(mSelectedMedia.getImage(1))))
Java
MediaMetadata movieMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE);

movieMetadata.putString(MediaMetadata.KEY_TITLE, mSelectedMedia.getTitle());
movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, mSelectedMedia.getStudio());
movieMetadata.addImage(new WebImage(Uri.parse(mSelectedMedia.getImage(0))));
movieMetadata.addImage(new WebImage(Uri.parse(mSelectedMedia.getImage(1))));

মিডিয়া মেটাডেটা সহ ছবির ব্যবহার সম্পর্কে জানতে ছবি বেছে নেওয়া দেখুন।

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

নিচে দেখানো কোডের মতো আপনার অ্যাপ কোনও মিডিয়া আইটেম লোড করতে পারে। প্রথমে, MediaInfo ইনস্ট্যান্স তৈরি করতে মিডিয়ার মেটাডেটার সাথে MediaInfo.Builder ব্যবহার করুন। বর্তমান CastSession থেকে RemoteMediaClient পান, তারপর সেই RemoteMediaClient-এ MediaInfo লোড করুন। RemoteMediaClient ব্যবহার করে ওয়েব রিসিভারে চলা মিডিয়া প্লেয়ার অ্যাপ চালান, পজ করুন ও অন্যভাবে নিয়ন্ত্রণ করুন।

Kotlin
val mediaInfo = MediaInfo.Builder(mSelectedMedia.getUrl())
    .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
    .setContentType("videos/mp4")
    .setMetadata(movieMetadata)
    .setStreamDuration(mSelectedMedia.getDuration() * 1000)
    .build()
val remoteMediaClient = mCastSession.getRemoteMediaClient()
remoteMediaClient.load(MediaLoadRequestData.Builder().setMediaInfo(mediaInfo).build())
Java
MediaInfo mediaInfo = new MediaInfo.Builder(mSelectedMedia.getUrl())
        .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
        .setContentType("videos/mp4")
        .setMetadata(movieMetadata)
        .setStreamDuration(mSelectedMedia.getDuration() * 1000)
        .build();
RemoteMediaClient remoteMediaClient = mCastSession.getRemoteMediaClient();
remoteMediaClient.load(new MediaLoadRequestData.Builder().setMediaInfo(mediaInfo).build());

এছাড়াও, মিডিয়া ট্র্যাক ব্যবহার করা সংক্রান্ত বিভাগটি দেখুন।

4K ভিডিও ফর্ম্যাট

আপনার মিডিয়া কোন ভিডিও ফর্ম্যাটে আছে তা চেক করতে, VideoInfo-এর বর্তমান ইনস্ট্যান্স পেতে getVideoInfo() MediaStatus-এ ব্যবহার করুন। এই ইনস্ট্যান্সে HDR টিভি ফর্ম্যাটের ধরন এবং পিক্সেল অনুযায়ী ডিসপ্লের উচ্চতা ও প্রস্থের তথ্য থাকে। 4K ফর্ম্যাটের ভেরিয়েন্টগুলি ধ্রুবক HDR_TYPE_* দ্বারা নির্দেশিত হয়।

একাধিক ডিভাইসে রিমোট কন্ট্রোল বিজ্ঞপ্তি

কোনও ব্যবহারকারী কাস্ট করার সময়, একই নেটওয়ার্কে থাকা অন্যান্য Android ডিভাইস একটি বিজ্ঞপ্তি পাবে যাতে তারাও প্লেব্যাক নিয়ন্ত্রণ করতে পারে। যেসব ডিভাইসে এই ধরনের বিজ্ঞপ্তি পাওয়া যায়, সেগুলির ক্ষেত্রে 'সেটিংস' অ্যাপে গিয়ে Google > Google Cast > রিমোট কন্ট্রোল বিজ্ঞপ্তি দেখুন বিকল্প থেকে বিজ্ঞপ্তি বন্ধ করা যাবে। (বিজ্ঞপ্তিতে সেটিংস অ্যাপের শর্টকাট অন্তর্ভুক্ত থাকে।) আরও জানতে, Cast রিমোট কন্ট্রোল বিজ্ঞপ্তি দেখুন।

মিনি কন্ট্রোলার যোগ করুন

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

ফ্রেমওয়ার্কটি একটি কাস্টম ভিউ, MiniControllerFragment প্রদান করে, যা আপনি প্রতিটি অ্যাক্টিভিটির লেআউট ফাইলের নিচে যোগ করতে পারেন, যেখানে আপনি মিনি কন্ট্রোলার দেখাতে চান।

<fragment
    android:id="@+id/castMiniController"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:visibility="gone"
    class="com.google.android.gms.cast.framework.media.widget.MiniControllerFragment" />

আপনার প্রেরক অ্যাপ কোনও ভিডিও বা অডিও লাইভ স্ট্রিম চালালে, SDK মিনি কন্ট্রোলারে প্লে/পজ বোতামের পরিবর্তে অটোমেটিক প্লে/স্টপ বোতাম দেখায়।

এই কাস্টম ভিউয়ের শীর্ষক ও সাবটাইটেলের টেক্সট কেমন দেখতে হবে তা সেট করতে এবং বোতাম বেছে নিতে, মিনি কন্ট্রোলার কাস্টমাইজ করুন দেখুন।

বড় করা কন্ট্রোলার যোগ করুন

Google Cast ডিজাইন চেকলিস্টের জন্য প্রয়োজন যে, কাস্ট করা মিডিয়ার জন্য প্রেরক অ্যাপ যেন একটি এক্সপ্যান্ড করা কন্ট্রোলার প্রদান করে। মিনি কন্ট্রোলারের ফুল স্ক্রিন ভার্সন হল এক্সপ্যান্ডেড কন্ট্রোলার।

Cast SDK, এক্সপ্যান্ড করা কন্ট্রোলারের জন্য একটি উইজেট প্রদান করে, যাকে ExpandedControllerActivity বলা হয়। এটি একটি অ্যাবস্ট্রাক্ট ক্লাস, কাস্ট করার বোতাম যোগ করতে আপনাকে সাবক্লাস করতে হবে।

প্রথমে, কাস্ট করার বোতাম প্রদান করার জন্য এক্সপ্যান্ডেড কন্ট্রোলারের জন্য একটি নতুন মেনু রিসোর্স ফাইল তৈরি করুন:

<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:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
            app:showAsAction="always"/>

</menu>

ExpandedControllerActivity-এর এক্সটেনশন হিসেবে নতুন ক্লাস তৈরি করুন।

Kotlin
class ExpandedControlsActivity : ExpandedControllerActivity() {
    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        super.onCreateOptionsMenu(menu)
        menuInflater.inflate(R.menu.expanded_controller, menu)
        CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.media_route_menu_item)
        return true
    }
}
Java
public class ExpandedControlsActivity extends ExpandedControllerActivity {
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.expanded_controller, menu);
        CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.media_route_menu_item);
        return true;
    }
}

এখন application ট্যাগের মধ্যে অ্যাপ ম্যানিফেস্টে আপনার নতুন অ্যাক্টিভিটি ঘোষণা করুন:

<application>
...
<activity
        android:name=".expandedcontrols.ExpandedControlsActivity"
        android:label="@string/app_name"
        android:launchMode="singleTask"
        android:theme="@style/Theme.CastVideosDark"
        android:screenOrientation="portrait"
        android:parentActivityName="com.google.sample.cast.refplayer.VideoBrowserActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
    </intent-filter>
</activity>
...
</application>

আপনার নতুন অ্যাক্টিভিটিতে টার্গেট অ্যাক্টিভিটি সেট করতে, CastOptionsProvider এডিট করুন এবং NotificationOptions ও CastMediaOptions পরিবর্তন করুন:

Kotlin
override fun getCastOptions(context: Context): CastOptions? {
    val notificationOptions = NotificationOptions.Builder()
        .setTargetActivityClassName(ExpandedControlsActivity::class.java.name)
        .build()
    val mediaOptions = CastMediaOptions.Builder()
        .setNotificationOptions(notificationOptions)
        .setExpandedControllerActivityClassName(ExpandedControlsActivity::class.java.name)
        .build()

    return CastOptions.Builder()
        .setReceiverApplicationId(context.getString(R.string.app_id))
        .setCastMediaOptions(mediaOptions)
        .build()
}
Java
public CastOptions getCastOptions(Context context) {
    NotificationOptions notificationOptions = new NotificationOptions.Builder()
            .setTargetActivityClassName(ExpandedControlsActivity.class.getName())
            .build();
    CastMediaOptions mediaOptions = new CastMediaOptions.Builder()
            .setNotificationOptions(notificationOptions)
            .setExpandedControllerActivityClassName(ExpandedControlsActivity.class.getName())
            .build();

    return new CastOptions.Builder()
            .setReceiverApplicationId(context.getString(R.string.app_id))
            .setCastMediaOptions(mediaOptions)
            .build();
}

রিমোট মিডিয়া লোড হওয়ার সময় আপনার নতুন অ্যাক্টিভিটি দেখাতে LocalPlayerActivity loadRemoteMedia পদ্ধতি আপডেট করুন:

Kotlin
private fun loadRemoteMedia(position: Int, autoPlay: Boolean) {
    val remoteMediaClient = mCastSession?.remoteMediaClient ?: return

    remoteMediaClient.registerCallback(object : RemoteMediaClient.Callback() {
        override fun onStatusUpdated() {
            val intent = Intent(this@LocalPlayerActivity, ExpandedControlsActivity::class.java)
            startActivity(intent)
            remoteMediaClient.unregisterCallback(this)
        }
    })

    remoteMediaClient.load(
        MediaLoadRequestData.Builder()
            .setMediaInfo(mSelectedMedia)
            .setAutoplay(autoPlay)
            .setCurrentTime(position.toLong()).build()
    )
}
Java
private void loadRemoteMedia(int position, boolean autoPlay) {
    if (mCastSession == null) {
        return;
    }
    final RemoteMediaClient remoteMediaClient = mCastSession.getRemoteMediaClient();
    if (remoteMediaClient == null) {
        return;
    }
    remoteMediaClient.registerCallback(new RemoteMediaClient.Callback() {
        @Override
        public void onStatusUpdated() {
            Intent intent = new Intent(LocalPlayerActivity.this, ExpandedControlsActivity.class);
            startActivity(intent);
            remoteMediaClient.unregisterCallback(this);
        }
    });
    remoteMediaClient.load(new MediaLoadRequestData.Builder()
            .setMediaInfo(mSelectedMedia)
            .setAutoplay(autoPlay)
            .setCurrentTime(position).build());
}

আপনার প্রেরক অ্যাপ কোনও ভিডিও বা অডিও লাইভ স্ট্রিম চালালে, SDK এক্সপ্যান্ড করা কন্ট্রোলারে প্লে/পজ বোতামের জায়গায় অটোমেটিক প্লে/স্টপ বোতাম দেখায়।

থিম ব্যবহার করে অ্যাপের লুক সেট করতে, কোন বোতাম দেখানো হবে তা বেছে নিতে এবং কাস্টম বোতাম যোগ করতে, এক্সপ্যান্ডেড কন্ট্রোলার কাস্টমাইজ করুন দেখুন।

ভলিউম কন্ট্রোল

ফ্রেমওয়ার্ক অটোমেটিক প্রেরক অ্যাপের ভলিউম ম্যানেজ করে। ফ্রেমওয়ার্ক অটোমেটিক প্রেরক ও ওয়েব রিসিভার অ্যাপ সিঙ্ক করে যাতে প্রেরক UI সবসময় ওয়েব রিসিভারের উল্লেখ করা ভলিউম রিপোর্ট করে।

ফিজিক্যাল বোতামের মাধ্যমে ভলিউম কন্ট্রোল

Android-এ, Jelly Bean বা তার পরবর্তী যেকোনও ভার্সন ব্যবহার করা ডিভাইসের জন্য ডিফল্ট হিসেবে Web Receiver-এ Cast সেশনের ভলিউম পরিবর্তন করতে প্রেরক ডিভাইসের ফিজিক্যাল বোতাম ব্যবহার করা যেতে পারে।

Jelly Bean-এর আগে ফিজিক্যাল বোতামের মাধ্যমে ভলিউম কন্ট্রোল

Jelly Bean-এর থেকে পুরনো Android ডিভাইসে Web Receiver ডিভাইসের ভলিউম কন্ট্রোল করার জন্য ফিজিক্যাল ভলিউম কী ব্যবহার করতে, প্রেরক অ্যাপকে তাদের অ্যাক্টিভিটিতে dispatchKeyEvent ওভাররাইড করতে হবে এবং CastContext.onDispatchVolumeKeyEventBeforeJellyBean() কল করতে হবে:

Kotlin
class MyActivity : FragmentActivity() {
    override fun dispatchKeyEvent(event: KeyEvent): Boolean {
        return (CastContext.getSharedInstance(this)
            .onDispatchVolumeKeyEventBeforeJellyBean(event)
                || super.dispatchKeyEvent(event))
    }
}
Java
class MyActivity extends FragmentActivity {
    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        return CastContext.getSharedInstance(this)
            .onDispatchVolumeKeyEventBeforeJellyBean(event)
            || super.dispatchKeyEvent(event);
    }
}

বিজ্ঞপ্তি ও লক স্ক্রিনে মিডিয়া কন্ট্রোল যোগ করুন

শুধুমাত্র Android-এর ক্ষেত্রে, Google Cast ডিজাইন চেকলিস্টে প্রেরক অ্যাপের প্রয়োজন হয় যাতে বিজ্ঞপ্তিতে মিডিয়া কন্ট্রোল প্রয়োগ করা যায় এবং লক স্ক্রিনে, যেখানে প্রেরক কাস্ট করছে কিন্তু প্রেরক অ্যাপে ফোকাস নেই। ফ্রেমওয়ার্ক MediaNotificationService এবং MediaIntentReceiver প্রদান করে যাতে প্রেরক অ্যাপ বিজ্ঞপ্তি এবং লক স্ক্রিনে মিডিয়া কন্ট্রোল তৈরি করতে পারে।

প্রেরক কাস্ট করার সময় MediaNotificationService রান করে এবং ইমেজ থাম্বনেল ও বর্তমান কাস্টিং আইটেম, প্লে/পজ বোতাম ও স্টপ বোতাম সহ বিজ্ঞপ্তি দেখাবে।

MediaIntentReceiver হল একটি BroadcastReceiver যা বিজ্ঞপ্তি থেকে ব্যবহারকারীর অ্যাকশন ম্যানেজ করে।

আপনার অ্যাপ NotificationOptions-এর মাধ্যমে লক স্ক্রিন থেকে বিজ্ঞপ্তি ও মিডিয়া কন্ট্রোল কনফিগার করতে পারে। বিজ্ঞপ্তিতে কোন কন্ট্রোল বোতাম দেখানো হবে এবং ব্যবহারকারী বিজ্ঞপ্তিতে ট্যাপ করলে কোন Activity খোলা হবে তা আপনার অ্যাপ কনফিগার করতে পারে। অ্যাকশন স্পষ্টভাবে উল্লেখ করা না থাকলে, ডিফল্ট ভ্যালু, MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK এবং MediaIntentReceiver.ACTION_STOP_CASTING ব্যবহার করা হবে।

Kotlin
// Example showing 4 buttons: "rewind", "play/pause", "forward" and "stop casting".
val buttonActions: MutableList<String> = ArrayList()
buttonActions.add(MediaIntentReceiver.ACTION_REWIND)
buttonActions.add(MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK)
buttonActions.add(MediaIntentReceiver.ACTION_FORWARD)
buttonActions.add(MediaIntentReceiver.ACTION_STOP_CASTING)

// Showing "play/pause" and "stop casting" in the compat view of the notification.
val compatButtonActionsIndices = intArrayOf(1, 3)

// Builds a notification with the above actions. Each tap on the "rewind" and "forward" buttons skips 30 seconds.
// Tapping on the notification opens an Activity with class VideoBrowserActivity.
val notificationOptions = NotificationOptions.Builder()
    .setActions(buttonActions, compatButtonActionsIndices)
    .setSkipStepMs(30 * DateUtils.SECOND_IN_MILLIS)
    .setTargetActivityClassName(VideoBrowserActivity::class.java.name)
    .build()
Java
// Example showing 4 buttons: "rewind", "play/pause", "forward" and "stop casting".
List<String> buttonActions = new ArrayList<>();
buttonActions.add(MediaIntentReceiver.ACTION_REWIND);
buttonActions.add(MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK);
buttonActions.add(MediaIntentReceiver.ACTION_FORWARD);
buttonActions.add(MediaIntentReceiver.ACTION_STOP_CASTING);

// Showing "play/pause" and "stop casting" in the compat view of the notification.
int[] compatButtonActionsIndices = new int[]{1, 3};

// Builds a notification with the above actions. Each tap on the "rewind" and "forward" buttons skips 30 seconds.
// Tapping on the notification opens an Activity with class VideoBrowserActivity.
NotificationOptions notificationOptions = new NotificationOptions.Builder()
    .setActions(buttonActions, compatButtonActionsIndices)
    .setSkipStepMs(30 * DateUtils.SECOND_IN_MILLIS)
    .setTargetActivityClassName(VideoBrowserActivity.class.getName())
    .build();

বিজ্ঞপ্তি ও লক স্ক্রিন থেকে মিডিয়া কন্ট্রোল দেখানোর সুবিধা ডিফল্ট হিসেবে চালু করা থাকে এবং CastMediaOptions.Builder-এ নাল সহ setNotificationOptions কল করে বন্ধ করা যেতে পারে। বর্তমানে, বিজ্ঞপ্তি চালু থাকলে লক স্ক্রিন ফিচার চালু থাকে।

Kotlin
// ... continue with the NotificationOptions built above
val mediaOptions = CastMediaOptions.Builder()
    .setNotificationOptions(notificationOptions)
    .build()
val castOptions: CastOptions = Builder()
    .setReceiverApplicationId(context.getString(R.string.app_id))
    .setCastMediaOptions(mediaOptions)
    .build()
Java
// ... continue with the NotificationOptions built above
CastMediaOptions mediaOptions = new CastMediaOptions.Builder()
        .setNotificationOptions(notificationOptions)
        .build();
CastOptions castOptions = new CastOptions.Builder()
        .setReceiverApplicationId(context.getString(R.string.app_id))
        .setCastMediaOptions(mediaOptions)
        .build();

আপনার প্রেরক অ্যাপ কোনও ভিডিও বা অডিও লাইভ স্ট্রিম চালালে, SDK বিজ্ঞপ্তি কন্ট্রোলে প্লে/পজ বোতামের পরিবর্তে অটোমেটিক প্লে/স্টপ বোতাম দেখায় তবে লক স্ক্রিন কন্ট্রোলে নয়।

মনে রাখবেন: Lollipop-এর আগের ভার্সনের ডিভাইসে লক স্ক্রিন কন্ট্রোল দেখাতে, RemoteMediaClient আপনার হয়ে অডিও ফোকাসের জন্য অটোমেটিক অনুরোধ করবে।

সমস্যা ম্যানেজ করা

প্রেরক অ্যাপের জন্য সমস্ত ত্রুটি কলব্যাক পরিচালনা করা এবং Cast লাইফ সাইকেলের প্রতিটি পর্যায়ের জন্য সেরা প্রতিক্রিয়া নির্ধারণ করা খুবই গুরুত্বপূর্ণ। অ্যাপটি ব্যবহারকারীকে সমস্যার ডায়ালগ দেখাতে পারে অথবা এটি Web Receiver-এর সাথে কানেকশন বন্ধ করার সিদ্ধান্ত নিতে পারে।