আপনার Android অ্যাপে উন্নত ফিচার যোগ করা

বিজ্ঞাপন বিরতি

Android Sender SDK, প্রদত্ত মিডিয়া স্ট্রিমের মধ্যে বিজ্ঞাপন বিরতি ও কম্প্যানিয়ন বিজ্ঞাপনের জন্য সহায়তা প্রদান করে।

বিজ্ঞাপন বিরতি কীভাবে কাজ করে সেই সম্পর্কে আরও তথ্য পেতে ওয়েব রিসিভার বিজ্ঞাপন বিরতির ওভারভিউ দেখুন।

প্রেরক ও প্রাপক, উভয়ের ক্ষেত্রেই বিরতি নির্দিষ্ট করা গেলেও, বিভিন্ন প্ল্যাটফর্ম জুড়ে সামঞ্জস্যপূর্ণ আচরণ বজায় রাখার জন্য ওয়েব রিসিভার ও Android TV রিসিভার-এ বিরতি নির্দিষ্ট করার সাজেশন দেওয়া হয়।

Android-এ, লোড কমান্ডে বিজ্ঞাপন বিরতি নির্দিষ্ট করতে AdBreakClipInfo এবং AdBreakInfo ব্যবহার করুন:

Kotlin
val breakClip1: AdBreakClipInfo =
    AdBreakClipInfo.Builder("bc0")
        .setTitle("Clip title")
        .setPosterUrl("https://www.some.url")
        .setDuration(60000)
        .setWhenSkippableInMs(5000)  // Set this field so that the ad is skippable
        .build()

val breakClip2: AdBreakClipInfo = …
val breakClip3: AdBreakClipInfo = …

val break1: AdBreakClipInfo =
    AdBreakInfo.Builder(/* playbackPositionInMs= */ 10000)
        .setId("b0")
        .setBreakClipIds({"bc0","bc1","bc2"})
        …
        .build()

val mediaInfo: MediaInfo = MediaInfo.Builder()
    …
    .setAdBreaks({break1})
    .setAdBreakClips({breakClip1, breakClip2, breakClip3})
    .build()

val mediaLoadRequestData: MediaLoadRequestData = MediaInfo.Builder()
    …
    .setMediaInfo(mediaInfo)
    .build()

remoteMediaClient.load(mediaLoadRequestData)
Java
AdBreakClipInfo breakClip1 =
    new AdBreakClipInfo.Builder("bc0")
        .setTitle("Clip title")
        .setPosterUrl("https://www.some.url")
        .setDuration(60000)
        .setWhenSkippableInMs(5000)  // Set this field so that the ad is skippable
        .build();

AdBreakClipInfo breakClip2 = …
AdBreakClipInfo breakClip3 = …

AdBreakInfo break1 =
    new AdBreakInfo.Builder(/* playbackPositionInMs= */ 10000)
        .setId("b0")
        .setBreakClipIds({"bc0","bc1","bc2"})
        …
        .build();

MediaInfo mediaInfo = new MediaInfo.Builder()
    …
    .setAdBreaks({break1})
    .setAdBreakClips({breakClip1, breakClip2, breakClip3})
    .build();

MediaLoadRequestData mediaLoadRequestData = new MediaInfo.Builder()
    …
    .setMediaInfo(mediaInfo)
    .build();

remoteMediaClient.load(mediaLoadRequestData);

কাস্টম অ্যাকশন যোগ করা

কাস্টম অ্যাকশন হ্যান্ডেল করতে বা এর আচরণ ওভাররাইড করতে MediaIntentReceiver একটি প্রেরক অ্যাপ এক্সটেন্ড করা যেতে পারে। আপনি যদি নিজের MediaIntentReceiver প্রয়োগ করে থাকেন, তাহলে আপনাকে এটি ম্যানিফেস্টে যোগ করতে হবে এবং CastMediaOptions-এ এর নাম সেট করতে হবে। এই উদাহরণে কাস্টম অ্যাকশন দেওয়া হয়েছে যা রিমোট মিডিয়া প্লেব্যাক টগল করা, মিডিয়া বোতাম প্রেস করা এবং অন্যান্য ধরনের অ্যাকশন ওভাররাইড করে।

// In AndroidManifest.xml
<receiver android:name="com.example.MyMediaIntentReceiver" />
Kotlin
// In your OptionsProvider
var mediaOptions = CastMediaOptions.Builder()
    .setMediaIntentReceiverClassName(MyMediaIntentReceiver::class.java.name)
    .build()

// Implementation of MyMediaIntentReceiver
internal class MyMediaIntentReceiver : MediaIntentReceiver() {
    override fun onReceiveActionTogglePlayback(currentSession: Session) {
    }

    override fun onReceiveActionMediaButton(currentSession: Session, intent: Intent) {
    }

    override fun onReceiveOtherAction(context: Context?, action: String, intent: Intent) {
    }
}
Java
// In your OptionsProvider
CastMediaOptions mediaOptions = new CastMediaOptions.Builder()
        .setMediaIntentReceiverClassName(MyMediaIntentReceiver.class.getName())
        .build();

// Implementation of MyMediaIntentReceiver
class MyMediaIntentReceiver extends MediaIntentReceiver {
    @Override
    protected void onReceiveActionTogglePlayback(Session currentSession) {
    }

    @Override
    protected void onReceiveActionMediaButton(Session currentSession, Intent intent) {
    }

    @Override
    protected void onReceiveOtherAction(Context context, String action, Intent intent) {
    }
}

কাস্টম চ্যানেল যোগ করা

প্রেরক অ্যাপকে প্রাপক অ্যাপের সাথে যোগাযোগ করতে হলে, আপনার অ্যাপকে কাস্টম চ্যানেল তৈরি করতে হবে। প্রেরক কাস্টম চ্যানেল ব্যবহার করে প্রাপককে স্ট্রিং মেসেজ পাঠাতে পারেন। প্রতিটি কাস্টম চ্যানেলকে একটি অনন্য নেমস্পেসের মাধ্যমে সংজ্ঞায়িত করা হয় এবং অবশ্যই urn:x-cast: উপসর্গ দিয়ে শুরু হতে হবে, যেমন, urn:x-cast:com.example.custom। একাধিক কাস্টম চ্যানেল থাকতে পারে, প্রত্যেকটির অনন্য নেমস্পেস থাকে। রিসিভার অ্যাপ একই নেমস্পেস ব্যবহার করে মেসেজ পাঠাতে ও পেতে পারবে।

কাস্টম চ্যানেলটি Cast.MessageReceivedCallback ইন্টারফেসের মাধ্যমে প্রয়োগ করা হয়:

Kotlin
class HelloWorldChannel : MessageReceivedCallback {
    val namespace: String
        get() = "urn:x-cast:com.example.custom"

    override fun onMessageReceived(castDevice: CastDevice, namespace: String, message: String) {
        Log.d(TAG, "onMessageReceived: $message")
    }
}
Java
class HelloWorldChannel implements Cast.MessageReceivedCallback {
    public String getNamespace() {
        return "urn:x-cast:com.example.custom";
    }
    @Override
    public void onMessageReceived(CastDevice castDevice, String namespace, String message) {
        Log.d(TAG, "onMessageReceived: " + message);
    }
}

প্রেরক অ্যাপ, প্রাপক অ্যাপের সাথে কানেক্ট হয়ে গেলে, কাস্টম চ্যানেলটি setMessageReceivedCallbacks পদ্ধতি ব্যবহার করে তৈরি করা যায়:

Kotlin
try {
    mCastSession.setMessageReceivedCallbacks(
        mHelloWorldChannel.namespace,
        mHelloWorldChannel)
} catch (e: IOException) {
    Log.e(TAG, "Exception while creating channel", e)
}
Java
try {
    mCastSession.setMessageReceivedCallbacks(
            mHelloWorldChannel.getNamespace(),
            mHelloWorldChannel);
} catch (IOException e) {
    Log.e(TAG, "Exception while creating channel", e);
}

কাস্টম চ্যানেল তৈরি হয়ে গেলে, প্রেরক সেই চ্যানেলের মাধ্যমে প্রাপককে স্ট্রিং মেসেজ পাঠাতে sendMessage পদ্ধতি ব্যবহার করতে পারেন:

Kotlin
private fun sendMessage(message: String) {
    if (mHelloWorldChannel != null) {
        try {
            mCastSession.sendMessage(mHelloWorldChannel.namespace, message)
                .setResultCallback { status ->
                    if (!status.isSuccess) {
                        Log.e(TAG, "Sending message failed")
                    }
                }
        } catch (e: Exception) {
            Log.e(TAG, "Exception while sending message", e)
        }
    }
}
Java
private void sendMessage(String message) {
    if (mHelloWorldChannel != null) {
        try {
            mCastSession.sendMessage(mHelloWorldChannel.getNamespace(), message)
                .setResultCallback( status -> {
                    if (!status.isSuccess()) {
                        Log.e(TAG, "Sending message failed");
                    }
                });
        } catch (Exception e) {
            Log.e(TAG, "Exception while sending message", e);
        }
    }
}

অটোপ্লে ফিচার কাজ করে

অটোপ্লে ও কিউয়িং API বিভাগটি দেখুন।

UX উইজেটের জন্য ছবি বেছে নেওয়ার বিকল্প ওভাররাইড করা

ফ্রেমওয়ার্কের বিভিন্ন কম্পোনেন্ট (যেমন, কাস্ট ডায়ালগ, মিনি কন্ট্রোলার এবং UIMediaController, যদি কনফিগার করা থাকে) বর্তমানে কাস্ট করা মিডিয়ার আর্টওয়ার্ক দেখাবে। সাধারণত, মিডিয়ার MediaMetadata-এ ইমেজ আর্টওয়ার্কের URL অন্তর্ভুক্ত থাকে, কিন্তু প্রেরক অ্যাপে URL-এর বিকল্প সোর্স থাকতে পারে।

ImagePicker MediaMetadata-এ থাকা ছবির তালিকা থেকে কোনও উপযুক্ত ছবি বেছে নেওয়ার একটি উপায় এই ক্লাস নির্ধারণ করে। ছবির ব্যবহার, যেমন, বিজ্ঞপ্তি থাম্বনেল বা ফুল স্ক্রিন ব্যাকগ্রাউন্ডের উপর ভিত্তি করে এটি করা হয়। ডিফল্ট ImagePicker প্রয়োগ সবসময় প্রথম ছবিটি বেছে নেয় অথবা MediaMetadata-এ কোনও ছবি উপলভ্য না থাকলে শূন্য মান রিটার্ন করে। আপনার অ্যাপ ImagePicker-এর সাবক্লাস তৈরি করতে পারে এবং onPickImage(MediaMetadata, ImageHints) পদ্ধতি ওভাররাইড করে বিকল্প ইমপ্লিমেন্টেশন প্রদান করতে পারে এবং তারপরে CastMediaOptions.Builder-এর setImagePicker পদ্ধতির মাধ্যমে সেই সাবক্লাস বেছে নিতে পারে। ImageHints UI-তে দেখানোর জন্য বেছে নেওয়া ছবির ধরন ও সাইজ সম্পর্কে ImagePicker-কে হিন্ট দেয়।

কাস্ট ডায়ালগ কাস্টমাইজ করা

সেশন লাইফসাইকেল ম্যানেজ করা

SessionManager সেশন লাইফসাইকেল ম্যানেজ করার জন্য এটি হল কেন্দ্রীয় জায়গা। SessionManager Android-এর কথা শোনে MediaRouter সেশন শুরু, আবার চালু ও শেষ করার জন্য রুট বেছে নেওয়ার স্টেট পরিবর্তন করে। কোনও রুট বেছে নেওয়া হলে, SessionManager একটি Session অবজেক্ট তৈরি করে এবং সেটি শুরু বা আবার চালু করার চেষ্টা করে। কোনও রুট বেছে না নেওয়া হলে, SessionManager বর্তমান সেশন শেষ করে দেবে।

তাই, SessionManager যাতে সেশন লাইফসাইকেল সঠিকভাবে ম্যানেজ করে তা নিশ্চিত করতে, আপনাকে অবশ্যই এগুলি নিশ্চিত করতে হবে:

আপনি কীভাবে Cast ডায়ালগ তৈরি করেন তার উপর নির্ভর করে, অতিরিক্ত অ্যাকশন নিতে হতে পারে:

  • আপনি যদি MediaRouteChooserDialog এবং MediaRouteControllerDialog ব্যবহার করে কাস্ট ডায়ালগ তৈরি করেন, তাহলে এইসব ডায়ালগ MediaRouter-এ অটোমেটিক রুট বেছে নেওয়া আপডেট করবে, তাই কিছু করার প্রয়োজন নেই।
  • আপনি যদি CastButtonFactory.setUpMediaRouteButton(Context, Menu, int) বা CastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton) ব্যবহার করে আপনার Cast বোতাম সেট-আপ করেন, তাহলে ডায়ালগগুলি আসলে MediaRouteChooserDialog ও MediaRouteControllerDialog ব্যবহার করে তৈরি করা হয়, তাই আপনাকে কিছুই করতে হবে না।
  • অন্যান্য ক্ষেত্রে, আপনি কাস্টম কাস্ট ডায়ালগ তৈরি করবেন, তাই আপনাকে MediaRouter-এ রুট বেছে নেওয়ার স্ট্যাটাস আপডেট করতে উপরের নির্দেশাবলী অনুসরণ করতে হবে।

জিরো ডিভাইস স্টেট

আপনি কাস্টম কাস্ট ডায়ালগ তৈরি করলে, আপনার কাস্টম MediaRouteChooserDialog-কে কোনও ডিভাইস না পাওয়া গেলে সেই পরিস্থিতি সঠিকভাবে হ্যান্ডেল করতে হবে। ডায়ালগে এমন ইনডিকেটর থাকতে হবে যা আপনার ব্যবহারকারীদের কাছে এটি স্পষ্ট করে দেবে যে আপনার অ্যাপ এখনও ডিভাইস খোঁজার চেষ্টা করছে এবং ডিভাইস খোঁজার চেষ্টা আর অ্যাক্টিভ নেই।

আপনি ডিফল্ট MediaRouteChooserDialog ব্যবহার করলে, জিরো ডিভাইস স্টেট আগে থেকেই ম্যানেজ করা থাকে।

পরবর্তী ধাপ

আপনার Android প্রেরক অ্যাপে যোগ করতে পারবেন এমন ফিচারগুলি এখানে শেষ হল। আপনি এখন অন্য প্ল্যাটফর্মের জন্য প্রেরক অ্যাপ তৈরি করতে পারবেন (iOS বা ওয়েব) অথবা ওয়েব রিসিভার অ্যাপ তৈরি করতে পারবেন।