আপনার অ্যান্ড্রয়েড অ্যাপে কাস্ট সংহত করুন

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

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

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

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

অ্যাপ প্রবাহ

নিম্নলিখিত ধাপগুলি একটি প্রেরক Android অ্যাপের জন্য সাধারণ উচ্চ-স্তরের কার্যকরী প্রবাহ বর্ণনা করে:

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

Google Cast Android SDK-এর সমস্ত ক্লাস, পদ্ধতি এবং ইভেন্টগুলির একটি বিস্তৃত তালিকার জন্য, Android এর জন্য Google Cast প্রেরক API রেফারেন্স দেখুন৷ নিম্নলিখিত বিভাগগুলি আপনার Android অ্যাপে কাস্ট যোগ করার পদক্ষেপগুলি কভার করে৷

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

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

use-sdk

কাস্ট SDK সমর্থন করে এমন ন্যূনতম এবং লক্ষ্য Android API স্তরগুলি সেট করুন৷ বর্তমানে সর্বনিম্ন হল API স্তর 23 এবং লক্ষ্য হল API স্তর 34৷

<uses-sdk
        android:minSdkVersion="23"
        android:targetSdkVersion="34" />

অ্যান্ড্রয়েড: থিম

ন্যূনতম Android SDK সংস্করণের উপর ভিত্তি করে আপনার অ্যাপের থিম সেট করুন। উদাহরণ স্বরূপ, আপনি যদি নিজের থিম বাস্তবায়ন না করেন, তাহলে ন্যূনতম অ্যানড্রয়েড 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 এর একটি উদাহরণ প্রদান করে যাতে এমন বিকল্প রয়েছে যা কাঠামোর আচরণকে প্রভাবিত করে। এর মধ্যে সবচেয়ে গুরুত্বপূর্ণ হল ওয়েব রিসিভার অ্যাপ্লিকেশন আইডি, যা আবিষ্কারের ফলাফল ফিল্টার করতে এবং কাস্ট সেশন শুরু হলে ওয়েব রিসিভার অ্যাপ চালু করতে ব্যবহৃত হয়।

কোটলিন
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
    }
}
জাভা
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 অলসভাবে আরম্ভ করা হয় যখন CastContext.getSharedInstance() কল করা হয়।

কোটলিন
class MyActivity : FragmentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        val castContext = CastContext.getSharedInstance(this)
    }
}
জাভা
public class MyActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        CastContext castContext = CastContext.getSharedInstance(this);
    }
}

কাস্ট ইউএক্স উইজেট

কাস্ট ফ্রেমওয়ার্ক উইজেটগুলি প্রদান করে যা কাস্ট ডিজাইন চেকলিস্ট মেনে চলে:

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

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

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

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

  • বিজ্ঞপ্তি : শুধুমাত্র অ্যান্ড্রয়েড। যখন ব্যবহারকারী সামগ্রী কাস্ট করে এবং প্রেরক অ্যাপ থেকে দূরে নেভিগেট করে, তখন একটি মিডিয়া বিজ্ঞপ্তি প্রদর্শিত হয় যা বর্তমানে কাস্ট করা মিডিয়া মেটাডেটা এবং প্লেব্যাক নিয়ন্ত্রণগুলি দেখায়৷

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

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

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

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

ফ্রেমওয়ার্ক Cast button হিসাবে একটি MediaRouteButton যোগ করা খুব সহজ করে তোলে। আপনাকে প্রথমে 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" />
কোটলিন
// 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
}
জাভা
// 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>
কোটলিন
// 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)
}
জাভা
// 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 আরম্ভ করার সময়, প্রেরক অ্যাপ ওয়েব রিসিভার অ্যাপ্লিকেশন আইডি নির্দিষ্ট করে, এবং CastOptionssupportedNamespaces সেট করে ঐচ্ছিকভাবে নেমস্পেস ফিল্টারিংয়ের অনুরোধ করতে পারে। CastContext অভ্যন্তরীণভাবে MediaRouter এর একটি রেফারেন্স ধারণ করে এবং নিম্নলিখিত শর্তে আবিষ্কার প্রক্রিয়া শুরু করবে:

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

কাস্ট ডায়ালগ বন্ধ হয়ে গেলে বা প্রেরক অ্যাপ ব্যাকগ্রাউন্ডে প্রবেশ করলে আবিষ্কার প্রক্রিয়া বন্ধ হয়ে যাবে।

কোটলিন
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
    }
}
জাভা
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;
    }
}

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

কাস্ট SDK একটি কাস্ট সেশনের ধারণা প্রবর্তন করে, যার প্রতিষ্ঠা একটি ডিভাইসের সাথে সংযোগ স্থাপন, একটি ওয়েব রিসিভার অ্যাপ চালু (বা যোগদান), সেই অ্যাপের সাথে সংযোগ স্থাপন এবং একটি মিডিয়া নিয়ন্ত্রণ চ্যানেল শুরু করার ধাপগুলিকে একত্রিত করে৷ কাস্ট সেশন এবং ওয়েব রিসিভার জীবনচক্র সম্পর্কে আরও তথ্যের জন্য ওয়েব রিসিভার অ্যাপ্লিকেশন লাইফ সাইকেল গাইড দেখুন৷

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

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

MediaRouter ডায়ালগগুলি থেকে ব্যবহারকারীর অঙ্গভঙ্গির প্রতিক্রিয়া হিসাবে সেশনগুলি তৈরি হয় এবং স্বয়ংক্রিয়ভাবে ছিঁড়ে যায়৷

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

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

কোটলিন
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)
    }
}
জাভা
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);
    }
}

স্ট্রিম স্থানান্তর

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

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

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

স্বয়ংক্রিয় পুনঃসংযোগ

ফ্রেমওয়ার্ক একটি ReconnectionService প্রদান করে যা প্রেরক অ্যাপ দ্বারা অনেক সূক্ষ্ম কোণার ক্ষেত্রে পুনঃসংযোগ পরিচালনা করতে সক্ষম করা যেতে পারে, যেমন:

  • WiFi এর সাময়িক ক্ষতি থেকে পুনরুদ্ধার করুন
  • ডিভাইসের ঘুম থেকে পুনরুদ্ধার করুন
  • অ্যাপের ব্যাকগ্রাউন্ডিং থেকে পুনরুদ্ধার করুন
  • অ্যাপটি ক্র্যাশ হলে পুনরুদ্ধার করুন

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

এই পরিষেবাটি স্বয়ংক্রিয়ভাবে আপনার অ্যাপের ম্যানিফেস্টে একত্রিত হতে পারে যদি আপনার গ্রেডল ফাইলে স্বয়ংক্রিয়-মার্জন সক্ষম করা থাকে।

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

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

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

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

RemoteMediaClient এর সমস্ত পদ্ধতি যা ওয়েব রিসিভারের কাছে অনুরোধ জারি করে সেগুলি একটি PendingResult অবজেক্ট ফিরিয়ে দেবে যা সেই অনুরোধ ট্র্যাক করতে ব্যবহার করা যেতে পারে।

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

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

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

কোটলিন
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))))
জাভা
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 পান, তারপর সেই RemoteMediaClientMediaInfo লোড করুন। ওয়েব রিসিভারে চলমান একটি মিডিয়া প্লেয়ার অ্যাপ চালাতে, বিরতি দিতে এবং অন্যথায় নিয়ন্ত্রণ করতে RemoteMediaClient ব্যবহার করুন।

কোটলিন
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())
জাভা
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 এর বর্তমান উদাহরণ পেতে MediaStatus-এ getVideoInfo() ব্যবহার করুন। এই উদাহরণে HDR টিভি ফর্ম্যাটের ধরন এবং ডিসপ্লের উচ্চতা এবং প্রস্থ পিক্সেলে রয়েছে৷ 4K ফরম্যাটের ভেরিয়েন্টগুলি স্থির HDR_TYPE_* দ্বারা নির্দেশিত হয়।

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

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

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

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

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

<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 ডিজাইন চেকলিস্টের প্রয়োজন যে একটি প্রেরক অ্যাপ কাস্ট করা মিডিয়ার জন্য একটি প্রসারিত নিয়ামক প্রদান করে৷ প্রসারিত কন্ট্রোলারটি মিনি কন্ট্রোলারের একটি পূর্ণ স্ক্রীন সংস্করণ।

কাস্ট 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 প্রসারিত করে।

কোটলিন
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
    }
}
জাভা
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 পরিবর্তন করুন:

কোটলিন
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()
}
জাভা
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 পদ্ধতি আপডেট করুন:

কোটলিন
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()
    )
}
জাভা
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 সর্বদা ওয়েব রিসিভার দ্বারা নির্দিষ্ট ভলিউম রিপোর্ট করে৷

শারীরিক বোতাম ভলিউম নিয়ন্ত্রণ

অ্যান্ড্রয়েডে, প্রেরক ডিভাইসের ফিজিক্যাল বোতামগুলি জেলি বিন বা নতুন ব্যবহার করে যেকোনো ডিভাইসের জন্য ডিফল্টরূপে ওয়েব রিসিভারে কাস্ট সেশনের ভলিউম পরিবর্তন করতে ব্যবহার করা যেতে পারে।

জেলি বিনের আগে শারীরিক বোতামের ভলিউম নিয়ন্ত্রণ

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

কোটলিন
class MyActivity : FragmentActivity() {
    override fun dispatchKeyEvent(event: KeyEvent): Boolean {
        return (CastContext.getSharedInstance(this)
            .onDispatchVolumeKeyEventBeforeJellyBean(event)
                || super.dispatchKeyEvent(event))
    }
}
জাভা
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 ব্যবহার করা হবে৷

কোটলিন
// 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()
জাভা
// 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 কল করে অক্ষম করা যেতে পারে। বর্তমানে, যতক্ষণ নোটিফিকেশন চালু থাকে ততক্ষণ লক স্ক্রিন বৈশিষ্ট্যটি চালু থাকে।

কোটলিন
// ... 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()
জাভা
// ... 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 স্বয়ংক্রিয়ভাবে বিজ্ঞপ্তি নিয়ন্ত্রণে প্লে/পজ বোতামের জায়গায় একটি প্লে/স্টপ বোতাম প্রদর্শন করে কিন্তু লক স্ক্রিন নিয়ন্ত্রণ নয়।

দ্রষ্টব্য : প্রাক-ললিপপ ডিভাইসগুলিতে লক স্ক্রিন নিয়ন্ত্রণগুলি প্রদর্শন করতে, RemoteMediaClient স্বয়ংক্রিয়ভাবে আপনার পক্ষ থেকে অডিও ফোকাসের অনুরোধ করবে৷

ত্রুটিগুলি পরিচালনা করুন

প্রেরক অ্যাপগুলির জন্য সমস্ত ত্রুটি কলব্যাকগুলি পরিচালনা করা এবং কাস্ট জীবন চক্রের প্রতিটি পর্যায়ে সেরা প্রতিক্রিয়া নির্ধারণ করা অত্যন্ত গুরুত্বপূর্ণ৷ অ্যাপটি ব্যবহারকারীর কাছে ত্রুটি ডায়ালগ প্রদর্শন করতে পারে বা এটি ওয়েব রিসিভারের সাথে সংযোগটি ছিন্ন করার সিদ্ধান্ত নিতে পারে।