আপনার 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 উইজেটের জন্য ছবি বেছে নেওয়ার বিকল্প ওভাররাইড করুন

ফ্রেমওয়ার্কের বিভিন্ন কম্পোনেন্ট (যেমন Cast ডায়ালগ, মিনি কন্ট্রোলার এবং UIMediaController, যদি কনফিগার করা থাকে) বর্তমানে কাস্ট করা মিডিয়ার জন্য আর্টওয়ার্ক দেখাবে। ছবির আর্টওয়ার্কের URL সাধারণত মিডিয়ার জন্য MediaMetadata-এ অন্তর্ভুক্ত থাকে, তবে প্রেরক অ্যাপের কাছে 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) ব্যবহার করে আপনার কাস্ট করার বোতাম সেট-আপ করেন, তাহলে ডায়ালগগুলি আসলে MediaRouteChooserDialog এবং MediaRouteControllerDialog ব্যবহার করে তৈরি করা হয়, তাই কিছুই করার প্রয়োজন নেই।
  • অন্যান্য ক্ষেত্রে, আপনি কাস্টম Cast ডায়ালগ তৈরি করবেন, তাই আপনাকে MediaRouter-এ রুট বেছে নেওয়ার স্ট্যাটাস আপডেট করতে উপরের নির্দেশাবলী অনুসরণ করতে হবে।

কোনও ডিভাইস নেই স্ট্যাটাস

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

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

পরবর্তী ধাপ

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