Cast को अपने Android ऐप्लिकेशन में इंटिग्रेट करें

इस डेवलपर गाइड में बताया गया है कि Android Sender SDK का इस्तेमाल करके, अपने Android सेंडर ऐप्लिकेशन में Google Cast की सुविधा कैसे जोड़ी जा सकती है.

मोबाइल डिवाइस या लैपटॉप, भेजने वाला डिवाइस होता है. इससे कॉन्टेंट चलाने की सुविधा कंट्रोल की जाती है. वहीं, Google Cast की सुविधा वाला डिवाइस, पाने वाला डिवाइस होता है. यह टीवी पर कॉन्टेंट दिखाता है.

सेंडर फ़्रेमवर्क का मतलब, Cast क्लास लाइब्रेरी बाइनरी और उससे जुड़ी उन संसाधनों से है जो सेंडर पर रनटाइम के दौरान मौजूद होते हैं. सेंडर ऐप्लिकेशन या कास्ट ऐप्लिकेशन का मतलब, सेंडर पर चल रहे किसी ऐप्लिकेशन से है. वेब रिसीवर ऐप्लिकेशन, Cast की सुविधा वाले डिवाइस पर चलने वाले एचटीएमएल ऐप्लिकेशन को कहते हैं.

सेंडर फ़्रेमवर्क, एसिंक्रोनस कॉलबैक डिज़ाइन का इस्तेमाल करता है. इससे सेंडर ऐप्लिकेशन को इवेंट के बारे में सूचना मिलती है. साथ ही, Cast ऐप्लिकेशन के लाइफ़साइकल की अलग-अलग स्थितियों के बीच ट्रांज़िशन होता है.

ऐप्लिकेशन फ़्लो

यहां दिए गए तरीके में, Android ऐप्लिकेशन से ईमेल भेजने की सामान्य प्रोसेस के बारे में बताया गया है:

  • कास्ट फ़्रेमवर्क, Activity के लाइफ़साइकल के आधार पर, डिवाइस ढूंढने की प्रोसेस को अपने-आप शुरू कर देता है MediaRouter.
  • जब उपयोगकर्ता 'कास्ट बटन' पर क्लिक करता है, तो फ़्रेमवर्क, खोजे गए कास्ट डिवाइसों की सूची के साथ कास्ट डायलॉग दिखाता है.
  • जब उपयोगकर्ता कोई कास्ट डिवाइस चुनता है, तो फ़्रेमवर्क उस कास्ट डिवाइस पर Web Receiver ऐप्लिकेशन लॉन्च करने की कोशिश करता है.
  • फ़्रेमवर्क, भेजने वाले ऐप्लिकेशन में कॉलबैक शुरू करता है. इससे यह पुष्टि की जाती है कि WebReceiver ऐप्लिकेशन लॉन्च हो गया है.
  • यह फ़्रेमवर्क, मैसेज भेजने वाले और Web Receiver ऐप्लिकेशन के बीच एक कम्यूनिकेशन चैनल बनाता है.
  • यह फ़्रेमवर्क, वेब रिसीवर पर मीडिया चलाने की सुविधा को लोड करने और उसे कंट्रोल करने के लिए, कम्यूनिकेशन चैनल का इस्तेमाल करता है.
  • यह फ़्रेमवर्क, मीडिया चलाने की स्थिति को सेंडर और वेब रिसीवर के बीच सिंक करता है: जब उपयोगकर्ता, सेंडर यूज़र इंटरफ़ेस (यूआई) पर कोई कार्रवाई करता है, तो फ़्रेमवर्क, मीडिया कंट्रोल करने के उन अनुरोधों को वेब रिसीवर को भेजता है. साथ ही, जब वेब रिसीवर, मीडिया की स्थिति से जुड़े अपडेट भेजता है, तो फ़्रेमवर्क, सेंडर यूज़र इंटरफ़ेस (यूआई) की स्थिति को अपडेट करता है.
  • जब उपयोगकर्ता, कास्ट किए जा रहे डिवाइस से डिसकनेक्ट करने के लिए कास्ट बटन पर क्लिक करता है, तो फ़्रेमवर्क, सेंडर ऐप्लिकेशन को वेब रिसीवर से डिसकनेक्ट कर देगा.

Google Cast Android SDK में मौजूद सभी क्लास, तरीकों, और इवेंट की पूरी सूची देखने के लिए, Android के लिए Google Cast Sender API का रेफ़रंस देखें. यहां दिए गए सेक्शन में, Android ऐप्लिकेशन में कास्ट करने की सुविधा जोड़ने का तरीका बताया गया है.

Android मेनिफ़ेस्ट कॉन्फ़िगर करना

आपके ऐप्लिकेशन की AndroidManifest.xml फ़ाइल में, Cast SDK के लिए इन एलिमेंट को कॉन्फ़िगर करना ज़रूरी है:

uses-sdk

Android के उन एपीआई लेवल को सेट करें जिन पर Cast SDK काम करता है. फ़िलहाल, कम से कम एपीआई लेवल 24 और टारगेट एपीआई लेवल 35 है.

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

android:theme

Android SDK के कम से कम वर्शन के आधार पर, अपने ऐप्लिकेशन का थीम सेट करें. उदाहरण के लिए, अगर आपको अपनी थीम लागू नहीं करनी है, तो Android के Lollipop से पहले के वर्शन वाले Android SDK को टारगेट करते समय, आपको Theme.AppCompat के किसी वैरिएंट का इस्तेमाल करना चाहिए.

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

कास्ट कॉन्टेक्स्ट को शुरू करना

फ़्रेमवर्क में एक ग्लोबल सिंगलटन ऑब्जेक्ट, CastContext होता है. यह फ़्रेमवर्क के सभी इंटरैक्शन को मैनेज करता है.

आपके ऐप्लिकेशन में OptionsProvider इंटरफ़ेस लागू होना चाहिए, ताकि CastContext सिंगलटन को शुरू करने के लिए ज़रूरी विकल्प दिए जा सकें. 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;
    }
}

आपको लागू किए गए OptionsProvider का पूरा नाम, भेजने वाले ऐप्लिकेशन की AndroidManifest.xml फ़ाइल में मेटाडेटा फ़ील्ड के तौर पर एलान करना होगा:

<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 फ़्रेमवर्क, ऐसे विजेट उपलब्ध कराता है जो Cast डिज़ाइन चेकलिस्ट के मुताबिक होते हैं:

  • इंट्रोडक्ट्री ओवरले: फ़्रेमवर्क, कस्टम व्यू उपलब्ध कराता है, IntroductoryOverlay, जो उपयोगकर्ता को तब दिखाया जाता है, जब पहली बार कोई रिसीवर उपलब्ध होता है. इससे उपयोगकर्ता का ध्यान Cast बटन की ओर जाता है. सेंडर ऐप्लिकेशन, टाइटल के टेक्स्ट और उसकी जगह को पसंद के मुताबिक बना सकता है.

  • कास्ट बटन: कास्ट डिवाइसों के उपलब्ध होने या न होने पर भी, कास्ट बटन दिखता है. जब उपयोगकर्ता पहली बार Cast बटन पर क्लिक करता है, तो उसे Cast डायलॉग दिखता है. इसमें खोजे गए डिवाइसों की सूची होती है. जब डिवाइस कनेक्ट होता है, तब उपयोगकर्ता के Cast बटन पर क्लिक करने से, मौजूदा मीडिया का मेटाडेटा दिखता है. जैसे, टाइटल, रिकॉर्डिंग स्टूडियो का नाम, और थंबनेल इमेज. इसके अलावा, उपयोगकर्ता को Cast डिवाइस से डिस्कनेक्ट करने का विकल्प भी मिलता है. "कास्ट बटन" को कभी-कभी "कास्ट आइकॉन" भी कहा जाता है.

  • मिनी कंट्रोलर: जब उपयोगकर्ता कॉन्टेंट कास्ट कर रहा हो और उसने मौजूदा कॉन्टेंट पेज या बड़े कंट्रोलर से हटकर, भेजने वाले ऐप्लिकेशन की किसी दूसरी स्क्रीन पर नेविगेट किया हो, तो स्क्रीन के सबसे नीचे मिनी कंट्रोलर दिखता है. इससे उपयोगकर्ता को, फ़िलहाल कास्ट किए जा रहे मीडिया का मेटाडेटा देखने और प्लेबैक को कंट्रोल करने की सुविधा मिलती है.

  • बड़ा किया गया कंट्रोलर: जब उपयोगकर्ता कॉन्टेंट कास्ट कर रहा होता है, तब मीडिया सूचना या मिनी कंट्रोलर पर क्लिक करने से बड़ा किया गया कंट्रोलर लॉन्च होता है. इसमें, फ़िलहाल चल रहे मीडिया का मेटाडेटा दिखता है. साथ ही, मीडिया प्लेबैक को कंट्रोल करने के लिए कई बटन मिलते हैं.

  • सूचना: सिर्फ़ Android पर उपलब्ध है. जब उपयोगकर्ता कॉन्टेंट कास्ट कर रहा होता है और सेंडर ऐप्लिकेशन से हट जाता है, तो मीडिया सूचना दिखती है. इसमें, मौजूदा समय में कास्ट किए जा रहे मीडिया का मेटाडेटा और प्लेबैक कंट्रोल दिखते हैं.

  • लॉक स्क्रीन: सिर्फ़ Android के लिए. जब उपयोगकर्ता कॉन्टेंट कास्ट कर रहा होता है और लॉक स्क्रीन पर नेविगेट करता है या डिवाइस टाइम आउट हो जाता है, तो मीडिया लॉक स्क्रीन कंट्रोल दिखता है. इसमें, फ़िलहाल कास्ट किए जा रहे मीडिया का मेटाडेटा और चलाने के कंट्रोल दिखते हैं.

यहां दी गई गाइड में, इन विजेट को अपने ऐप्लिकेशन में जोड़ने का तरीका बताया गया है.

कास्ट करने का बटन जोड़ना

Android MediaRouter API, सेकंडरी डिवाइसों पर मीडिया डिसप्ले और प्लेबैक की सुविधा देने के लिए डिज़ाइन किए गए हैं. MediaRouter एपीआई का इस्तेमाल करने वाले Android ऐप्लिकेशन को अपने यूज़र इंटरफ़ेस में कास्ट बटन शामिल करना चाहिए. इससे लोग, मीडिया चलाने के लिए कोई मीडिया रूट चुन पाएंगे. जैसे, कास्ट डिवाइस जैसे किसी दूसरे डिवाइस पर मीडिया चलाना.

इस फ़्रेमवर्क की मदद से, MediaRouteButton को Cast button के तौर पर जोड़ना बहुत आसान है. आपको सबसे पहले, मेन्यू तय करने वाली XML फ़ाइल में कोई मेन्यू आइटम या MediaRouteButton जोड़ना होगा. इसके बाद, इसे फ़्रेमवर्क से जोड़ने के लिए 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 SDK, कास्ट सेशन को वापस लाने की कोशिश कर रहा है.

कास्ट करने की सुविधा वाला डायलॉग बंद होने या भेजने वाले ऐप्लिकेशन के बैकग्राउंड में जाने पर, डिवाइसों का पता लगाने की प्रोसेस बंद हो जाएगी.

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, कास्ट सेशन का कॉन्सेप्ट पेश करता है. इसे सेट अप करने के लिए, डिवाइस से कनेक्ट करने, Web Receiver ऐप्लिकेशन लॉन्च करने (या उसमें शामिल होने), उससे कनेक्ट करने, और मीडिया कंट्रोल चैनल शुरू करने के चरणों को एक साथ पूरा किया जाता है. कास्ट सेशन और वेब रिसीवर के लाइफ़ साइकल के बारे में ज़्यादा जानने के लिए, वेब रिसीवर की ऐप्लिकेशन के लाइफ़ साइकल से जुड़ी गाइड देखें.

सेशन को क्लास SessionManager मैनेज करती है. आपका ऐप्लिकेशन, CastContext.getSessionManager() के ज़रिए इसे ऐक्सेस कर सकता है. अलग-अलग सेशन को क्लास Session की सबक्लास के तौर पर दिखाया जाता है. उदाहरण के लिए, CastSession का मतलब है कि सेशन, कास्ट डिवाइसों से हुए हैं. आपका ऐप्लिकेशन, SessionManager.getCurrentCastSession() के ज़रिए, चालू कास्ट सेशन को ऐक्सेस कर सकता है.

आपका ऐप्लिकेशन, सेशन इवेंट को मॉनिटर करने के लिए SessionManagerListener क्लास का इस्तेमाल कर सकता है. जैसे, सेशन बनाना, निलंबित करना, फिर से शुरू करना, और खत्म करना. जब सेशन चालू होता है, तो फ़्रेमवर्क असामान्य/अचानक बंद होने की स्थिति में, अपने-आप फिर से शुरू होने की कोशिश करता है.

MediaRouter डायलॉग से उपयोगकर्ता के जेस्चर के जवाब में, सेशन अपने-आप बनते और बंद होते हैं.

कास्टिंग शुरू करने से जुड़ी गड़बड़ियों को बेहतर तरीके से समझने के लिए, ऐप्लिकेशन 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 ऐप्लिकेशन या स्मार्ट डिसप्ले का इस्तेमाल करके, मौजूदा ऑडियो और वीडियो स्ट्रीम को अलग-अलग डिवाइसों पर ट्रांसफ़र कर सकते हैं. मीडिया, एक डिवाइस (सोर्स) पर चलना बंद हो जाता है और दूसरे डिवाइस (डेस्टिनेशन) पर चलने लगता है. कास्ट करने की सुविधा वाले किसी भी डिवाइस पर, स्ट्रीम ट्रांसफ़र के लिए सोर्स या डेस्टिनेशन के तौर पर काम किया जा सकता है. इसके लिए, डिवाइस पर फ़र्मवेयर का नया वर्शन होना ज़रूरी है.

स्ट्रीम ट्रांसफ़र या बढ़ाने के दौरान, नए डेस्टिनेशन डिवाइस को पाने के लिए, CastSession#addCastListener का इस्तेमाल करके, Cast.Listener रजिस्टर करें. इसके बाद, onDeviceNameChanged कॉलबैक के दौरान CastSession#getCastDevice() को कॉल करें.

ज़्यादा जानकारी के लिए, वेब रिसीवर पर स्ट्रीम ट्रांसफ़र करना लेख पढ़ें.

अपने-आप फिर से कनेक्ट होने की सुविधा

फ़्रेमवर्क, ReconnectionService उपलब्ध कराता है. इसे भेजने वाला ऐप्लिकेशन चालू कर सकता है. इससे कई खास मामलों में फिर से कनेक्ट करने की सुविधा को मैनेज किया जा सकता है. जैसे:

  • कुछ समय के लिए वाई-फ़ाई बंद होने पर, उसे फिर से चालू करने के लिए
  • डिवाइस के स्लीप मोड से वापस आना
  • ऐप्लिकेशन को बैकग्राउंड में ले जाने के बाद वापस लाना
  • ऐप्लिकेशन क्रैश होने पर डेटा वापस पाना

यह सेवा डिफ़ॉल्ट रूप से चालू होती है. इसे CastOptions.Builder में जाकर बंद किया जा सकता है.

अगर आपकी gradle फ़ाइल में ऑटो-मर्ज की सुविधा चालू है, तो इस सेवा को आपके ऐप्लिकेशन के मेनिफ़ेस्ट में अपने-आप मर्ज किया जा सकता है.

मीडिया सेशन शुरू होने पर, फ़्रेमवर्क सेवा शुरू कर देगा. मीडिया सेशन खत्म होने पर, फ़्रेमवर्क सेवा बंद कर देगा.

मीडिया कंट्रोल की सुविधा कैसे काम करती है

Cast फ़्रेमवर्क, Cast 2.x में उपलब्ध RemoteMediaPlayer क्लास को बंद कर रहा है. इसके बजाय, RemoteMediaClient नाम की नई क्लास उपलब्ध कराई जा रही है. यह क्लास, ज़्यादा सुविधाजनक एपीआई के सेट में वही फ़ंक्शन उपलब्ध कराती है. साथ ही, इसमें GoogleApiClient को पास करने की ज़रूरत नहीं होती.

जब आपका ऐप्लिकेशन, मीडिया नेमस्पेस के साथ काम करने वाले वेब रिसीवर ऐप्लिकेशन के साथ CastSession बनाता है, तो फ़्रेमवर्क RemoteMediaClient का एक इंस्टेंस अपने-आप बना देगा. आपका ऐप्लिकेशन, CastSession इंस्टेंस पर getRemoteMediaClient() तरीके को कॉल करके इसे ऐक्सेस कर सकता है.

वेब रिसीवर को अनुरोध भेजने वाले RemoteMediaClient के सभी तरीके, PendingResult ऑब्जेक्ट दिखाते हैं. इस ऑब्जेक्ट का इस्तेमाल, अनुरोध को ट्रैक करने के लिए किया जा सकता है.

ऐसा हो सकता है कि आपके ऐप्लिकेशन के कई हिस्सों में RemoteMediaClient का इंस्टेंस शेयर किया गया हो. साथ ही, फ़्रेमवर्क के कुछ इंटरनल कॉम्पोनेंट, जैसे कि लगातार दिखने वाले मिनी कंट्रोलर और सूचना सेवा भी ऐसा कर सकते हैं. इसलिए, यह इंस्टेंस RemoteMediaClient.Listener के कई इंस्टेंस के रजिस्ट्रेशन की सुविधा देता है.

मीडिया मेटाडेटा सेट करना

MediaMetadata क्लास, उस मीडिया आइटम के बारे में जानकारी देती है जिसे आपको कास्ट करना है. यहां दिए गए उदाहरण में, किसी फ़िल्म का नया 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.Builder का इस्तेमाल करके, MediaInfo इंस्टेंस बनाएं. मौजूदा 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 वीडियो फ़ॉर्मैट

यह देखने के लिए कि आपका मीडिया किस वीडियो फ़ॉर्मैट में है, MediaStatus में getVideoInfo() का इस्तेमाल करें. इससे आपको VideoInfo का मौजूदा इंस्टेंस मिलेगा. इस इंस्टेंस में, एचडीआर टीवी फ़ॉर्मैट का टाइप और पिक्सल में डिसप्ले की लंबाई और चौड़ाई शामिल होती है. 4K फ़ॉर्मैट के वैरिएंट को कॉन्स्टेंट HDR_TYPE_* से दिखाया जाता है.

कई डिवाइसों पर रिमोट कंट्रोल की सूचनाएं पाना

जब कोई उपयोगकर्ता कास्ट कर रहा होता है, तो उसी नेटवर्क से कनेक्ट किए गए अन्य Android डिवाइसों पर एक सूचना दिखेगी. इससे वे भी मीडिया चलाने की सुविधा को कंट्रोल कर पाएंगे. जिस व्यक्ति के डिवाइस पर ऐसी सूचनाएँ मिलती हैं वह उन्हें बंद कर सकता है. इसके लिए, उसे सेटिंग ऐप्लिकेशन में जाकर Google > Google 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" />

जब आपका सेंडर ऐप्लिकेशन, वीडियो या ऑडियो की लाइव स्ट्रीम चला रहा होता है, तो एसडीके, मिनी कंट्रोलर में 'चलाएं/रोकें' बटन की जगह 'चलाएं/बंद करें' बटन अपने-आप दिखाता है.

इस कस्टम व्यू के टाइटल और सबटाइटल के टेक्स्ट का लुक सेट करने के लिए, मिनी कंट्रोलर को पसंद के मुताबिक बनाएं लेख पढ़ें. साथ ही, बटन चुनने के लिए भी यह लेख पढ़ें.

बड़ा किया गया कंट्रोलर जोड़ना

Google Cast डिज़ाइन चेकलिस्ट के मुताबिक, सेंडर ऐप्लिकेशन को कास्ट किए जा रहे मीडिया के लिए, बड़ा किया गया कंट्रोलर उपलब्ध कराना होगा. बड़ा किया गया कंट्रोलर, मिनी कंट्रोलर का फ़ुल स्क्रीन वर्शन होता है.

Cast SDK, बड़े किए गए कंट्रोलर के लिए एक विजेट उपलब्ध कराता है. इसे ExpandedControllerActivity कहा जाता है. यह एक ऐब्स्ट्रैक्ट क्लास है. कास्ट बटन जोड़ने के लिए, आपको इसे सबक्लास करना होगा.

सबसे पहले, बड़े किए गए कंट्रोलर के लिए नई मेन्यू रिसॉर्स फ़ाइल बनाएं, ताकि Cast बटन उपलब्ध कराया जा सके:

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

जब भेजने वाला ऐप्लिकेशन, वीडियो या ऑडियो की लाइव स्ट्रीम चला रहा होता है, तो एसडीके, बड़े किए गए कंट्रोलर में 'चलाएं/रोकें' बटन की जगह, 'चलाएं/बंद करें' बटन अपने-आप दिखाता है.

थीम का इस्तेमाल करके, दिखने का तरीका सेट करने के लिए चुनें कि आपको कौनसे बटन दिखाने हैं. इसके अलावा, कस्टम बटन जोड़ें. इसके लिए, बढ़े हुए कंट्रोलर को पसंद के मुताबिक बनाएं लेख पढ़ें.

आवाज़ कंट्रोल करें

यह फ़्रेमवर्क, भेजने वाले ऐप्लिकेशन के लिए आवाज़ को अपने-आप मैनेज करता है. यह फ़्रेमवर्क, भेजने वाले और वेब रिसीवर ऐप्लिकेशन को अपने-आप सिंक करता है, ताकि भेजने वाले ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) हमेशा वेब रिसीवर की तय की गई आवाज़ को रिपोर्ट करे.

फ़िज़िकल बटन से वॉल्यूम कंट्रोल करने की सुविधा

Android पर, भेजने वाले डिवाइस पर मौजूद फ़िज़िकल बटन का इस्तेमाल करके, वेब रिसीवर पर कास्ट सेशन का वॉल्यूम बदला जा सकता है. यह सुविधा, Jelly Bean या इसके बाद के वर्शन का इस्तेमाल करने वाले किसी भी डिवाइस के लिए डिफ़ॉल्ट रूप से उपलब्ध होती है.

Jelly Bean से पहले, आवाज़ को कम या ज़्यादा करने के लिए फ़िज़िकल बटन का इस्तेमाल करना

Jelly Bean से पहले के Android डिवाइसों पर, वेब रिसीवर डिवाइस की आवाज़ को कंट्रोल करने के लिए, वॉल्यूम कंट्रोल करने वाले बटन का इस्तेमाल किया जा सकता है. इसके लिए, सेंडर ऐप्लिकेशन को अपनी गतिविधियों में 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 में null के साथ 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 की लाइफ़साइकल के हर चरण के लिए सबसे सही जवाब तय करना बहुत ज़रूरी है. ऐप्लिकेशन, उपयोगकर्ता को गड़बड़ी वाले डायलॉग दिखा सकता है. इसके अलावा, यह वेब रिसीवर से कनेक्शन बंद करने का फ़ैसला भी ले सकता है.