iOS প্রেরক SDK ব্যবহার করে আপনার iOS প্রেরক অ্যাপে কীভাবে Google Cast সহায়তা যোগ করবেন তা এই ডেভেলপার গাইডে বর্ণনা করা হয়েছে।
মোবাইল ডিভাইস বা ল্যাপটপ হল প্রেরক যা প্লেব্যাক নিয়ন্ত্রণ করে এবং Google Cast ডিভাইস হল প্রাপক যা টিভিতে কন্টেন্ট দেখায়।
প্রেরক ফ্রেমওয়ার্ক বলতে Cast ক্লাস লাইব্রেরি বাইনারি এবং রানটাইমে প্রেরকের কাছে উপলভ্য সংশ্লিষ্ট রিসোর্সকে বোঝায়। প্রেরক অ্যাপ বা Cast অ্যাপ বলতে এমন অ্যাপকে বোঝায় যা প্রেরকের ডিভাইসেও চলছে। ওয়েব রিসিভার অ্যাপ বলতে ওয়েব রিসিভারে চলা HTML অ্যাপ্লিকেশনকে বোঝায়।
প্রেরক ফ্রেমওয়ার্ক অ্যাসিঙ্ক্রোনাস কলব্যাক ডিজাইন ব্যবহার করে প্রেরক অ্যাপকে ইভেন্ট সম্পর্কে জানায় এবং Cast অ্যাপ লাইফ সাইকেলের বিভিন্ন অবস্থার মধ্যে ট্রানজিশন করে।
অ্যাপ ফ্লো
নিম্নলিখিত ধাপগুলি iOS অ্যাপ প্রেরকের জন্য সাধারণ হাই-লেভেল এক্সিকিউশন ফ্লো বর্ণনা করে:
- ডিভাইস স্ক্যান করা শুরু করতে
GCKCastOptions-এ প্রদান করা প্রপার্টির উপর ভিত্তি করেGCKDiscoveryManagerCast ফ্রেমওয়ার্ক শুরু হয়। - ব্যবহারকারী কাস্ট করার বোতামে ক্লিক করলে, ফ্রেমওয়ার্কটি খুঁজে পাওয়া কাস্ট ডিভাইসের তালিকা সহ কাস্ট ডায়ালগ দেখায়।
- ব্যবহারকারী কোনও Cast ডিভাইস বেছে নিলে, ফ্রেমওয়ার্ক Cast ডিভাইসে Web Receiver অ্যাপ চালু করার চেষ্টা করে।
- ফ্রেমওয়ার্ক, প্রেরক অ্যাপে কলব্যাক ইনভোক করে যাতে কনফার্ম করা যায় যে Web Receiver অ্যাপ চালু করা হয়েছে।
- ফ্রেমওয়ার্কটি প্রেরক এবং ওয়েব রিসিভার অ্যাপের মধ্যে একটি কমিউনিকেশন চ্যানেল তৈরি করে।
- ফ্রেমওয়ার্কটি ওয়েব রিসিভারে মিডিয়া প্লেব্যাক লোড ও নিয়ন্ত্রণ করতে কমিউনিকেশন চ্যানেল ব্যবহার করে।
- ফ্রেমওয়ার্কটি প্রেরক এবং ওয়েব রিসিভারের মধ্যে মিডিয়া প্লেব্যাক স্ট্যাটাস সিঙ্ক করে: ব্যবহারকারী প্রেরক UI অ্যাকশন করলে, ফ্রেমওয়ার্কটি সেই মিডিয়া কন্ট্রোল অনুরোধগুলি ওয়েব রিসিভারে পাঠায় এবং ওয়েব রিসিভার মিডিয়া স্ট্যাটাস আপডেট পাঠালে, ফ্রেমওয়ার্কটি প্রেরক UI-এর স্ট্যাটাস আপডেট করে।
- ব্যবহারকারী Cast ডিভাইস থেকে ডিসকানেক্ট করার জন্য Cast বোতামে ক্লিক করলে, ফ্রেমওয়ার্ক Web Receiver থেকে প্রেরক অ্যাপ ডিসকানেক্ট করবে।
আপনার প্রেরকের সমস্যার সমাধান করতে, আপনাকে লগিং চালু করতে হবে।
Google Cast iOS ফ্রেমওয়ার্কে সব ক্লাস, পদ্ধতি ও ইভেন্টের সম্পূর্ণ তালিকা দেখতে, Google Cast iOS API রেফারেন্স দেখুন। নিম্নলিখিত বিভাগে আপনার iOS অ্যাপে Cast ইন্টিগ্রেট করার ধাপগুলি কভার করা হয়েছে।
প্রধান থ্রেড থেকে কল পদ্ধতি
Cast কন্টেক্সট শুরু করুন
Cast ফ্রেমওয়ার্কে একটি গ্লোবাল সিঙ্গলটন অবজেক্ট আছে,
GCKCastContext, যা
ফ্রেমওয়ার্কের সব অ্যাক্টিভিটি কোঅর্ডিনেট করে। এই অবজেক্টটি অ্যাপ্লিকেশনের লাইফসাইকেলের
শুরুতেই ইনিশিয়ালাইজ করতে হবে, সাধারণত অ্যাপ ডেলিগেটের
-[application:didFinishLaunchingWithOptions:] পদ্ধতিতে, যাতে
সেন্ডার অ্যাপ রিস্টার্ট করার সময় অটোমেটিক সেশন রিজাম্পশন সঠিকভাবে ট্রিগার করা যায়।
GCKCastContext শুরু করার সময় একটি GCKCastOptions
অবজেক্ট অবশ্যই প্রদান করতে হবে।
এই ক্লাসে এমন বিকল্প আছে যা ফ্রেমওয়ার্কের আচরণকে প্রভাবিত করে। এর মধ্যে সবচেয়ে
গুরুত্বপূর্ণ হল ওয়েব রিসিভার অ্যাপ্লিকেশন আইডি, যা ডিসকভারি ফলাফল ফিল্টার করতে এবং কাস্ট সেশন শুরু হলে
ওয়েব রিসিভার অ্যাপ চালু করতে
ব্যবহার করা হয়।
ফ্রেমওয়ার্ক থেকে লগিং মেসেজ পাওয়ার জন্য লগিং ডেলিগেট সেট-আপ করার ক্ষেত্রে
-[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 iOS প্রেরক SDK 4.6.0 থেকে শুরু করে, প্রেরক ডিভাইস ওয়াই-ফাইয়ের সাথে কানেক্ট করা থাকলে, কাস্ট করার বোতাম সবসময় দেখা যায়। অ্যাপটি প্রথমবার চালু করার পরে ব্যবহারকারী প্রথমবার কাস্ট বোতামে ট্যাপ করলে, একটি অনুমতি ডায়ালগ দেখানো হয় যাতে ব্যবহারকারী অ্যাপটিকে নেটওয়ার্কে থাকা ডিভাইসে লোকাল নেটওয়ার্ক অ্যাক্সেস করার অনুমতি দিতে পারেন। এরপর, ব্যবহারকারী কাস্ট করার বোতামে ট্যাপ করলে, একটি কাস্ট ডায়ালগ দেখানো হয় যেখানে খুঁজে পাওয়া ডিভাইসের তালিকা থাকে। ডিভাইস কানেক্ট করা থাকাকালীন ব্যবহারকারী কাস্ট করার বোতামে ট্যাপ করলে, এটি বর্তমান মিডিয়া মেটাডেটা (যেমন, টাইটেল, রেকর্ডিং স্টুডিওর নাম এবং থাম্বনেল ছবি) দেখায় অথবা ব্যবহারকারীকে কাস্ট ডিভাইস থেকে ডিসকানেক্ট করার অনুমতি দেয়। কোনও ডিভাইস উপলভ্য না থাকা অবস্থায় ব্যবহারকারী কাস্ট করার বোতামে ট্যাপ করলে, একটি স্ক্রিন দেখানো হবে যেখানে ব্যবহারকারীকে জানানো হবে যে কেন ডিভাইস খুঁজে পাওয়া যায়নি এবং কীভাবে সমস্যার সমাধান করতে হবে।
মিনি কন্ট্রোলার: ব্যবহারকারী কন্টেন্ট কাস্ট করার সময় বর্তমান কন্টেন্ট পৃষ্ঠা থেকে নেভিগেট করে অন্য পৃষ্ঠায় চলে গেলে অথবা প্রেরক অ্যাপে অন্য স্ক্রিনে কন্ট্রোলার বড় করলে, স্ক্রিনের নিচে মিনি কন্ট্রোলার দেখানো হয়। এর ফলে ব্যবহারকারী বর্তমানে কাস্ট করা মিডিয়া মেটাডেটা দেখতে এবং প্লেব্যাক কন্ট্রোল করতে পারেন।
এক্সপ্যান্ড করা কন্ট্রোলার: ব্যবহারকারী কন্টেন্ট কাস্ট করার সময়, মিডিয়া বিজ্ঞপ্তি বা মিনি কন্ট্রোলারে ক্লিক করলে, এক্সপ্যান্ড করা কন্ট্রোলার চালু হয়, যা বর্তমানে চলা মিডিয়া মেটাডেটা দেখায় এবং মিডিয়া প্লেব্যাক নিয়ন্ত্রণ করার জন্য একাধিক বোতাম প্রদান করে।
'কাস্ট করুন' বোতাম যোগ করা
ফ্রেমওয়ার্কটি UIButton সাবক্লাস হিসেবে কাস্ট করার বোতাম কম্পোনেন্ট প্রদান করে। এটি UIBarButtonItem-এ
র্যাপ করে অ্যাপের টাইটেল বারে যোগ করা যেতে পারে। একটি সাধারণ
UIViewController সাবক্লাস নিম্নলিখিত উপায়ে কাস্ট করার বোতাম ইনস্টল করতে পারে:
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];
ডিফল্ট হিসেবে, বোতামে ট্যাপ করলে ফ্রেমওয়ার্কের মাধ্যমে প্রদান করা Cast ডায়ালগ খুলে যাবে।
GCKUICastButton
সরাসরি স্টোরিবোর্ডেও যোগ করা যেতে পারে।
ডিভাইস ডিসকভারি কনফিগার করুন
ফ্রেমওয়ার্কে, ডিভাইস খোঁজার কাজ অটোমেটিক হয়। আপনি কাস্টম UI প্রয়োগ না করলে, আলাদা করে ডিসকভারি প্রসেস শুরু বা বন্ধ করার প্রয়োজন নেই।
ফ্রেমওয়ার্কে ডিসকভারি
GCKDiscoveryManager
ক্লাস দ্বারা ম্যানেজ করা হয়, যা
GCKCastContext-এর
একটি প্রপার্টি। ডিভাইস বেছে নেওয়া ও কন্ট্রোল করার জন্য
ফ্রেমওয়ার্ক ডিফল্ট Cast ডায়ালগ কম্পোনেন্ট প্রদান করে। ডিভাইসের বন্ধুত্বপূর্ণ নাম অনুযায়ী ডিভাইসের তালিকা অভিধানের ক্রম অনুসারে সাজানো আছে।
সেশন ম্যানেজমেন্ট কীভাবে কাজ করে
Cast SDK-তে Cast সেশনের ধারণাটি চালু করা হয়েছে, যার মাধ্যমে কোনও ডিভাইসে কানেক্ট করা, ওয়েব রিসিভার অ্যাপ চালু করা (বা তাতে যোগ দেওয়া), সেই অ্যাপে কানেক্ট করা এবং মিডিয়া কন্ট্রোল চ্যানেল শুরু করার ধাপগুলি একত্রিত করা হয়। Cast সেশন এবং ওয়েব রিসিভার লাইফ সাইকেল সম্পর্কে আরও জানতে অ্যাপ্লিকেশন লাইফ সাইকেল গাইড দেখুন।
সেশনগুলি
GCKSessionManager
ক্লাস দ্বারা পরিচালিত হয়,
যা
GCKCastContext-এর
একটি প্রপার্টি।
আলাদা আলাদা সেশনকে ক্লাসের সাবক্লাস হিসেবে দেখানো হয়
GCKSession: যেমন,
GCKCastSession
Cast ডিভাইসের সাথে সেশন দেখায়। আপনি বর্তমানে অ্যাক্টিভ Cast সেশন (যদি থাকে) অ্যাক্সেস করতে পারবেন,
GCKSessionManager-এর currentCastSession প্রপার্টি হিসেবে।
GCKSessionManagerListener
ইন্টারফেস ব্যবহার করে সেশন ইভেন্ট মনিটর করা যায়, যেমন সেশন তৈরি,
সাসপেন্ড, আবার চালু ও বন্ধ করা। প্রেরক অ্যাপ ব্যাকগ্রাউন্ডে চলে গেলে ফ্রেমওয়ার্ক অটোমেটিক সেশন সাসপেন্ড করে দেয় এবং অ্যাপ ফোরগ্রাউন্ডে ফিরে এলে (অথবা সেশন অ্যাক্টিভ থাকাকালীন অ্যাপ অস্বাভাবিক/হঠাৎ বন্ধ হয়ে যাওয়ার পরে আবার চালু হলে) সেশন আবার শুরু করার চেষ্টা করে।
Cast ডায়ালগ ব্যবহার করা হলে, ব্যবহারকারীর জেসচারের উত্তরে সেশন অটোমেটিক তৈরি ও বন্ধ
করা হয়। অন্যথায়, অ্যাপটি GCKSessionManager-এ
পদ্ধতির মাধ্যমে স্পষ্টভাবে সেশন শুরু ও শেষ
করতে পারে।
সেশন লাইফসাইকেল ইভেন্টের উত্তরে অ্যাপকে বিশেষ প্রসেসিং করতে হলে, এটি GCKSessionManager-এর সাথে এক বা একাধিক GCKSessionManagerListener ইনস্ট্যান্স
রেজিস্টার করতে পারে। GCKSessionManagerListener হল একটি প্রোটোকল যা সেশন শুরু, সেশন শেষ এবং এই ধরনের ইভেন্টের জন্য
কলব্যাক নির্ধারণ করে।
স্ট্রিম ট্রান্সফার করার ফিচার
সেশন স্টেট সংরক্ষণ করা হল স্ট্রিম ট্রান্সফারের ভিত্তি, যেখানে ব্যবহারকারীরা ভয়েস কমান্ড, Google Home অ্যাপ বা স্মার্ট ডিসপ্লে ব্যবহার করে বিভিন্ন ডিভাইসে বর্তমান অডিও ও ভিডিও স্ট্রিম ট্রান্সফার করতে পারবেন। একটি ডিভাইসে (সোর্স) মিডিয়া চলা বন্ধ হয়ে যায় এবং অন্য ডিভাইসে (ডেস্টিনেশন) চালু থাকে। লেটেস্ট ফার্মওয়্যার সহ যেকোনও Cast ডিভাইস স্ট্রিম ট্রান্সফারের সোর্স বা ডেস্টিনেশন হিসেবে কাজ করতে পারে।
স্ট্রিম ট্রান্সফার করার সময় নতুন ডেস্টিনেশন ডিভাইস পেতে,
[sessionManager:didResumeCastSession:]
কলব্যাকের সময়
GCKCastSession#device
প্রপার্টি ব্যবহার করুন।
আরও তথ্যের জন্য ওয়েব রিসিভারে স্ট্রিম ট্রান্সফার করার ফিচার দেখুন।
অটোমেটিক আবার কানেক্ট করা
Cast ফ্রেমওয়ার্ক, অনেক সূক্ষ্ম কর্নার কেসে অটোমেটিক আবার কানেক্ট করার জন্য রিকানেকশন লজিক যোগ করে, যেমন:
- সাময়িকভাবে ওয়াই-ফাই কানেকশন চলে গেলে তা আগের অবস্থায় ফিরিয়ে আনা
- ডিভাইস স্লিপ মোড থেকে রিকভার করুন
- অ্যাপ ব্যাকগ্রাউন্ডে চলে যাওয়ার সমস্যা থেকে রিকভার করা
- অ্যাপ ক্র্যাশ করলে রিকভার করুন
মিডিয়া কন্ট্রোল কীভাবে কাজ করে
মিডিয়া নেমস্পেস সাপোর্ট করে এমন কোনও ওয়েব রিসিভার অ্যাপের সাথে কাস্ট সেশন তৈরি করা হলে, ফ্রেমওয়ার্কের মাধ্যমে অটোমেটিক
GCKRemoteMediaClient-এর
একটি ইনস্ট্যান্স তৈরি করা হবে;
GCKCastSession
ইনস্ট্যান্সের
remoteMediaClient প্রপার্টি হিসেবে এটি অ্যাক্সেস করা যাবে।
GCKRemoteMediaClient-এর সব পদ্ধতি যা ওয়েব রিসিভারকে অনুরোধ পাঠায়
তা একটি
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 টিভি ফর্ম্যাটের ধরন এবং পিক্সেল অনুযায়ী উচ্চতা ও প্রস্থের তথ্য
থাকে। 4K ফর্ম্যাটের ভেরিয়েন্ট hdrType প্রপার্টিতে enum
ভ্যালু GCKVideoInfoHDRType দ্বারা দেখানো হয়।
মিনি কন্ট্রোলার যোগ করুন
Cast ডিজাইন চেকলিস্ট অনুযায়ী, প্রেরক অ্যাপের মিনি কন্ট্রোলার নামে পরিচিত একটি স্থায়ী কন্ট্রোল প্রদান করা উচিত যা ব্যবহারকারী বর্তমান কন্টেন্ট পৃষ্ঠা থেকে অন্য পৃষ্ঠায় গেলে দেখানো উচিত। মিনি কন্ট্রোলার, বর্তমান Cast সেশনের জন্য ইনস্ট্যান্ট অ্যাক্সেস ও দৃশ্যমান রিমাইন্ডার প্রদান করে।
Cast ফ্রেমওয়ার্ক একটি কন্ট্রোল বার প্রদান করে,
GCKUIMiniMediaControlsViewController,
যা সেইসব দৃশ্যে যোগ করা যেতে পারে যেখানে আপনি মিনি কন্ট্রোলার দেখাতে চান।
আপনার প্রেরক অ্যাপ কোনও ভিডিও বা অডিও লাইভ স্ট্রিম চালালে, SDK মিনি কন্ট্রোলারে প্লে/পজ বোতামের পরিবর্তে অটোমেটিক প্লে/স্টপ বোতাম দেখায়।
আপনার প্রেরক অ্যাপ কীভাবে Cast উইজেটের চেহারা কনফিগার করতে পারে তার জন্য iOS প্রেরক UI কাস্টমাইজ করুন দেখুন।
প্রেরক অ্যাপে মিনি কন্ট্রোলার যোগ করার দুটি উপায় আছে:
- আপনার বর্তমান ভিউ কন্ট্রোলারকে নিজের ভিউ কন্ট্রোলারের সাথে র্যাপ করার মাধ্যমে 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
আগে থেকে থাকা ভিউ কন্ট্রোলারে এম্বেড করুন
দ্বিতীয় উপায় হল,
createMiniMediaControlsViewController
ব্যবহার করে
GCKUIMiniMediaControlsViewController
ইনস্ট্যান্স তৈরি করে এবং তারপর কন্টেনার ভিউ কন্ট্রোলারে সাবভিউ হিসেবে যোগ করে, আপনার বর্তমান ভিউ কন্ট্রোলারে সরাসরি মিনি কন্ট্রোলার যোগ করা।
অ্যাপ ডেলিগেটে আপনার ভিউ কন্ট্রোলার সেট-আপ করুন:
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 অ্যাপে কাস্টম স্টাইল প্রয়োগ করুন দেখুন।
ভলিউম কন্ট্রোল
কাস্ট ফ্রেমওয়ার্ক অটোমেটিক প্রেরক অ্যাপের ভলিউম ম্যানেজ করে।
ফ্রেমওয়ার্ক অটোমেটিক সরবরাহ করা UI উইজেটের জন্য ওয়েব রিসিভার ভলিউমের সাথে
সিঙ্ক করে। অ্যাপের মাধ্যমে প্রদান করা স্লাইডার সিঙ্ক করতে,
GCKUIDeviceVolumeController ব্যবহার করুন।
ফিজিক্যাল বোতামের মাধ্যমে ভলিউম কন্ট্রোল
GCKCastContext-এ সেট করা
GCKCastOptions-এর
physicalVolumeButtonsWillControlDeviceVolume ফ্ল্যাগ ব্যবহার করে
ওয়েব রিসিভারে কাস্ট সেশনের ভলিউম পরিবর্তন করতে
প্রেরক ডিভাইসের ফিজিক্যাল ভলিউম বোতাম ব্যবহার করা যেতে পারে।
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।