इस डेवलपर गाइड में, iOS Sender SDK टूल का इस्तेमाल करके, अपने iOS डिवाइस से स्क्रीन शेयर करने वाले ऐप्लिकेशन में Google Cast की सुविधा जोड़ने का तरीका बताया गया है.
मोबाइल डिवाइस या लैपटॉप, संचालक होता है, जो वीडियो चलाने की सुविधा को कंट्रोल करता है. वहीं, Google Cast डिवाइस रिसीवर होता है, जो टीवी पर कॉन्टेंट दिखाता है.
संडर फ़्रेमवर्क, भेजने वाले डिवाइस पर रनटाइम के दौरान मौजूद Cast क्लास लाइब्रेरी बाइनरी और उससे जुड़े संसाधनों को दिखाता है. ऐप्लिकेशन भेजने वाले व्यक्ति के डिवाइस पर मौजूद ऐप्लिकेशन या कास्ट करने वाला ऐप्लिकेशन, दोनों एक ही ऐप्लिकेशन होते हैं. वेब रिसीवर ऐप्लिकेशन का मतलब, वेब रिसीवर पर चल रहे एचटीएमएल ऐप्लिकेशन से है.
Sender फ़्रेमवर्क, इवेंट के बारे में Sender ऐप्लिकेशन को बताने और Cast ऐप्लिकेशन के लाइफ़साइकल की अलग-अलग स्थितियों के बीच ट्रांज़िशन करने के लिए, असाइनोक्रोनस कॉलबैक डिज़ाइन का इस्तेमाल करता है.
ऐप्लिकेशन फ़्लो
यहां दिए गए चरणों में, ईमेल भेजने वाले iOS ऐप्लिकेशन के लिए, सामान्य तौर पर ईमेल भेजने के फ़्लो के बारे में बताया गया है:
- डिवाइसों को स्कैन करने के लिए,
GCKCastOptions
में दी गई प्रॉपर्टी के आधार पर, Cast फ़्रेमवर्कGCKDiscoveryManager
शुरू होता है. - जब उपयोगकर्ता 'कास्ट करें' बटन पर क्लिक करता है, तो फ़्रेमवर्क, 'कास्ट करें' डायलॉग बॉक्स के साथ, ढूंढे गए Cast डिवाइसों की सूची दिखाता है.
- जब कोई उपयोगकर्ता कोई Cast डिवाइस चुनता है, तो फ़्रेमवर्क उस डिवाइस पर Web Receiver ऐप्लिकेशन को लॉन्च करने की कोशिश करता है.
- फ़्रेमवर्क, वेब रिसीवर ऐप्लिकेशन के लॉन्च होने की पुष्टि करने के लिए, भेजने वाले ऐप्लिकेशन में कॉलबैक को ट्रिगर करता है.
- यह फ़्रेमवर्क, ईमेल भेजने वाले और वेब रिसीवर ऐप्लिकेशन के बीच कम्यूनिकेशन चैनल बनाता है.
- यह फ़्रेमवर्क, वेब रिसीवर पर मीडिया चलाने की सुविधा को लोड और कंट्रोल करने के लिए, कम्यूनिकेशन चैनल का इस्तेमाल करता है.
- फ़्रेमवर्क, मीडिया चलाने की स्थिति को भेजने वाले और वेब रिसीवर के बीच सिंक करता है: जब उपयोगकर्ता, भेजने वाले के यूज़र इंटरफ़ेस (यूआई) पर कोई कार्रवाई करता है, तो फ़्रेमवर्क उन मीडिया कंट्रोल के अनुरोधों को वेब रिसीवर को भेजता है. साथ ही, जब वेब रिसीवर मीडिया की स्थिति के अपडेट भेजता है, तो फ़्रेमवर्क, भेजने वाले के यूज़र इंटरफ़ेस की स्थिति को अपडेट करता है.
- जब उपयोगकर्ता, Cast डिवाइस से डिसकनेक्ट करने के लिए Cast बटन पर क्लिक करता है, तो फ़्रेमवर्क, वेब रिसीवर से भेजने वाले ऐप्लिकेशन को डिसकनेक्ट कर देगा.
ईमेल भेजने वाले व्यक्ति की समस्या हल करने के लिए, आपको लॉगिंग की सुविधा चालू करनी होगी.
Google Cast के iOS फ़्रेमवर्क में मौजूद सभी क्लास, तरीकों, और इवेंट की पूरी सूची के लिए, Google Cast iOS API का रेफ़रंस देखें. यहां दिए गए सेक्शन में, iOS ऐप्लिकेशन में 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 के यूज़र इंटरफ़ेस (यूएक्स) विजेट
Cast iOS SDK, ये विजेट उपलब्ध कराता है, जो Cast के डिज़ाइन की चेकलिस्ट के मुताबिक हैं:
शुरुआती ओवरले:
GCKCastContext
क्लास में एक तरीका है,presentCastInstructionsViewControllerOnceWithCastButton
, जिसका इस्तेमाल पहली बार वेब रिसीवर उपलब्ध होने पर, कास्ट बटन को हाइलाइट करने के लिए किया जा सकता है. ईमेल भेजने वाला ऐप्लिकेशन, टेक्स्ट, टाइटल टेक्स्ट की पोज़िशन, और 'खारिज करें' बटन को पसंद के मुताबिक बना सकता है.कास्ट बटन: कास्ट करने वाले डिवाइस के वाई-फ़ाई से कनेक्ट होने पर, कास्ट बटन हमेशा दिखता है. यह सुविधा, iOS के लिए कास्ट करने वाले डिवाइस के SDK टूल के 4.6.0 वर्शन से शुरू हुई है. ऐप्लिकेशन को शुरू करने के बाद, जब उपयोगकर्ता पहली बार कास्ट बटन पर टैप करता है, तो अनुमतियों वाला डायलॉग बॉक्स दिखता है. इससे उपयोगकर्ता, ऐप्लिकेशन को नेटवर्क पर मौजूद डिवाइसों का लोकल नेटवर्क ऐक्सेस दे सकता है. इसके बाद, जब उपयोगकर्ता कास्ट बटन पर टैप करता है, तो कास्ट करने के लिए उपलब्ध डिवाइसों की सूची वाला डायलॉग दिखता है. जब डिवाइस कनेक्ट होता है, तो उपयोगकर्ता कास्ट बटन पर टैप करता है. इससे, मौजूदा मीडिया का मेटाडेटा दिखता है. जैसे, टाइटल, रिकॉर्डिंग स्टूडियो का नाम, और थंबनेल इमेज. इसके अलावा, उपयोगकर्ता को कास्ट डिवाइस से डिसकनेक्ट करने की अनुमति भी मिलती है. जब कोई डिवाइस उपलब्ध न होने पर, उपयोगकर्ता कास्ट बटन पर टैप करता है, तो उसे एक स्क्रीन दिखेगी. इस स्क्रीन पर, उपयोगकर्ता को यह जानकारी मिलेगी कि डिवाइस क्यों नहीं मिल रहे हैं और समस्या को कैसे हल किया जा सकता है.
मिनी कंट्रोलर: जब उपयोगकर्ता किसी कॉन्टेंट को कास्ट कर रहा होता है और वह कॉन्टेंट भेजने वाले ऐप्लिकेशन के मौजूदा कॉन्टेंट पेज या बड़े किए गए कंट्रोलर से किसी दूसरी स्क्रीन पर चला जाता है, तो स्क्रीन पर सबसे नीचे मिनी कंट्रोलर दिखता है. इससे उपयोगकर्ता, कास्ट किए जा रहे मौजूदा मीडिया का मेटाडेटा देख सकता है और उसे चला सकता है.
बड़ा किया गया कंट्रोलर: जब कोई उपयोगकर्ता कॉन्टेंट कास्ट कर रहा होता है, तो अगर वह मीडिया सूचना या मिनी कंट्रोलर पर क्लिक करता है, तो बड़ा किया गया कंट्रोलर लॉन्च होता है. इसमें, फ़िलहाल चल रहे मीडिया का मेटाडेटा दिखता है. साथ ही, मीडिया प्लेबैक को कंट्रोल करने के लिए कई बटन भी होते हैं.
कास्ट करने के लिए बटन जोड़ना
फ़्रेमवर्क, UIButton
सबक्लास के तौर पर कास्ट बटन कॉम्पोनेंट उपलब्ध कराता है. इसे 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
को सीधे स्टोरीबोर्ड में भी जोड़ा जा सकता है.
डिवाइस खोजे जाने की सुविधा को कॉन्फ़िगर करना
फ़्रेमवर्क में, डिवाइस की खोज अपने-आप होती है. कस्टम यूज़र इंटरफ़ेस (यूआई) लागू करने तक, डिस्कवरी प्रोसेस को साफ़ तौर पर शुरू या बंद करने की ज़रूरत नहीं है.
फ़्रेमवर्क में डिस्कवरी को क्लास GCKDiscoveryManager
मैनेज करता है. यह क्लास, GCKCastContext
की प्रॉपर्टी है. फ़्रेमवर्क, डिवाइस चुनने और उसे कंट्रोल करने के लिए, डिफ़ॉल्ट रूप से Cast डायलॉग कॉम्पोनेंट उपलब्ध कराता है. डिवाइसों की सूची, डिवाइस के आसान नाम के हिसाब से, अंग्रेज़ी के अक्षरों के मुताबिक क्रम में लगाई जाती है.
सेशन मैनेजमेंट के काम करने का तरीका
Cast SDK टूल, Cast सेशन के कॉन्सेप्ट को पेश करता है. इसे सेट अप करने के लिए, किसी डिवाइस से कनेक्ट करना, वेब रिसीवर ऐप्लिकेशन को लॉन्च करना (या उसमें शामिल होना), उस ऐप्लिकेशन से कनेक्ट करना, और मीडिया कंट्रोल चैनल को शुरू करना ज़रूरी है. कास्ट सेशन और वेब रिसीवर के लाइफ़साइकल के बारे में ज़्यादा जानने के लिए, वेब रिसीवर के ऐप्लिकेशन लाइफ़साइकल की गाइड देखें.
सेशन को क्लास GCKSessionManager
मैनेज करता है. यह GCKCastContext
की प्रॉपर्टी है.
अलग-अलग सेशन को क्लास GCKSession
के सबक्लास से दिखाया जाता है: उदाहरण के लिए, GCKCastSession
, कास्ट डिवाइसों से जुड़े सेशन दिखाता है. अगर कोई Cast
सेशन चालू है, तो उसे GCKSessionManager
की currentCastSession
प्रॉपर्टी के तौर पर ऐक्सेस किया जा सकता है.
GCKSessionManagerListener
इंटरफ़ेस का इस्तेमाल, सेशन से जुड़े इवेंट को मॉनिटर करने के लिए किया जा सकता है. जैसे, सेशन बनाना, निलंबित करना, फिर से शुरू करना, और खत्म करना. फ़्रेमवर्क, सेशन को अपने-आप निलंबित कर देता है, जब ईमेल भेजने वाला ऐप्लिकेशन बैकग्राउंड में चला जाता है. साथ ही, ऐप्लिकेशन के फ़ोरग्राउंड में वापस आने पर, सेशन को फिर से शुरू करने की कोशिश करता है. इसके अलावा, अगर सेशन के चालू रहने के दौरान ऐप्लिकेशन अचानक या गलत तरीके से बंद हो जाता है, तो उसे फिर से लॉन्च करने पर भी सेशन फिर से शुरू हो जाता है.
अगर कास्ट डायलॉग का इस्तेमाल किया जा रहा है, तो उपयोगकर्ता के जेस्चर के जवाब में सेशन अपने-आप बनते और बंद होते हैं. ऐसा न करने पर, ऐप्लिकेशन GCKSessionManager
पर मौजूद तरीकों का इस्तेमाल करके, सेशन को शुरू और खत्म कर सकता है.
अगर ऐप्लिकेशन को सेशन लाइफ़साइकल इवेंट के जवाब में खास प्रोसेसिंग करनी है, तो वह GCKSessionManager
के साथ एक या एक से ज़्यादा GCKSessionManagerListener
इंस्टेंस रजिस्टर कर सकता है. GCKSessionManagerListener
एक प्रोटोकॉल है, जो सेशन शुरू होने, सेशन खत्म होने वगैरह जैसे इवेंट के लिए कॉलबैक तय करता है.
संगीत को दूसरे स्पीकर पर चलाना
सेशन की स्थिति को बनाए रखना, स्ट्रीम ट्रांसफ़र करने का आधार है. इसकी मदद से, उपयोगकर्ता बोलकर दिए गए निर्देशों, Google Home ऐप्लिकेशन या स्मार्ट डिसप्ले का इस्तेमाल करके, मौजूदा ऑडियो और वीडियो स्ट्रीम को एक से दूसरे डिवाइस पर ले जा सकते हैं. मीडिया एक डिवाइस (सोर्स) पर चलना बंद हो जाता है और दूसरे डिवाइस (डेस्टिनेशन) पर चलता रहता है. नए फ़र्मवेयर वाला कोई भी Cast डिवाइस, स्ट्रीम ट्रांसफ़र में सोर्स या डेस्टिनेशन के तौर पर काम कर सकता है.
स्ट्रीम ट्रांसफ़र के दौरान नया डेस्टिनेशन डिवाइस पाने के लिए, [sessionManager:didResumeCastSession:]
कॉलबैक के दौरान GCKCastSession#device
प्रॉपर्टी का इस्तेमाल करें.
ज़्यादा जानकारी के लिए, वेब रिसीवर पर स्ट्रीम ट्रांसफ़र करना देखें.
अपने-आप फिर से कनेक्ट होना
Cast फ़्रेमवर्क में, रीकनेक्ट करने का लॉजिक जोड़ा गया है. इससे, कई मुश्किल मामलों में रीकनेक्ट करने की प्रोसेस अपने-आप मैनेज हो जाती है. जैसे:
- वाई-फ़ाई के कुछ समय के लिए बंद होने पर उसे वापस चालू करना
- डिवाइस के स्लीप मोड से वापस आना
- ऐप्लिकेशन को बैकग्राउंड में भेजने के बाद उसे वापस लाना
- ऐप्लिकेशन क्रैश होने पर उसे वापस लाना
मीडिया कंट्रोल की सुविधा कैसे काम करती है
अगर मीडिया नेमस्पेस के साथ काम करने वाले वेब रिसीवर ऐप्लिकेशन की मदद से कोई कास्ट सेशन शुरू किया जाता है, तो फ़्रेमवर्क अपने-आप GCKRemoteMediaClient
का एक इंस्टेंस बना देगा. इसे GCKCastSession
इंस्टेंस की remoteMediaClient
प्रॉपर्टी के तौर पर ऐक्सेस किया जा सकता है.
GCKRemoteMediaClient
पर वे सभी तरीके जो वेब रिसीवर को अनुरोध भेजते हैं, एक GCKRequest
ऑब्जेक्ट दिखाएंगे. इस ऑब्जेक्ट का इस्तेमाल, अनुरोध को ट्रैक करने के लिए किया जा सकता है. ऑपरेशन के नतीजे के बारे में सूचनाएं पाने के लिए, इस ऑब्जेक्ट को एक GCKRequestDelegate
असाइन किया जा सकता है.
ऐसा हो सकता है कि GCKRemoteMediaClient
का इंस्टेंस, ऐप्लिकेशन के कई हिस्सों के साथ शेयर किया जाए. असल में, फ़्रेमवर्क के कुछ इंटरनल कॉम्पोनेंट, जैसे कि कास्ट डायलॉग और मिनी मीडिया कंट्रोल, इंस्टेंस शेयर करते हैं. इसलिए, 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
प्रॉपर्टी का इस्तेमाल करें.
इस इंस्टेंस में, एचडीआर टीवी फ़ॉर्मैट का टाइप और ऊंचाई और चौड़ाई, पिक्सल में होती है. hdrType
प्रॉपर्टी में, 4K फ़ॉर्मैट के वैरिएंट की जानकारी, सूची वाली वैल्यू GCKVideoInfoHDRType
के ज़रिए दी जाती है.
मिनी कंट्रोलर जोड़ना
Cast डिज़ाइन की चेकलिस्ट के मुताबिक, भेजने वाले ऐप्लिकेशन में मिनी कंट्रोलर नाम का एक कंट्रोल होना चाहिए. यह कंट्रोल तब दिखना चाहिए, जब उपयोगकर्ता मौजूदा कॉन्टेंट पेज से किसी दूसरे पेज पर जाए. मिनी कंट्रोलर से, मौजूदा Cast सेशन को तुरंत ऐक्सेस किया जा सकता है. साथ ही, इससे आपको उस सेशन के लिए रिमाइंडर भी दिखता है.
Cast फ़्रेमवर्क में एक कंट्रोल बार,
GCKUIMiniMediaControlsViewController
होता है. इसे उन सीन में जोड़ा जा सकता है जिनमें आपको मिनी कंट्रोलर दिखाना है.
जब आपका ऐप्लिकेशन वीडियो या ऑडियो लाइव स्ट्रीम चला रहा होता है, तो एसडीके, मिनी कंट्रोलर में 'चलाएं/रोकें' बटन के बजाय, 'चलाएं/रोकें' बटन को अपने-आप दिखाता है.
iOS डिवाइस से भेजने वाले ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) पसंद के मुताबिक बनाना लेख पढ़ें. इससे आपको पता चलेगा कि भेजने वाले ऐप्लिकेशन में, 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, बड़े किए गए कंट्रोलर में चलाएं/रोकें बटन के बजाय, अपने-आप चलाएं/रोकें बटन दिखाता है.
अपने iOS ऐप्लिकेशन पर कस्टम स्टाइल लागू करना देखें. इससे आपको यह जानने में मदद मिलेगी कि भेजने वाला ऐप्लिकेशन, Cast विजेट के दिखने के तरीके को कैसे कॉन्फ़िगर कर सकता है.
आवाज़ कंट्रोल करें
Cast फ़्रेमवर्क, वीडियो भेजने वाले ऐप्लिकेशन के वॉल्यूम को अपने-आप मैनेज करता है. साथ ही, यह फ़्रेमवर्क, दिए गए यूज़र इंटरफ़ेस (यूआई) विजेट के लिए, वेब रिसीवर के वॉल्यूम के साथ अपने-आप सिंक हो जाता है. ऐप्लिकेशन से दिए गए स्लाइडर को सिंक करने के लिए, GCKUIDeviceVolumeController
का इस्तेमाल करें.
बटन की मदद से वॉल्यूम कंट्रोल करना
डिवाइस पर वॉल्यूम कम या ज़्यादा करने के बटन का इस्तेमाल करके, वेब रिसीवर पर कास्ट सेशन का वॉल्यूम बदला जा सकता है. इसके लिए, GCKCastOptions
पर मौजूद physicalVolumeButtonsWillControlDeviceVolume
फ़्लैग का इस्तेमाल करें. यह फ़्लैग, 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 सेशन को खत्म करने का फ़ैसला ले सकता है.
लॉग इन हो रहा है
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
.