আপনার অ্যান্ড্রয়েড অ্যাপে উন্নত বৈশিষ্ট্য যোগ করুন

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

অ্যান্ড্রয়েড সেন্ডার এসডিকে একটি নির্দিষ্ট মিডিয়া স্ট্রিমের মধ্যে অ্যাড ব্রেক এবং সহযোগী বিজ্ঞাপন প্রদর্শনের সুবিধা প্রদান করে।

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

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

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

কোটলিন
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)
জাভা
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" />
কোটলিন
// 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) {
    }
}
জাভা
// 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 ইন্টারফেসের মাধ্যমে প্রয়োগ করা হয়:

কোটলিন
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")
    }
}
জাভা
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 পদ্ধতিটি ব্যবহার করে কাস্টম চ্যানেলটি তৈরি করা যেতে পারে:

কোটলিন
try {
    mCastSession.setMessageReceivedCallbacks(
        mHelloWorldChannel.namespace,
        mHelloWorldChannel)
} catch (e: IOException) {
    Log.e(TAG, "Exception while creating channel", e)
}
জাভা
try {
    mCastSession.setMessageReceivedCallbacks(
            mHelloWorldChannel.getNamespace(),
            mHelloWorldChannel);
} catch (IOException e) {
    Log.e(TAG, "Exception while creating channel", e);
}

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

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

স্বয়ংক্রিয় প্লে সমর্থন করে

অটোপ্লে ও কিউইং এপিআই (Autoplay & Queueing APIs) বিভাগটি দেখুন।

ইউএক্স উইজেটগুলির জন্য ছবি নির্বাচন অগ্রাহ্য করুন

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

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

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

সেশন লাইফসাইকেল পরিচালনা

SessionManager হলো সেশনের জীবনচক্র পরিচালনার কেন্দ্রীয় স্থান। সেশন শুরু, পুনরায় চালু এবং শেষ করার জন্য SessionManager অ্যান্ড্রয়েড MediaRouter রুট নির্বাচনের অবস্থার পরিবর্তন পর্যবেক্ষণ করে। যখন কোনো রুট নির্বাচন করা হয়, SessionManager একটি Session অবজেক্ট তৈরি করে এবং সেটি শুরু বা পুনরায় চালু করার চেষ্টা করে। যখন কোনো রুট অনির্বাচিত হয়, SessionManager বর্তমান সেশনটি শেষ করে দেয়।

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

আপনি কাস্ট ডায়ালগগুলো কীভাবে তৈরি করেছেন তার উপর নির্ভর করে অতিরিক্ত কিছু পদক্ষেপ নেওয়ার প্রয়োজন হতে পারে:

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

শূন্য ডিভাইস অবস্থা

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

আপনি যদি ডিফল্ট MediaRouteChooserDialog ব্যবহার করেন, তাহলে শূন্য ডিভাইসের অবস্থাটি ইতিমধ্যেই সামলানো হয়ে গেছে।

পরবর্তী পদক্ষেপ

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