এই ডেভেলপার গাইড iOS Sender SDK ব্যবহার করে আপনার iOS সেন্ডার অ্যাপে কীভাবে Google Cast সাপোর্ট যোগ করতে হয় তা বর্ণনা করে।
মোবাইল ডিভাইস বা ল্যাপটপ হল প্রেরক যা প্লেব্যাক নিয়ন্ত্রণ করে এবং Google Cast ডিভাইস হল প্রাপক যা টিভিতে কন্টেন্ট দেখায়।
প্রেরক ফ্রেমওয়ার্ক বলতে Cast ক্লাস লাইব্রেরি বাইনারি ও সংশ্লিষ্ট সোর্সকে বোঝায় যা প্রেরকের রানটাইমে উপস্থিত থাকে। প্রেরক অ্যাপ বা কাস্ট অ্যাপ বলতে প্রেরকের ডিভাইসেও চলছে এমন অ্যাপকে বোঝায়। ওয়েব রিসিভার অ্যাপ ওয়েব রিসিভারে রান করা HTML অ্যাপ্লিকেশনকে বোঝায়।
প্রেরক ফ্রেমওয়ার্ক, ইভেন্ট সম্পর্কে প্রেরক অ্যাপকে জানাতে এবং Cast অ্যাপ লাইফ সাইকেলের বিভিন্ন স্টেটের মধ্যে ট্রানজিশন করতে অ্যাসিঙ্ক্রোনাস কলব্যাক ডিজাইন ব্যবহার করে।
অ্যাপ ফ্লো
নিচের ধাপগুলি প্রেরক iOS অ্যাপের জন্য সাধারণ হাই-লেভেল এক্সিকিউশন ফ্লো বর্ণনা করে:
- ডিভাইস স্ক্যান করা শুরু করতে,
GCKCastOptions-এ দেওয়া প্রপার্টির উপর ভিত্তি করে Cast ফ্রেমওয়ার্কGCKDiscoveryManagerশুরু হয়। - ব্যবহারকারী 'কাস্ট করুন' বোতামে ক্লিক করলে, ফ্রেমওয়ার্ক, খুঁজে পাওয়া কাস্ট ডিভাইসের তালিকা সহ কাস্ট ডায়ালগ দেখায়।
- ব্যবহারকারী কোনও কাস্ট ডিভাইস বেছে নিলে, ফ্রেমওয়ার্ক কাস্ট ডিভাইসে ওয়েব রিসিভার অ্যাপ লঞ্চ করার চেষ্টা করে।
- ফ্রেমওয়ার্ক, প্রেরক অ্যাপে কলব্যাক ইনভোক করে এটি কনফার্ম করে যে ওয়েব রিসিভার অ্যাপ লঞ্চ করা হয়েছে।
- ফ্রেমওয়ার্ক প্রেরক ও ওয়েব রিসিভার অ্যাপের মধ্যে একটি কমিউনিকেশন চ্যানেল তৈরি করে।
- ওয়েব রিসিভারে মিডিয়া প্লেব্যাক লোড ও কন্ট্রোল করতে ফ্রেমওয়ার্ক কমিউনিকেশন চ্যানেল ব্যবহার করে।
- ফ্রেমওয়ার্ক প্রেরক ও ওয়েব রিসিভারের মধ্যে মিডিয়া প্লেব্যাক স্টেট সিঙ্ক্রোনাইজ করে: ব্যবহারকারী প্রেরক UI অ্যাকশন নিলে, ফ্রেমওয়ার্ক সেইসব মিডিয়া কন্ট্রোল অনুরোধ ওয়েব রিসিভারকে পাঠায় এবং ওয়েব রিসিভার মিডিয়া স্ট্যাটাস আপডেট পাঠালে, ফ্রেমওয়ার্ক প্রেরক UI-এর স্টেট আপডেট করে।
- ব্যবহারকারী কাস্ট ডিভাইস থেকে ডিসকানেক্ট করার জন্য কাস্ট বোতামে ক্লিক করলে, ফ্রেমওয়ার্ক প্রেরক অ্যাপকে ওয়েব রিসিভার থেকে ডিসকানেক্ট করে দেবে।
আপনার প্রেরকের সমস্যার সমাধান করতে, আপনাকে লগ করা চালু করতে হবে।
Google Cast iOS ফ্রেমওয়ার্কের মধ্যে থাকা সব ক্লাস, পদ্ধতি ও ইভেন্টের একটি বিস্তারিত তালিকা পেতে, Google Cast iOS API রেফারেন্স দেখুন। আপনার iOS অ্যাপে Cast ইন্টিগ্রেট করার ধাপগুলি নিম্নলিখিত বিভাগে উল্লেখ করা হয়েছে।
মূল থ্রেড থেকে কল পদ্ধতি
Cast কনটেক্সট ইনিশিয়ালাইজ করা
Cast ফ্রেমওয়ার্কে একটি গ্লোবাল সিঙ্গলটন অবজেক্ট আছে, সেটি হল
GCKCastContext, যা
ফ্রেমওয়ার্কের সব অ্যাক্টিভিটি কোঅর্ডিনেট করে। এই অবজেক্টটি অবশ্যই অ্যাপ্লিকেশন লাইফসাইকেলের
শুরুতে, সাধারণত অ্যাপ ডেলিগেটের
-[application:didFinishLaunchingWithOptions:] পদ্ধতিতে ইনিশিয়ালাইজ করতে হবে, যাতে
সেন্ডার অ্যাপ রিস্টার্ট করার সময় অটোমেটিক সেশন আবার চালু করার প্রসেস সঠিকভাবে ট্রিগার করা যায়।
GCKCastContext ইনিশিয়ালাইজ করার সময় GCKCastOptions
অবজেক্ট দিতে হবে।
এই ক্লাসে এমন বিকল্প থাকে যা ফ্রেমওয়ার্কের আচরণকে প্রভাবিত করে। এর মধ্যে সবচেয়ে
গুরুত্বপূর্ণ হল Web Receiver অ্যাপ্লিকেশন আইডি, যা ডিসকভারি ফলাফল ফিল্টার করতে
এবং কোনও Cast সেশন শুরু হলে Web Receiver অ্যাপ লঞ্চ করতে
ব্যবহৃত হয়।
এছাড়াও, ফ্রেমওয়ার্ক থেকে লগিং মেসেজ পাওয়ার জন্য
লগিং ডেলিগেট সেট-আপ করার জন্য -[application:didFinishLaunchingWithOptions:] পদ্ধতিটি ভালো।
এগুলি ডিবাগিং ও সমস্যার সমাধানের জন্য কাজে লাগতে পারে।
@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, GCKLoggerDelegate { let kReceiverAppID = kGCKDefaultMediaReceiverApplicationID let kDebugLoggingEnabled = true var window: UIWindow? func applicationDidFinishLaunching(_ application: UIApplication) { let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID) let options = GCKCastOptions(discoveryCriteria: criteria) GCKCastContext.setSharedInstanceWith(options) // Enable logger. GCKLogger.sharedInstance().delegate = self ... } // MARK: - GCKLoggerDelegate func logMessage(_ message: String, at level: GCKLoggerLevel, fromFunction function: String, location: String) { if (kDebugLoggingEnabled) { print(function + " - " + message) } } }
AppDelegate.h
@interface AppDelegate () <GCKLoggerDelegate> @end
AppDelegate.m
@implementation AppDelegate static NSString *const kReceiverAppID = @"AABBCCDD"; static const BOOL kDebugLoggingEnabled = YES; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { GCKDiscoveryCriteria *criteria = [[GCKDiscoveryCriteria alloc] initWithApplicationID:kReceiverAppID]; GCKCastOptions *options = [[GCKCastOptions alloc] initWithDiscoveryCriteria:criteria]; [GCKCastContext setSharedInstanceWithOptions:options]; // Enable logger. [GCKLogger sharedInstance].delegate = self; ... return YES; } ... #pragma mark - GCKLoggerDelegate - (void)logMessage:(NSString *)message atLevel:(GCKLoggerLevel)level fromFunction:(NSString *)function location:(NSString *)location { if (kDebugLoggingEnabled) { NSLog(@"%@ - %@, %@", function, message, location); } } @end
Cast UX উইজেট
Cast iOS SDK এইসব উইজেট প্রদান করে যা Cast ডিজাইন চেকলিস্ট মেনে চলে:
প্রাথমিক ওভারলে:
GCKCastContextক্লাসে একটি পদ্ধতি আছে,presentCastInstructionsViewControllerOnceWithCastButton, যা প্রথমবার কোনও ওয়েব রিসিভার উপলভ্য হলে, Cast বোতামটি হাইলাইট করতে ব্যবহার করা যেতে পারে। প্রেরক অ্যাপ, টেক্সট, শীর্ষকের পজিশন টেক্সট ও বাতিল করার বোতাম কাস্টমাইজ করতে পারে।কাস্ট বোতাম: Cast iOS প্রেরক SDK 4.6.0 থেকে শুরু করে, প্রেরক ডিভাইস ওয়াই-ফাইয়ের সাথে কানেক্ট করা থাকলে, কাস্ট বোতাম সবসময় দেখা যায়। প্রথমবার অ্যাপ চালু করার পরে ব্যবহারকারী Cast বোতামে ট্যাপ করলে, অনুমতি সংক্রান্ত ডায়ালগ দেখানো হয় যাতে ব্যবহারকারী নেটওয়ার্কে থাকা ডিভাইসকে অ্যাপের লোকাল নেটওয়ার্ক অ্যাক্সেস দিতে পারেন। এরপরে, ব্যবহারকারী কাস্ট বোতামে ট্যাপ করলে, একটি কাস্ট ডায়ালগ দেখানো হয় যেখানে ডিসকভার করা ডিভাইসগুলির তালিকা থাকে। ডিভাইস কানেক্ট করা অবস্থায় ব্যবহারকারী কাস্ট বোতামে ট্যাপ করলে, বর্তমান মিডিয়া মেটাডেটা (যেমন, শীর্ষক, রেকর্ডিং স্টুডিওর নাম ও থাম্বনেল ছবি) দেখানো হয় অথবা ব্যবহারকারীকে কাস্ট ডিভাইস থেকে ডিসকানেক্ট করার অনুমতি দেওয়া হয়। কোনও ডিভাইস উপলভ্য না থাকাকালীন ব্যবহারকারী কাস্ট বোতামে ট্যাপ করলে, একটি স্ক্রিন দেখানো হবে যেখানে ডিভাইস কেন খুঁজে পাওয়া যাচ্ছে না এবং কীভাবে সমস্যার সমাধান করতে হবে সেই সম্পর্কে ব্যবহারকারীকে তথ্য দেওয়া হবে।
মিনি কন্ট্রোলার: ব্যবহারকারী কন্টেন্ট কাস্ট করার সময় বর্তমান কন্টেন্ট পৃষ্ঠা থেকে নেভিগেট করে সेंडर অ্যাপের অন্য স্ক্রিনে চলে গেলে, স্ক্রিনের নিচে মিনি কন্ট্রোলার দেখানো হয়। এর ফলে ব্যবহারকারী বর্তমানে কাস্ট করা মিডিয়ার মেটাডেটা দেখতে এবং প্লেব্যাক নিয়ন্ত্রণ করতে পারেন।
এক্সপ্যান্ড করা কন্ট্রোলার: ব্যবহারকারী কন্টেন্ট কাস্ট করার সময়, তিনি মিডিয়া বিজ্ঞপ্তি বা মিনি কন্ট্রোলারে ক্লিক করলে, এক্সপ্যান্ড করা কন্ট্রোলার লঞ্চ হয়, যা বর্তমানে চলছে এমন মিডিয়ার মেটাডেটা দেখায় এবং মিডিয়া প্লেব্যাক কন্ট্রোল করার জন্য একাধিক বোতাম প্রদান করে।
কাস্ট করার বোতাম যোগ করা
ফ্রেমওয়ার্ক UIButton সাবক্লাস হিসেবে Cast বোতাম কম্পোনেন্ট প্রদান করে। UIBarButtonItem-এর মধ্যে রেখে এটি
অ্যাপের টাইটেল বারে যোগ করা যেতে পারে। সাধারণ
UIViewController সাবক্লাস নিম্নলিখিত উপায়ে Cast বোতাম ইনস্টল করতে পারে:
let castButton = GCKUICastButton(frame: CGRect(x: 0, y: 0, width: 24, height: 24)) castButton.tintColor = UIColor.gray navigationItem.rightBarButtonItem = UIBarButtonItem(customView: castButton)
GCKUICastButton *castButton = [[GCKUICastButton alloc] initWithFrame:CGRectMake(0, 0, 24, 24)]; castButton.tintColor = [UIColor grayColor]; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:castButton];
ডিফল্ট হিসেবে, বোতামে ট্যাপ করলে ফ্রেমওয়ার্কের প্রদান করা কাস্ট ডায়ালগ খুলবে।
GCKUICastButton
স্টোরিবোর্ডে সরাসরি যোগ করা যেতে পারে।
ডিভাইস ডিসকভারি কনফিগার করা
ফ্রেমওয়ার্কে, ডিভাইস ডিসকভারি অটোমেটিক হয়। আপনি কাস্টম UI প্রয়োগ না করলে, ডিসকভারি প্রসেস স্পষ্টভাবে শুরু বা বন্ধ করার প্রয়োজন নেই।
ফ্রেমওয়ার্কে ডিসকভারি ম্যানেজ করে
GCKDiscoveryManager ক্লাস,
যা
GCKCastContext-এর প্রপার্টি। ফ্রেমওয়ার্ক ডিভাইস বেছে নেওয়া ও
কন্ট্রোল করার জন্য একটি ডিফল্ট কাস্ট ডায়ালগ কম্পোনেন্ট প্রদান করে।
ডিভাইসের পরিচিত নাম অনুযায়ী ডিভাইস তালিকা লেক্সিকোগ্রাফিক ক্রমে সাজানো হয়।
সেশন ম্যানেজমেন্ট কীভাবে কাজ করে
Cast SDK, Cast সেশনের ধারণা নিয়ে আসে, যার প্রতিষ্ঠা কোনও ডিভাইসে কানেক্ট করা, Web Receiver অ্যাপ লঞ্চ (বা যোগ দেওয়া), সেই অ্যাপে কানেক্ট করা এবং মিডিয়া কন্ট্রোল চ্যানেল শুরু করার ধাপগুলিকে একত্রিত করে। Cast সেশন ও Web Receiver লাইফ সাইকেল সম্পর্কে আরও জানতে, Web Receiver অ্যাপ্লিকেশন লাইফ সাইকেল গাইড দেখুন।
সেশনগুলি ক্লাস
GCKSessionManager দ্বারা ম্যানেজ করা হয়,
যা
GCKCastContext-এর প্রপার্টি।
আলাদা আলাদা সেশনকে class
GCKSession-এর সাবক্লাস দিয়ে দেখানো হয়: যেমন,
GCKCastSession
কাস্ট ডিভাইসের সেশনকে বোঝায়। আপনি বর্তমানে অ্যাক্টিভ থাকা Cast
সেশন (যদি থাকে) অ্যাক্সেস করতে পারবেন, কারণ এটি GCKSessionManager-এর currentCastSession প্রপার্টি।
সেশন তৈরি,
সাসপেনশন, আবার চালু করা এবং বন্ধ করার মতো সেশন ইভেন্ট মনিটর করতে
GCKSessionManagerListener
ইন্টারফেস ব্যবহার করা যেতে পারে। প্রেরক অ্যাপ ব্যাকগ্রাউন্ডে চলে গেলে ফ্রেমওয়ার্ক অটোমেটিক সেশন সাসপেন্ড
করে দেয় এবং অ্যাপ আবার ফোরগ্রাউন্ডে ফিরে এলে (অথবা সেশন অ্যাক্টিভ থাকাকালীন অ্যাপ
অস্বাভাবিক/আকস্মিক বন্ধ হয়ে গেলে রিলঞ্চ করা হলে) সেগুলি আবার চালু করার
চেষ্টা করে।
Cast ডায়ালগ ব্যবহার করা হলে, ব্যবহারকারীর জেসচারের উত্তরে সেশন অটোমেটিক তৈরি ও বন্ধ হয়ে যায়।
অন্যথায়, অ্যাপটি
GCKSessionManager-এ থাকা পদ্ধতির মাধ্যমে
স্পষ্টভাবে সেশন শুরু ও শেষ করতে পারে।
সেশন লাইফসাইকেল
ইভেন্টের উত্তরে অ্যাপকে বিশেষ প্রসেসিং করতে হলে, এটি GCKSessionManager-এর সাথে এক বা একাধিক GCKSessionManagerListener ইনস্ট্যান্স
রেজিস্টার করতে পারে। GCKSessionManagerListener হল একটি প্রোটোকল যা সেশন শুরু, সেশন শেষ ইত্যাদি ইভেন্টের জন্য
কলব্যাককে সংজ্ঞায়িত করে।
স্ট্রিম ট্রান্সফার
সেশন স্টেট সেভ করা হল স্ট্রিম ট্রান্সফারের ভিত্তি, যেখানে ব্যবহারকারীরা ভয়েস কমান্ড, Google Home অ্যাপ বা স্মার্ট ডিসপ্লে ব্যবহার করে ডিভাইস জুড়ে আগে থেকে থাকা অডিও ও ভিডিও স্ট্রিম সরাতে পারেন। একটি ডিভাইসে (সোর্স) মিডিয়া চালানো বন্ধ হয়ে যায় এবং অন্য ডিভাইসে (ডেস্টিনেশন) চালানো চলতে থাকে। লেটেস্ট ফার্মওয়্যার সহ যেকোনও Cast ডিভাইস, স্ট্রিম ট্রান্সফারে সোর্স বা ডেস্টিনেশন হিসেবে কাজ করতে পারে।
স্ট্রিম ট্রান্সফারের সময় নতুন ডেস্টিনেশন ডিভাইস পেতে, GCKCastSession#device
প্রপার্টিটি
[sessionManager:didResumeCastSession:]
কলব্যাকের সময় ব্যবহার করুন।
আরও তথ্যের জন্য ওয়েব রিসিভারে স্ট্রিম ট্রান্সফার দেখুন।
অটোমেটিক আবার কানেক্ট করা
Cast ফ্রেমওয়ার্ক রিকানেকশন লজিক যোগ করে যাতে রিকানেকশন অটোমেটিক ম্যানেজ করা যায় অনেক সূক্ষ্ম কর্নার কেসে, যেমন:
- ওয়াই-ফাই সাময়িকভাবে বন্ধ হয়ে গেলে তা থেকে রিকভার করা
- ডিভাইস স্লিপ মোড থেকে রিকভার করা
- অ্যাপ ব্যাকগ্রাউন্ডে চলে গেলে সেখান থেকে ফিরিয়ে আনা
- অ্যাপ ক্র্যাশ করলে ডেটা ফিরিয়ে আনা
মিডিয়া কন্ট্রোল কীভাবে কাজ করে
মিডিয়া
নেমস্পেস কাজ করে এমন কোনও ওয়েব রিসিভার অ্যাপের সাথে Cast সেশন তৈরি করা হলে, ফ্রেমওয়ার্ক অটোমেটিক
GCKRemoteMediaClient
-এর একটি ইনস্ট্যান্স তৈরি করবে; এটি
GCKCastSession
ইনস্ট্যান্সের
remoteMediaClient প্রপার্টি হিসেবে অ্যাক্সেস করা যাবে।
GCKRemoteMediaClient-এর সব পদ্ধতি Web Receiver-কে
অনুরোধ ইস্যু করে
এবং একটি GCKRequest অবজেক্ট রিটার্ন করে যা
সেই অনুরোধ ট্র্যাক করতে ব্যবহার করা যেতে পারে। অপারেশনের চূড়ান্ত
ফলাফল সম্পর্কে বিজ্ঞপ্তি পেতে এই অবজেক্টে
GCKRequestDelegate
অ্যাসাইন করা যেতে পারে।
এটি আশা করা হয় যে GCKRemoteMediaClient
ইনস্ট্যান্স অ্যাপের একাধিক অংশ শেয়ার করতে পারে এবং আসলে ফ্রেমওয়ার্কের কিছু ইন্টার্নাল কম্পোনেন্ট
যেমন Cast ডায়ালগ ও মিনি মিডিয়া কন্ট্রোল ইনস্ট্যান্স শেয়ার করে।
এই উদ্দেশ্যে, GCKRemoteMediaClient
একাধিক
GCKRemoteMediaClientListener রেজিস্ট্রেশন করা যায়।
মিডিয়া মেটাডেটা সেট করা
আপনি কাস্ট করতে চান এমন মিডিয়া আইটেম সম্পর্কে তথ্য
GCKMediaMetadata
ক্লাস দেখায়। নিচের
উদাহরণে একটি নতুন GCKMediaMetadata সিনেমার ইনস্ট্যান্স তৈরি করা হয়েছে এবং সেটির শীর্ষক,
উপশীর্ষক, রেকর্ডিং স্টুডিওর নাম ও দু'টি ছবি সেট করা হয়েছে।
let metadata = GCKMediaMetadata() metadata.setString("Big Buck Bunny (2008)", forKey: kGCKMetadataKeyTitle) metadata.setString("Big Buck Bunny tells the story of a giant rabbit with a heart bigger than " + "himself. When one sunny day three rodents rudely harass him, something " + "snaps... and the rabbit ain't no bunny anymore! In the typical cartoon " + "tradition he prepares the nasty rodents a comical revenge.", forKey: kGCKMetadataKeySubtitle) metadata.addImage(GCKImage(url: URL(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/BigBuckBunny.jpg")!, width: 480, height: 360))
GCKMediaMetadata *metadata = [[GCKMediaMetadata alloc] initWithMetadataType:GCKMediaMetadataTypeMovie]; [metadata setString:@"Big Buck Bunny (2008)" forKey:kGCKMetadataKeyTitle]; [metadata setString:@"Big Buck Bunny tells the story of a giant rabbit with a heart bigger than " "himself. When one sunny day three rodents rudely harass him, something " "snaps... and the rabbit ain't no bunny anymore! In the typical cartoon " "tradition he prepares the nasty rodents a comical revenge." forKey:kGCKMetadataKeySubtitle]; [metadata addImage:[[GCKImage alloc] initWithURL:[[NSURL alloc] initWithString:@"https://commondatastorage.googleapis.com/" "gtv-videos-bucket/sample/images/BigBuckBunny.jpg"] width:480 height:360]];
মিডিয়া মেটাডেটা সহ ছবি ব্যবহারের ব্যাপারে ছবি বেছে নেওয়া ও ক্যাশিং বিভাগ দেখুন।
মিডিয়া লোড করা
কোনও মিডিয়া আইটেম লোড করতে, মিডিয়ার মেটাডেটা ব্যবহার করে একটি
GCKMediaInformation
ইনস্ট্যান্স তৈরি করুন। তারপরে বর্তমান
GCKCastSession পান এবং
রিসিভার অ্যাপে মিডিয়া লোড করতে
এর
GCKRemoteMediaClient
ব্যবহার করুন। তারপরে, রিসিভারে চলা মিডিয়া প্লেয়ার অ্যাপ কন্ট্রোল করার জন্য GCKRemoteMediaClient
ব্যবহার করতে পারবেন, যেমন, চালাতে,
পজ করতে ও বন্ধ করতে।
let url = URL.init(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4") guard let mediaURL = url else { print("invalid mediaURL") return } let mediaInfoBuilder = GCKMediaInformationBuilder.init(contentURL: mediaURL) mediaInfoBuilder.streamType = GCKMediaStreamType.none; mediaInfoBuilder.contentType = "video/mp4" mediaInfoBuilder.metadata = metadata; mediaInformation = mediaInfoBuilder.build() guard let mediaInfo = mediaInformation else { print("invalid mediaInformation") return } if let request = sessionManager.currentSession?.remoteMediaClient?.loadMedia(mediaInfo) { request.delegate = self }
GCKMediaInformationBuilder *mediaInfoBuilder = [[GCKMediaInformationBuilder alloc] initWithContentURL: [NSURL URLWithString:@"https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"]]; mediaInfoBuilder.streamType = GCKMediaStreamTypeNone; mediaInfoBuilder.contentType = @"video/mp4"; mediaInfoBuilder.metadata = metadata; self.mediaInformation = [mediaInfoBuilder build]; GCKRequest *request = [self.sessionManager.currentSession.remoteMediaClient loadMedia:self.mediaInformation]; if (request != nil) { request.delegate = self; }
এছাড়াও, মিডিয়া ট্র্যাক ব্যবহার করা সংক্রান্ত বিভাগটি দেখুন।
4K ভিডিও ফর্ম্যাট
আপনার মিডিয়া কোন ভিডিও ফর্ম্যাটের তা নির্ধারণ করতে, GCKVideoInfo-এর বর্তমান ইনস্ট্যান্স পেতে
GCKMediaStatus
videoInfo প্রপার্টি ব্যবহার করুন।
এই ইনস্ট্যান্সে HDR TV ফর্ম্যাটের ধরন এবং পিক্সেলের
উচ্চতা ও প্রস্থ থাকে। 4K ফর্ম্যাটের ভেরিয়েন্টগুলি hdrType প্রপার্টিতে enum
ভ্যালু GCKVideoInfoHDRType দ্বারা নির্দেশিত হয়।
মিনি কন্ট্রোলার যোগ করা
কাস্ট ডিজাইন চেকলিস্ট অনুযায়ী, প্রেরক অ্যাপকে মিনি কন্ট্রোলার নামে একটি স্থায়ী কন্ট্রোল প্রদান করতে হবে যা ব্যবহারকারী বর্তমান কন্টেন্ট পৃষ্ঠা থেকে নেভিগেট করে বেরিয়ে গেলে দেখানো হবে। মিনি কন্ট্রোলার বর্তমান Cast সেশনের জন্য তৎক্ষণাৎ অ্যাক্সেস ও দৃশ্যমান রিমাইন্ডার প্রদান করে।
Cast ফ্রেমওয়ার্ক একটি কন্ট্রোল বার প্রদান করে,
GCKUIMiniMediaControlsViewController,
যেটি আপনি মিনি কন্ট্রোলার দেখাতে চান এমন দৃশ্যে যোগ করা যেতে পারে।
আপনার প্রেরক অ্যাপ কোনও ভিডিও বা অডিও লাইভ স্ট্রিম চালালে, SDK মিনি কন্ট্রোলারে থাকা 'চালান/পজ করুন' বোতামের জায়গায় অটোমেটিক 'চালান/বন্ধ করুন' বোতাম দেখায়।
আপনার প্রেরক অ্যাপ কীভাবে Cast উইজেটের চেহারা কনফিগার করতে পারে তা জানতে, iOS প্রেরক UI কাস্টমাইজ করা দেখুন।
প্রেরক অ্যাপে মিনি কন্ট্রোলার যোগ করার দুটি উপায় আছে:
- Cast ফ্রেমওয়ার্ককে মিনি কন্ট্রোলারের লেআউট ম্যানেজ করতে দিন। এর জন্য, Cast ফ্রেমওয়ার্কের নিজস্ব ভিউ কন্ট্রোলারের সাথে আপনার বর্তমান ভিউ কন্ট্রোলারকে র্যাপ করুন।
- স্টোরিবোর্ডে একটি সাবভিউ প্রদান করে আপনার বর্তমান ভিউ কন্ট্রোলারে যোগ করার মাধ্যমে মিনি কন্ট্রোলার উইজেটের লেআউট নিজেই ম্যানেজ করুন।
GCKUICastContainerViewController ব্যবহার করে র্যাপ করা
প্রথম উপায় হল
GCKUICastContainerViewController
ব্যবহার করা, যা অন্য ভিউ কন্ট্রোলারকে র্যাপ করে এবং নিচে একটি
GCKUIMiniMediaControlsViewController
যোগ করে। এই পদ্ধতির সীমাবদ্ধতা হল, আপনি অ্যানিমেশন কাস্টমাইজ করতে
পারবেন না এবং কন্টেনার ভিউ কন্ট্রোলারের আচরণ কনফিগার করতে পারবেন না।
প্রথম পদ্ধতিটি সাধারণত অ্যাপ ডেলিগেটের
-[application:didFinishLaunchingWithOptions:] পদ্ধতিতে করা হয়:
func applicationDidFinishLaunching(_ application: UIApplication) { ... // Wrap main view in the GCKUICastContainerViewController and display the mini controller. let appStoryboard = UIStoryboard(name: "Main", bundle: nil) let navigationController = appStoryboard.instantiateViewController(withIdentifier: "MainNavigation") let castContainerVC = GCKCastContext.sharedInstance().createCastContainerController(for: navigationController) castContainerVC.miniMediaControlsItemEnabled = true window = UIWindow(frame: UIScreen.main.bounds) window!.rootViewController = castContainerVC window!.makeKeyAndVisible() ... }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... // Wrap main view in the GCKUICastContainerViewController and display the mini controller. UIStoryboard *appStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; UINavigationController *navigationController = [appStoryboard instantiateViewControllerWithIdentifier:@"MainNavigation"]; GCKUICastContainerViewController *castContainerVC = [[GCKCastContext sharedInstance] createCastContainerControllerForViewController:navigationController]; castContainerVC.miniMediaControlsItemEnabled = YES; self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; self.window.rootViewController = castContainerVC; [self.window makeKeyAndVisible]; ... }
var castControlBarsEnabled: Bool { set(enabled) { if let castContainerVC = self.window?.rootViewController as? GCKUICastContainerViewController { castContainerVC.miniMediaControlsItemEnabled = enabled } else { print("GCKUICastContainerViewController is not correctly configured") } } get { if let castContainerVC = self.window?.rootViewController as? GCKUICastContainerViewController { return castContainerVC.miniMediaControlsItemEnabled } else { print("GCKUICastContainerViewController is not correctly configured") return false } } }
AppDelegate.h
@interface AppDelegate : UIResponder <UIApplicationDelegate> @property (nonatomic, strong) UIWindow *window; @property (nonatomic, assign) BOOL castControlBarsEnabled; @end
AppDelegate.m
@implementation AppDelegate ... - (void)setCastControlBarsEnabled:(BOOL)notificationsEnabled { GCKUICastContainerViewController *castContainerVC; castContainerVC = (GCKUICastContainerViewController *)self.window.rootViewController; castContainerVC.miniMediaControlsItemEnabled = notificationsEnabled; } - (BOOL)castControlBarsEnabled { GCKUICastContainerViewController *castContainerVC; castContainerVC = (GCKUICastContainerViewController *)self.window.rootViewController; return castContainerVC.miniMediaControlsItemEnabled; } ... @end
আগে থেকে থাকা ভিউ কন্ট্রোলারে এম্বেড করা
দ্বিতীয় উপায় হল, একটি
GCKUIMiniMediaControlsViewController
ইনস্ট্যান্স তৈরি করতে
createMiniMediaControlsViewController
ব্যবহার করে আপনার বর্তমান ভিউ
কন্ট্রোলারে সরাসরি মিনি কন্ট্রোলার যোগ করা এবং তারপরে এটিকে কন্টেনার ভিউ কন্ট্রোলারে সাবভিউ হিসেবে যোগ করা।
অ্যাপ ডেলিগেটে আপনার ভিউ কন্ট্রোলার সেট-আপ করুন:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { ... GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true window?.clipsToBounds = true let rootContainerVC = (window?.rootViewController as? RootContainerViewController) rootContainerVC?.miniMediaControlsViewEnabled = true ... return true }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... [GCKCastContext sharedInstance].useDefaultExpandedMediaControls = YES; self.window.clipsToBounds = YES; RootContainerViewController *rootContainerVC; rootContainerVC = (RootContainerViewController *)self.window.rootViewController; rootContainerVC.miniMediaControlsViewEnabled = YES; ... return YES; }
আপনার রুট ভিউ কন্ট্রোলারে, একটি GCKUIMiniMediaControlsViewController
ইনস্ট্যান্স তৈরি করুন এবং এটিকে কন্টেনার ভিউ কন্ট্রোলারে সাবভিউ হিসেবে যোগ করুন:
let kCastControlBarsAnimationDuration: TimeInterval = 0.20 @objc(RootContainerViewController) class RootContainerViewController: UIViewController, GCKUIMiniMediaControlsViewControllerDelegate { @IBOutlet weak private var _miniMediaControlsContainerView: UIView! @IBOutlet weak private var _miniMediaControlsHeightConstraint: NSLayoutConstraint! private var miniMediaControlsViewController: GCKUIMiniMediaControlsViewController! var miniMediaControlsViewEnabled = false { didSet { if self.isViewLoaded { self.updateControlBarsVisibility() } } } var overriddenNavigationController: UINavigationController? override var navigationController: UINavigationController? { get { return overriddenNavigationController } set { overriddenNavigationController = newValue } } var miniMediaControlsItemEnabled = false override func viewDidLoad() { super.viewDidLoad() let castContext = GCKCastContext.sharedInstance() self.miniMediaControlsViewController = castContext.createMiniMediaControlsViewController() self.miniMediaControlsViewController.delegate = self self.updateControlBarsVisibility() self.installViewController(self.miniMediaControlsViewController, inContainerView: self._miniMediaControlsContainerView) } func updateControlBarsVisibility() { if self.miniMediaControlsViewEnabled && self.miniMediaControlsViewController.active { self._miniMediaControlsHeightConstraint.constant = self.miniMediaControlsViewController.minHeight self.view.bringSubview(toFront: self._miniMediaControlsContainerView) } else { self._miniMediaControlsHeightConstraint.constant = 0 } UIView.animate(withDuration: kCastControlBarsAnimationDuration, animations: {() -> Void in self.view.layoutIfNeeded() }) self.view.setNeedsLayout() } func installViewController(_ viewController: UIViewController?, inContainerView containerView: UIView) { if let viewController = viewController { self.addChildViewController(viewController) viewController.view.frame = containerView.bounds containerView.addSubview(viewController.view) viewController.didMove(toParentViewController: self) } } func uninstallViewController(_ viewController: UIViewController) { viewController.willMove(toParentViewController: nil) viewController.view.removeFromSuperview() viewController.removeFromParentViewController() } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "NavigationVCEmbedSegue" { self.navigationController = (segue.destination as? UINavigationController) } } ...
RootContainerViewController.h
static const NSTimeInterval kCastControlBarsAnimationDuration = 0.20; @interface RootContainerViewController () <GCKUIMiniMediaControlsViewControllerDelegate> { __weak IBOutlet UIView *_miniMediaControlsContainerView; __weak IBOutlet NSLayoutConstraint *_miniMediaControlsHeightConstraint; GCKUIMiniMediaControlsViewController *_miniMediaControlsViewController; } @property(nonatomic, weak, readwrite) UINavigationController *navigationController; @property(nonatomic, assign, readwrite) BOOL miniMediaControlsViewEnabled; @property(nonatomic, assign, readwrite) BOOL miniMediaControlsItemEnabled; @end
RootContainerViewController.m
@implementation RootContainerViewController - (void)viewDidLoad { [super viewDidLoad]; GCKCastContext *castContext = [GCKCastContext sharedInstance]; _miniMediaControlsViewController = [castContext createMiniMediaControlsViewController]; _miniMediaControlsViewController.delegate = self; [self updateControlBarsVisibility]; [self installViewController:_miniMediaControlsViewController inContainerView:_miniMediaControlsContainerView]; } - (void)setMiniMediaControlsViewEnabled:(BOOL)miniMediaControlsViewEnabled { _miniMediaControlsViewEnabled = miniMediaControlsViewEnabled; if (self.isViewLoaded) { [self updateControlBarsVisibility]; } } - (void)updateControlBarsVisibility { if (self.miniMediaControlsViewEnabled && _miniMediaControlsViewController.active) { _miniMediaControlsHeightConstraint.constant = _miniMediaControlsViewController.minHeight; [self.view bringSubviewToFront:_miniMediaControlsContainerView]; } else { _miniMediaControlsHeightConstraint.constant = 0; } [UIView animateWithDuration:kCastControlBarsAnimationDuration animations:^{ [self.view layoutIfNeeded]; }]; [self.view setNeedsLayout]; } - (void)installViewController:(UIViewController *)viewController inContainerView:(UIView *)containerView { if (viewController) { [self addChildViewController:viewController]; viewController.view.frame = containerView.bounds; [containerView addSubview:viewController.view]; [viewController didMoveToParentViewController:self]; } } - (void)uninstallViewController:(UIViewController *)viewController { [viewController willMoveToParentViewController:nil]; [viewController.view removeFromSuperview]; [viewController removeFromParentViewController]; } - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"NavigationVCEmbedSegue"]) { self.navigationController = (UINavigationController *)segue.destinationViewController; } } ... @end
মিনি কন্ট্রোলার কখন দেখা যাবে তা
GCKUIMiniMediaControlsViewControllerDelegate
হোস্ট ভিউ কন্ট্রোলারকে জানায়:
func miniMediaControlsViewController(_: GCKUIMiniMediaControlsViewController, shouldAppear _: Bool) { updateControlBarsVisibility() }
- (void)miniMediaControlsViewController: (GCKUIMiniMediaControlsViewController *)miniMediaControlsViewController shouldAppear:(BOOL)shouldAppear { [self updateControlBarsVisibility]; }
বড় করা কন্ট্রোলার যোগ করা
Google Cast ডিজাইন চেকলিস্ট অনুযায়ী, কাস্ট করা মিডিয়ার জন্য প্রেরক অ্যাপকে একটি এক্সপ্যান্ডেড কন্ট্রোলার প্রদান করতে হবে। এক্সপ্যান্ড করা কন্ট্রোলার হল মিনি কন্ট্রোলারের ফুল-স্ক্রিন ভার্সন।
এক্সপ্যান্ড করা কন্ট্রোলার হল একটি ফুল-স্ক্রিন ভিউ যা রিমোট মিডিয়া প্লেব্যাকের সম্পূর্ণ কন্ট্রোল অফার করে। এই ভিউটি কাস্ট সেশনের প্রতিটি ম্যানেজ করা যায় এমন দিক ম্যানেজ করার জন্য কাস্টিং অ্যাপকে অনুমতি দেয়। তবে, ওয়েব রিসিভার ভলিউম কন্ট্রোল ও সেশন লাইফসাইকেল (কানেক্ট/কাস্ট করা বন্ধ করা) এর ব্যতিক্রম। এছাড়াও, এটি মিডিয়া সেশন (আর্টওয়ার্ক, শীর্ষক, উপশীর্ষক এবং আরও অনেক কিছু) সম্পর্কিত সমস্ত স্ট্যাটাস তথ্য প্রদান করে।
এই ভিউয়ের কার্যকারিতা
GCKUIExpandedMediaControlsViewController
ক্লাস দ্বারা প্রয়োগ করা হয়।
আপনাকে প্রথমে যা করতে হবে তা হল, কাস্ট কনটেক্সটে ডিফল্ট এক্সপ্যান্ডেড কন্ট্রোলার চালু করতে হবে। ডিফল্ট এক্সপ্যান্ডেড কন্ট্রোলার চালু করতে অ্যাপ ডেলিগেট পরিবর্তন করুন:
func applicationDidFinishLaunching(_ application: UIApplication) { .. GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true ... }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... [GCKCastContext sharedInstance].useDefaultExpandedMediaControls = YES; .. }
ব্যবহারকারী ভিডিও কাস্ট করা শুরু করলে, এক্সপ্যান্ড করা কন্ট্রোলার লোড করতে আপনার ভিউ কন্ট্রোলারে নিম্নলিখিত কোড যোগ করুন:
func playSelectedItemRemotely() { GCKCastContext.sharedInstance().presentDefaultExpandedMediaControls() ... // Load your media sessionManager.currentSession?.remoteMediaClient?.loadMedia(mediaInformation) }
- (void)playSelectedItemRemotely { [[GCKCastContext sharedInstance] presentDefaultExpandedMediaControls]; ... // Load your media [self.sessionManager.currentSession.remoteMediaClient loadMedia:mediaInformation]; }
এছাড়াও, ব্যবহারকারী মিনি কন্ট্রোলারে ট্যাপ করলে, বড় কন্ট্রোলার অটোমেটিক লঞ্চ হয়ে যাবে।
আপনার প্রেরক অ্যাপ কোনও ভিডিও বা অডিও লাইভ স্ট্রিম চালালে, SDK এক্সপ্যান্ড করা কন্ট্রোলারে থাকা 'চালান/পজ করুন' বোতামের পরিবর্তে অটোমেটিক 'চালান/বন্ধ করুন' বোতাম দেখায়।
আপনার প্রেরক অ্যাপ কীভাবে Cast উইজেটের চেহারা কনফিগার করতে পারে তা জানতে আপনার iOS অ্যাপে কাস্টম স্টাইল প্রয়োগ করুন লিঙ্ক দেখুন।
ভলিউম কন্ট্রোল
Cast ফ্রেমওয়ার্ক অটোমেটিক প্রেরক অ্যাপের ভলিউম ম্যানেজ করে। ফ্রেমওয়ার্ক অটোমেটিক
প্রদান করা UI উইজেটের জন্য ওয়েব রিসিভার ভলিউমের সাথে সিঙ্ক করে।
অ্যাপের দেওয়া স্লাইডার সিঙ্ক করতে, GCKUIDeviceVolumeController ব্যবহার করুন।
ফিজিক্যাল বোতামের মাধ্যমে ভলিউম কন্ট্রোল
সেন্ডার ডিভাইসের ফিজিক্যাল ভলিউম বোতাম ব্যবহার করে
physicalVolumeButtonsWillControlDeviceVolume ফ্ল্যাগ ব্যবহার করে ওয়েব রিসিভারে Cast সেশনের ভলিউম পরিবর্তন করা যেতে পারে।
GCKCastOptions,
এটি
GCKCastContext-এ সেট করা আছে।
let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID) let options = GCKCastOptions(discoveryCriteria: criteria) options.physicalVolumeButtonsWillControlDeviceVolume = true GCKCastContext.setSharedInstanceWith(options)
GCKDiscoveryCriteria *criteria = [[GCKDiscoveryCriteria alloc] initWithApplicationID:kReceiverAppID]; GCKCastOptions *options = [[GCKCastOptions alloc] initWithDiscoveryCriteria :criteria]; options.physicalVolumeButtonsWillControlDeviceVolume = YES; [GCKCastContext setSharedInstanceWithOptions:options];
সমস্যা ম্যানেজ করা
প্রেরক অ্যাপের জন্য সমস্ত ত্রুটি কলব্যাক ম্যানেজ করা এবং Cast লাইফ সাইকেলের প্রতিটি স্টেজের জন্য সবচেয়ে ভালো উত্তর নির্ধারণ করা খুবই গুরুত্বপূর্ণ। অ্যাপটি ব্যবহারকারীকে সমস্যা সংক্রান্ত ডায়ালগ দেখাতে পারে অথবা Cast সেশন শেষ করার সিদ্ধান্ত নিতে পারে।
মনে রাখবেন যে কিছু সমস্যা, যার মধ্যে
GCKErrorCode
GCKErrorCodeCancelled রয়েছে, সেগুলি উদ্দেশ্যপ্রণোদিত আচরণ।
GCKErrorCodeCancelled-এর সাথে কানেক্ট করা না গেলে আবার চেষ্টা করবেন না।
এটি করলে অপ্রত্যাশিত আচরণ দেখা যেতে পারে।
লগিং
GCKLogger
ফ্রেমওয়ার্কের মাধ্যমে লগ করার জন্য ব্যবহৃত একটি সিঙ্গলটন। আপনি কীভাবে লগ মেসেজ ম্যানেজ করবেন তা কাস্টমাইজ করতে
GCKLoggerDelegate
ব্যবহার করুন।
GCKLogger ব্যবহার করে, SDK লগিং আউটপুট তৈরি করে যা ডিবাগ
মেসেজ, সমস্যা ও সতর্কতা হিসেবে দেখানো হয়। এইসব লগ মেসেজ ডিবাগ করতে সাহায্য করে এবং সমস্যা সমাধান ও শনাক্ত করার জন্য
উপযোগী। ডিফল্ট হিসেবে, লগ আউটপুট
লুকানো থাকে, কিন্তু GCKLoggerDelegateঅ্যাসাইন করার মাধ্যমে, প্রেরক অ্যাপ SDK থেকে
এইসব মেসেজ পেতে এবং সিস্টেম কনসোলে লগ করতে পারে।
@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, GCKLoggerDelegate { let kReceiverAppID = kGCKDefaultMediaReceiverApplicationID let kDebugLoggingEnabled = true var window: UIWindow? func applicationDidFinishLaunching(_ application: UIApplication) { ... // Enable logger. GCKLogger.sharedInstance().delegate = self ... } // MARK: - GCKLoggerDelegate func logMessage(_ message: String, at level: GCKLoggerLevel, fromFunction function: String, location: String) { if (kDebugLoggingEnabled) { print(function + " - " + message) } } }
AppDelegate.h
@interface AppDelegate () <GCKLoggerDelegate> @end
AppDelegate.m
@implementation AppDelegate static NSString *const kReceiverAppID = @"AABBCCDD"; static const BOOL kDebugLoggingEnabled = YES; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... // Enable logger. [GCKLogger sharedInstance].delegate = self; ... return YES; } ... #pragma mark - GCKLoggerDelegate - (void)logMessage:(NSString *)message atLevel:(GCKLoggerLevel)level fromFunction:(NSString *)function location:(NSString *)location { if (kDebugLoggingEnabled) { NSLog(@"%@ - %@, %@", function, message, location); } } @end
এছাড়াও, ডিবাগ ও ভার্বোজ মেসেজ চালু করতে, ডেলিগেট সেট করার পরে (আগে দেখানো হয়েছে) কোডে এই লাইনটি যোগ করুন:
let filter = GCKLoggerFilter.init() filter.minimumLevel = GCKLoggerLevel.verbose GCKLogger.sharedInstance().filter = filter
GCKLoggerFilter *filter = [[GCKLoggerFilter alloc] init]; [filter setMinimumLevel:GCKLoggerLevelVerbose]; [GCKLogger sharedInstance].filter = filter;
এছাড়াও, আপনি
GCKLogger-এর তৈরি করা লগ মেসেজ ফিল্টার করতে পারবেন।
প্রতিটি ক্লাসের জন্য ন্যূনতম লগিং লেভেল সেট করুন, যেমন:
let filter = GCKLoggerFilter.init() filter.setLoggingLevel(GCKLoggerLevel.verbose, forClasses: ["GCKUICastButton", "GCKUIImageCache", "NSMutableDictionary"]) GCKLogger.sharedInstance().filter = filter
GCKLoggerFilter *filter = [[GCKLoggerFilter alloc] init]; [filter setLoggingLevel:GCKLoggerLevelVerbose forClasses:@[@"GCKUICastButton", @"GCKUIImageCache", @"NSMutableDictionary" ]]; [GCKLogger sharedInstance].filter = filter;
ক্লাসের নাম আক্ষরিক নাম বা গ্লোব প্যাটার্ন হতে পারে, যেমন,
GCKUI\* এবং GCK\*Session।