Cast को अपने iOS ऐप्लिकेशन में इंटिग्रेट करें

इस डेवलपर गाइड में बताया गया है कि iOS Sender SDK का इस्तेमाल करके, अपने iOS सेंडर ऐप्लिकेशन में Google Cast की सुविधा कैसे जोड़ी जा सकती है.

मोबाइल डिवाइस या लैपटॉप, भेजने वाला डिवाइस होता है. इससे कॉन्टेंट चलाने की सुविधा कंट्रोल की जाती है. वहीं, Google Cast डिवाइस, पाने वाला डिवाइस होता है. यह टीवी पर कॉन्टेंट दिखाता है.

सेंडर फ़्रेमवर्क का मतलब, Cast क्लास लाइब्रेरी बाइनरी और उससे जुड़ी उन संसाधनों से है जो सेंडर पर रनटाइम के दौरान मौजूद होते हैं. भेजने वाले ऐप्लिकेशन या कास्ट करने वाले ऐप्लिकेशन का मतलब, भेजने वाले व्यक्ति के डिवाइस पर चल रहे ऐप्लिकेशन से है. वेब रिसीवर ऐप्लिकेशन, वेब रिसीवर पर चलने वाले एचटीएमएल ऐप्लिकेशन को कहते हैं.

सेंडर फ़्रेमवर्क, एसिंक्रोनस कॉलबैक डिज़ाइन का इस्तेमाल करता है. इससे सेंडर ऐप्लिकेशन को इवेंट के बारे में सूचना मिलती है. साथ ही, Cast ऐप्लिकेशन की लाइफ़साइकल की अलग-अलग स्थितियों के बीच ट्रांज़िशन होता है.

ऐप्लिकेशन फ़्लो

यहां दिए गए चरणों में, iOS ऐप्लिकेशन का इस्तेमाल करने वाले किसी व्यक्ति के लिए, पुष्टि करने की प्रोसेस के बारे में बताया गया है:

  • डिवाइसों को स्कैन करना शुरू करने के लिए, Cast फ़्रेमवर्क GCKCastOptions में दी गई प्रॉपर्टी के आधार पर GCKDiscoveryManager शुरू होता है.
  • जब उपयोगकर्ता Cast बटन पर क्लिक करता है, तो फ़्रेमवर्क, Cast डिवाइसों की सूची के साथ Cast डायलॉग दिखाता है.
  • जब उपयोगकर्ता कोई कास्ट डिवाइस चुनता है, तो फ़्रेमवर्क उस कास्ट डिवाइस पर Web Receiver ऐप्लिकेशन लॉन्च करने की कोशिश करता है.
  • फ़्रेमवर्क, भेजने वाले ऐप्लिकेशन में कॉलबैक शुरू करता है. इससे यह पुष्टि की जाती है कि Web Receiver ऐप्लिकेशन लॉन्च हो गया है.
  • यह फ़्रेमवर्क, मैसेज भेजने वाले व्यक्ति और Web Receiver ऐप्लिकेशन के बीच बातचीत का चैनल बनाता है.
  • यह फ़्रेमवर्क, वेब रिसीवर पर मीडिया चलाने की सुविधा को लोड करने और कंट्रोल करने के लिए, कम्यूनिकेशन चैनल का इस्तेमाल करता है.
  • फ़्रेमवर्क, भेजने वाले डिवाइस और वेब रिसीवर के बीच मीडिया चलाने की स्थिति को सिंक करता है: जब उपयोगकर्ता, भेजने वाले डिवाइस के यूज़र इंटरफ़ेस (यूआई) पर कार्रवाई करता है, तो फ़्रेमवर्क, मीडिया कंट्रोल करने के उन अनुरोधों को वेब रिसीवर को भेजता है. साथ ही, जब वेब रिसीवर, मीडिया की स्थिति से जुड़े अपडेट भेजता है, तो फ़्रेमवर्क, भेजने वाले डिवाइस के यूज़र इंटरफ़ेस (यूआई) की स्थिति को अपडेट करता है.
  • जब उपयोगकर्ता, कास्ट डिवाइस से डिसकनेक्ट करने के लिए कास्ट बटन पर क्लिक करता है, तो फ़्रेमवर्क, सेंडर ऐप्लिकेशन को वेब रिसीवर से डिसकनेक्ट कर देगा.

ईमेल भेजने वाले व्यक्ति की समस्या हल करने के लिए, आपको लॉगिंग चालू करनी होगी.

Google Cast iOS फ़्रेमवर्क में मौजूद सभी क्लास, तरीकों, और इवेंट की पूरी सूची देखने के लिए, Google Cast iOS API का रेफ़रंस देखें. यहां दिए गए सेक्शन में, iOS ऐप्लिकेशन में Cast को इंटिग्रेट करने का तरीका बताया गया है.

मुख्य थ्रेड से तरीकों को कॉल करना

कास्ट कॉन्टेक्स्ट को शुरू करना

Cast फ़्रेमवर्क में एक ग्लोबल सिंगलटन ऑब्जेक्ट होता है, जो GCKCastContext है. यह फ़्रेमवर्क की सभी गतिविधियों को मैनेज करता है. इस ऑब्जेक्ट को ऐप्लिकेशन के लाइफ़साइकल की शुरुआत में ही शुरू करना ज़रूरी है. आम तौर पर, इसे ऐप्लिकेशन के डेलिगेट के -[application:didFinishLaunchingWithOptions:] तरीके में शुरू किया जाता है, ताकि सेंडर ऐप्लिकेशन को फिर से शुरू करने पर, सेशन अपने-आप फिर से शुरू होने की सुविधा ठीक से काम कर सके.

GCKCastContext को शुरू करते समय, GCKCastOptions ऑब्जेक्ट देना ज़रूरी है. इस क्लास में ऐसे विकल्प होते हैं जो फ़्रेमवर्क के व्यवहार पर असर डालते हैं. इनमें सबसे अहम है वेब रिसीवर ऐप्लिकेशन आईडी. इसका इस्तेमाल, डिवाइस ढूंढने के नतीजों को फ़िल्टर करने के लिए किया जाता है. साथ ही, कास्ट सेशन शुरू होने पर वेब रिसीवर ऐप्लिकेशन लॉन्च करने के लिए भी इसका इस्तेमाल किया जाता है.

-[application:didFinishLaunchingWithOptions:] तरीका, फ़्रेमवर्क से लॉगिंग मैसेज पाने के लिए, लॉगिंग डेलिगेट को सेट अप करने का भी एक अच्छा तरीका है. ये डीबग करने और समस्या हल करने में काम आ सकते हैं.

Swift
@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)
    }
  }
}
Objective-C

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 Design Checklist के मुताबिक काम करने वाले ये विजेट उपलब्ध कराता है:

  • इंट्रोडक्ट्री ओवरले: GCKCastContext क्लास में एक तरीका है, presentCastInstructionsViewControllerOnceWithCastButton, जिसका इस्तेमाल, पहली बार वेब रिसीवर उपलब्ध होने पर Cast बटन को हाइलाइट करने के लिए किया जा सकता है. भेजने वाला ऐप्लिकेशन, टाइटल टेक्स्ट और 'खारिज करें' बटन के टेक्स्ट और उनकी जगह को पसंद के मुताबिक बना सकता है.

  • कास्ट बटन: Cast iOS sender SDK 4.6.0 से, कास्ट बटन हमेशा दिखता है. ऐसा तब होता है, जब भेजने वाला डिवाइस वाई-फ़ाई से कनेक्ट होता है. जब कोई उपयोगकर्ता ऐप्लिकेशन को पहली बार शुरू करने के बाद, Cast बटन पर टैप करता है, तो अनुमतियों का डायलॉग दिखता है. इससे उपयोगकर्ता, ऐप्लिकेशन को नेटवर्क पर मौजूद डिवाइसों के लोकल नेटवर्क का ऐक्सेस दे सकता है. इसके बाद, जब उपयोगकर्ता कास्ट बटन पर टैप करता है, तो उसे कास्ट करने का डायलॉग बॉक्स दिखता है. इसमें खोजे गए डिवाइसों की सूची होती है. जब डिवाइस कनेक्ट होता है, तब उपयोगकर्ता के कास्ट बटन पर टैप करने पर, मौजूदा मीडिया का मेटाडेटा दिखता है. जैसे, टाइटल, रिकॉर्डिंग स्टूडियो का नाम, और थंबनेल इमेज. इसके अलावा, उपयोगकर्ता को कास्ट डिवाइस से डिसकनेक्ट करने का विकल्प भी मिलता है. जब उपयोगकर्ता को कोई डिवाइस उपलब्ध नहीं होता और वह कास्ट बटन पर टैप करता है, तो उसे एक स्क्रीन दिखेगी. इस स्क्रीन पर, उपयोगकर्ता को यह जानकारी मिलेगी कि डिवाइस क्यों नहीं मिल रहे हैं और समस्या को कैसे ठीक किया जाए.

  • मिनी कंट्रोलर: जब उपयोगकर्ता कॉन्टेंट कास्ट कर रहा हो और उसने मौजूदा कॉन्टेंट पेज या बड़े कंट्रोलर से हटकर, सेंडर ऐप्लिकेशन की किसी दूसरी स्क्रीन पर नेविगेट किया हो, तो स्क्रीन पर सबसे नीचे मिनी कंट्रोलर दिखता है. इससे उपयोगकर्ता को, फ़िलहाल कास्ट किए जा रहे मीडिया का मेटाडेटा देखने और प्लेबैक को कंट्रोल करने की सुविधा मिलती है.

  • बड़ा किया गया कंट्रोलर: जब उपयोगकर्ता कॉन्टेंट कास्ट कर रहा होता है, तब मीडिया सूचना या मिनी कंट्रोलर पर क्लिक करने से बड़ा किया गया कंट्रोलर लॉन्च होता है. इसमें, फ़िलहाल चल रहे मीडिया का मेटाडेटा दिखता है. साथ ही, मीडिया प्लेबैक को कंट्रोल करने के लिए कई बटन मिलते हैं.

कास्ट करने का बटन जोड़ना

फ़्रेमवर्क, Cast बटन कॉम्पोनेंट को UIButton सबक्लास के तौर पर उपलब्ध कराता है. इसे ऐप्लिकेशन के टाइटल बार में जोड़ा जा सकता है. इसके लिए, इसे UIBarButtonItem में रैप करें. कोई सामान्य UIViewController सबक्लास, Cast बटन को इस तरह इंस्टॉल कर सकती है:

Swift
let castButton = GCKUICastButton(frame: CGRect(x: 0, y: 0, width: 24, height: 24))
castButton.tintColor = UIColor.gray
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: castButton)
Objective-C
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 SDK टूल में कास्ट सेशन का कॉन्सेप्ट पेश किया गया है. इसे सेट अप करने के लिए, डिवाइस से कनेक्ट करना, Web Receiver ऐप्लिकेशन लॉन्च करना (या उसमें शामिल होना), उससे कनेक्ट करना, और मीडिया कंट्रोल चैनल को शुरू करना होता है. कास्ट सेशन और वेब रिसीवर के लाइफ़साइकल के बारे में ज़्यादा जानने के लिए, वेब रिसीवर की ऐप्लिकेशन के लाइफ़ साइकल से जुड़ी गाइड देखें.

सेशन को GCKSessionManager क्लास मैनेज करता है. यह GCKCastContext की प्रॉपर्टी है. हर सेशन को क्लास GCKSession की सबक्लास से दिखाया जाता है. उदाहरण के लिए, GCKCastSession, कास्ट डिवाइसों के साथ सेशन दिखाता है. GCKSessionManager की currentCastSession प्रॉपर्टी के तौर पर, मौजूदा समय में चालू कास्ट सेशन (अगर कोई हो) को ऐक्सेस किया जा सकता है.

GCKSessionManagerListener इंटरफ़ेस का इस्तेमाल, सेशन इवेंट को मॉनिटर करने के लिए किया जा सकता है. जैसे, सेशन बनाना, सेशन रोकना, सेशन फिर से शुरू करना, और सेशन खत्म करना. जब भेजने वाला ऐप्लिकेशन बैकग्राउंड में चला जाता है, तो फ़्रेमवर्क अपने-आप सेशन को निलंबित कर देता है. जब ऐप्लिकेशन फ़ोरग्राउंड में वापस आता है, तो फ़्रेमवर्क सेशन को फिर से शुरू करने की कोशिश करता है. ऐसा तब भी होता है, जब सेशन चालू रहने के दौरान ऐप्लिकेशन अचानक बंद हो जाता है और फिर से लॉन्च होता है.

अगर कास्ट डायलॉग का इस्तेमाल किया जा रहा है, तो उपयोगकर्ता के जेस्चर के जवाब में सेशन अपने-आप बन जाते हैं और बंद हो जाते हैं. इसके अलावा, ऐप्लिकेशन GCKSessionManager पर मौजूद तरीकों का इस्तेमाल करके, सेशन को साफ़ तौर पर शुरू और खत्म कर सकता है.

अगर ऐप्लिकेशन को सेशन के लाइफ़साइकल इवेंट के जवाब में खास प्रोसेसिंग करनी है, तो वह GCKSessionManager के साथ एक या उससे ज़्यादा GCKSessionManagerListener इंस्टेंस रजिस्टर कर सकता है. GCKSessionManagerListener एक प्रोटोकॉल है. यह सेशन शुरू होने, सेशन खत्म होने जैसे इवेंट के लिए कॉलबैक तय करता है.

स्ट्रीम ट्रांसफ़र करना

सेशन की स्थिति को बनाए रखना, स्ट्रीम ट्रांसफ़र की बुनियादी शर्त है. इसकी मदद से लोग, आवाज़ के निर्देश, Google Home ऐप्लिकेशन या स्मार्ट डिसप्ले का इस्तेमाल करके, मौजूदा ऑडियो और वीडियो स्ट्रीम को अलग-अलग डिवाइसों पर ट्रांसफ़र कर सकते हैं. मीडिया, एक डिवाइस (सोर्स) पर चलना बंद हो जाता है और दूसरे डिवाइस (डेस्टिनेशन) पर चलना जारी रहता है. कास्ट करने की सुविधा वाले किसी भी डिवाइस को, स्ट्रीम ट्रांसफ़र के दौरान सोर्स या डेस्टिनेशन के तौर पर इस्तेमाल किया जा सकता है. इसके लिए, डिवाइस में फ़र्मवेयर का नया वर्शन होना चाहिए.

स्ट्रीम ट्रांसफ़र के दौरान नए डेस्टिनेशन डिवाइस को पाने के लिए, [sessionManager:didResumeCastSession:] कॉलबैक के दौरान GCKCastSession#device प्रॉपर्टी का इस्तेमाल करें.

ज़्यादा जानकारी के लिए, वेब रिसीवर पर स्ट्रीम ट्रांसफ़र करना देखें.

अपने-आप फिर से कनेक्ट होने की सुविधा

Cast फ़्रेमवर्क, फिर से कनेक्ट करने का लॉजिक जोड़ता है. इससे, फिर से कनेक्ट करने की प्रोसेस अपने-आप मैनेज होती है. ऐसा कई मामलों में होता है. जैसे:

  • कुछ समय के लिए वाई-फ़ाई बंद होने पर, उसे फिर से चालू करने के लिए
  • डिवाइस को स्लीप मोड से वापस लाना
  • ऐप्लिकेशन को बैकग्राउंड में ले जाने के बाद वापस लाना
  • ऐप्लिकेशन क्रैश होने पर डेटा वापस पाना

मीडिया कंट्रोल की सुविधा कैसे काम करती है

अगर मीडिया नेमस्पेस के साथ काम करने वाले वेब रिसीवर ऐप्लिकेशन के साथ कास्ट सेशन शुरू किया जाता है, तो फ़्रेमवर्क GCKRemoteMediaClient का एक इंस्टेंस अपने-आप बना देगा. इसे GCKCastSession इंस्टेंस की remoteMediaClient प्रॉपर्टी के तौर पर ऐक्सेस किया जा सकता है.

GCKRemoteMediaClient पर मौजूद सभी तरीके, Web Receiver को अनुरोध भेजते हैं. ये तरीके, GCKRequest ऑब्जेक्ट दिखाते हैं. इस ऑब्जेक्ट का इस्तेमाल, अनुरोध को ट्रैक करने के लिए किया जा सकता है. इस ऑब्जेक्ट को कोई GCKRequestDelegate असाइन किया जा सकता है, ताकि ऑपरेशन के आखिर में मिलने वाले नतीजे के बारे में सूचनाएं मिल सकें.

ऐसा माना जाता है कि GCKRemoteMediaClient का इंस्टेंस, ऐप्लिकेशन के कई हिस्सों के साथ शेयर किया जा सकता है. साथ ही, फ़्रेमवर्क के कुछ इंटरनल कॉम्पोनेंट, जैसे कि कास्ट डायलॉग और मिनी मीडिया कंट्रोल भी इंस्टेंस को शेयर करते हैं. इसलिए, GCKRemoteMediaClient एक से ज़्यादा GCKRemoteMediaClientListener रजिस्टर करने की सुविधा देता है.

मीडिया का मेटाडेटा सेट करना

GCKMediaMetadata क्लास, उस मीडिया आइटम के बारे में जानकारी देती है जिसे आपको कास्ट करना है. इस उदाहरण में, किसी फ़िल्म का नया GCKMediaMetadata इंस्टेंस बनाया गया है. साथ ही, इसमें टाइटल, सबटाइटल, रिकॉर्डिंग स्टूडियो का नाम, और दो इमेज सेट की गई हैं.

Swift
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))
Objective-C
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 का इस्तेमाल किया जा सकता है. जैसे, चलाने, रोकने, और बंद करने के लिए.

Swift
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
}
Objective-C
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 वीडियो फ़ॉर्मैट

यह पता लगाने के लिए कि आपका मीडिया किस वीडियो फ़ॉर्मैट में है, GCKMediaStatus की videoInfo प्रॉपर्टी का इस्तेमाल करें. इससे आपको GCKVideoInfo का मौजूदा इंस्टेंस मिलेगा. इस इंस्टेंस में, एचडीआर टीवी फ़ॉर्मैट का टाइप और पिक्सल में ऊंचाई और चौड़ाई शामिल होती है. 4K फ़ॉर्मैट के वैरिएंट, hdrType प्रॉपर्टी में enum वैल्यू GCKVideoInfoHDRType के ज़रिए दिखाए जाते हैं.

मिनी कंट्रोलर जोड़ना

कास्ट डिज़ाइन चेकलिस्ट के मुताबिक, सेंडर ऐप्लिकेशन को एक ऐसा कंट्रोल उपलब्ध कराना चाहिए जो हमेशा दिखता रहे. इसे मिनी कंट्रोलर कहा जाता है. यह तब दिखना चाहिए, जब उपयोगकर्ता मौजूदा कॉन्टेंट पेज से हट जाए. मिनी कंट्रोलर से, कास्ट किए जा रहे मौजूदा सेशन को तुरंत ऐक्सेस किया जा सकता है. साथ ही, इससे आपको कास्ट किए जा रहे सेशन के बारे में सूचना भी मिलती है.

Cast फ़्रेमवर्क, कंट्रोल बार GCKUIMiniMediaControlsViewController उपलब्ध कराता है. इसे उन सीन में जोड़ा जा सकता है जिनमें आपको मिनी कंट्रोलर दिखाना है.

जब आपका सेंडर ऐप्लिकेशन, वीडियो या ऑडियो की लाइव स्ट्रीम चला रहा होता है, तो एसडीके, मिनी कंट्रोलर में मौजूद 'चलाएं/रोकें' बटन की जगह, 'चलाएं/बंद करें' बटन अपने-आप दिखाता है.

iOS Sender UI को पसंद के मुताबिक बनाएं लेख पढ़ें. इसमें बताया गया है कि आपका सेंडर ऐप्लिकेशन, Cast विजेट के दिखने के तरीके को कैसे कॉन्फ़िगर कर सकता है.

सेंडर ऐप्लिकेशन में मिनी कंट्रोलर जोड़ने के दो तरीके हैं:

  • कास्ट फ़्रेमवर्क को मिनी कंट्रोलर के लेआउट को मैनेज करने दें. इसके लिए, अपने मौजूदा व्यू कंट्रोलर को कास्ट फ़्रेमवर्क के व्यू कंट्रोलर के साथ रैप करें.
  • मिनी कंट्रोलर विजेट के लेआउट को खुद मैनेज करें. इसके लिए, इसे अपने मौजूदा व्यू कंट्रोलर में जोड़ें. इसके लिए, स्टोरीबोर्ड में एक सबव्यू दें.

GCKUICastContainerViewController का इस्तेमाल करके रैप करना

पहला तरीका यह है कि GCKUICastContainerViewController का इस्तेमाल किया जाए. यह किसी दूसरे व्यू कंट्रोलर को रैप करता है और सबसे नीचे GCKUIMiniMediaControlsViewController जोड़ता है. इस तरीके में कुछ सीमाएं हैं. जैसे, इसमें ऐनिमेशन को पसंद के मुताबिक नहीं बनाया जा सकता. साथ ही, कंटेनर व्यू कंट्रोलर के व्यवहार को कॉन्फ़िगर नहीं किया जा सकता.

आम तौर पर, इस पहले तरीके का इस्तेमाल ऐप्लिकेशन डेलिगेट के -[application:didFinishLaunchingWithOptions:] तरीके में किया जाता है:

Swift
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()

  ...
}
Objective-C
- (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];
  ...

}
Swift
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
    }
  }
}
Objective-C

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 इंस्टेंस बनाएं. इसके बाद, इसे कंटेनर व्यू कंट्रोलर में सबव्यू के तौर पर जोड़ें.

ऐप्लिकेशन डेलिगेट में अपना व्यू कंट्रोलर सेट अप करें:

Swift
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
}
Objective-C
- (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 का एक इंस्टेंस बनाएं और उसे कंटेनर व्यू कंट्रोलर में सबव्यू के तौर पर जोड़ें:

Swift
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)
    }
  }

...
Objective-C

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, होस्ट व्यू कंट्रोलर को यह बताता है कि मिनी कंट्रोलर कब दिखना चाहिए:

Swift
  func miniMediaControlsViewController(_: GCKUIMiniMediaControlsViewController,
                                       shouldAppear _: Bool) {
    updateControlBarsVisibility()
  }
Objective-C
- (void)miniMediaControlsViewController:
            (GCKUIMiniMediaControlsViewController *)miniMediaControlsViewController
                           shouldAppear:(BOOL)shouldAppear {
  [self updateControlBarsVisibility];
}

बड़ा किया गया कंट्रोलर जोड़ना

Google Cast की डिज़ाइन चेकलिस्ट के मुताबिक, सेंडर ऐप्लिकेशन को कास्ट किए जा रहे मीडिया के लिए, बड़ा किया गया कंट्रोलर उपलब्ध कराना होता है. बड़ा किया गया कंट्रोलर, मिनी कंट्रोलर का फ़ुल स्क्रीन वर्शन होता है.

बड़ा किया गया कंट्रोलर, फ़ुल स्क्रीन व्यू होता है. इससे रिमोट मीडिया प्लेबैक को पूरी तरह से कंट्रोल किया जा सकता है. इस व्यू की मदद से, कास्टिंग ऐप्लिकेशन को कास्ट सेशन के हर पहलू को मैनेज करने की अनुमति मिलनी चाहिए. हालांकि, वेब रिसीवर के वॉल्यूम कंट्रोल और सेशन के लाइफ़साइकल (कास्ट करना/कास्ट करना बंद करना) को मैनेज करने की अनुमति नहीं मिलनी चाहिए. यह मीडिया सेशन के बारे में स्थिति की पूरी जानकारी भी देता है. जैसे, आर्टवर्क, टाइटल, सबटाइटल वगैरह.

इस व्यू की सुविधा, GCKUIExpandedMediaControlsViewController क्लास से लागू की जाती है.

सबसे पहले, आपको कास्ट कॉन्टेक्स्ट में डिफ़ॉल्ट तौर पर बड़ा किया गया कंट्रोलर चालू करना होगा. डिफ़ॉल्ट तौर पर बड़ा किया गया कंट्रोलर चालू करने के लिए, ऐप्लिकेशन डेलिगेट में बदलाव करें:

Swift
func applicationDidFinishLaunching(_ application: UIApplication) {
  ..

  GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true

  ...
}
Objective-C
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  ...

  [GCKCastContext sharedInstance].useDefaultExpandedMediaControls = YES;

  ..
}

जब उपयोगकर्ता वीडियो कास्ट करना शुरू करे, तब बड़े किए गए कंट्रोलर को लोड करने के लिए, अपने व्यू कंट्रोलर में यह कोड जोड़ें:

Swift
func playSelectedItemRemotely() {
  GCKCastContext.sharedInstance().presentDefaultExpandedMediaControls()

  ...

  // Load your media
  sessionManager.currentSession?.remoteMediaClient?.loadMedia(mediaInformation)
}
Objective-C
- (void)playSelectedItemRemotely {
  [[GCKCastContext sharedInstance] presentDefaultExpandedMediaControls];

  ...

  // Load your media
  [self.sessionManager.currentSession.remoteMediaClient loadMedia:mediaInformation];
}

जब उपयोगकर्ता मिनी कंट्रोलर पर टैप करेगा, तब बड़ा किया गया कंट्रोलर भी अपने-आप लॉन्च हो जाएगा.

जब आपका सेंडर ऐप्लिकेशन, वीडियो या ऑडियो लाइव स्ट्रीम चला रहा होता है, तो SDK टूल, बड़े किए गए कंट्रोलर में 'चलाएं/रोकें' बटन की जगह 'चलाएं/बंद करें' बटन अपने-आप दिखाता है.

कास्ट विजेट का लुक कॉन्फ़िगर करने के तरीके के बारे में जानने के लिए, अपने iOS ऐप्लिकेशन पर कस्टम स्टाइल लागू करना लेख पढ़ें.

आवाज़ कंट्रोल करें

कास्ट फ़्रेमवर्क, भेजने वाले ऐप्लिकेशन के लिए वॉल्यूम को अपने-आप मैनेज करता है. यह फ़्रेमवर्क, दिए गए यूज़र इंटरफ़ेस (यूआई) विजेट के लिए, वेब रिसीवर के वॉल्यूम के साथ अपने-आप सिंक हो जाता है. ऐप्लिकेशन से मिले स्लाइडर को सिंक करने के लिए, GCKUIDeviceVolumeController का इस्तेमाल करें.

बटन से वॉल्यूम कंट्रोल करने की सुविधा

भेजने वाले डिवाइस पर मौजूद वॉल्यूम के बटन का इस्तेमाल करके, वेब रिसीवर पर कास्ट किए जा रहे सेशन का वॉल्यूम बदला जा सकता है. इसके लिए, GCKCastOptions पर मौजूद physicalVolumeButtonsWillControlDeviceVolume फ़्लैग का इस्तेमाल किया जाता है. यह फ़्लैग, GCKCastContext पर सेट होता है.

Swift
let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID)
let options = GCKCastOptions(discoveryCriteria: criteria)
options.physicalVolumeButtonsWillControlDeviceVolume = true
GCKCastContext.setSharedInstanceWith(options)
Objective-C
GCKDiscoveryCriteria *criteria = [[GCKDiscoveryCriteria alloc]
                                          initWithApplicationID:kReceiverAppID];
GCKCastOptions *options = [[GCKCastOptions alloc]
                                          initWithDiscoveryCriteria :criteria];
options.physicalVolumeButtonsWillControlDeviceVolume = YES;
[GCKCastContext setSharedInstanceWithOptions:options];

गड़बड़ियां ठीक करना

भेजने वाले ऐप्लिकेशन के लिए, गड़बड़ी से जुड़े सभी कॉलबैक को मैनेज करना और Cast की लाइफ़साइकल के हर चरण के लिए सबसे सही जवाब तय करना बहुत ज़रूरी है. ऐप्लिकेशन, उपयोगकर्ता को गड़बड़ी के डायलॉग बॉक्स दिखा सकता है या कास्ट सेशन को खत्म कर सकता है.

लॉग इन हो रहा है

GCKLogger एक सिंगलटन है. इसका इस्तेमाल फ़्रेमवर्क, लॉगिंग के लिए करता है. लॉग मैसेज को मैनेज करने के तरीके को पसंद के मुताबिक बनाने के लिए, GCKLoggerDelegate का इस्तेमाल करें.

GCKLogger का इस्तेमाल करके, SDK टूल लॉगिंग आउटपुट जनरेट करता है. यह आउटपुट, डीबग मैसेज, गड़बड़ियों, और चेतावनियों के तौर पर होता है. ये लॉग मैसेज, डीबग करने में मदद करते हैं. साथ ही, समस्याओं का पता लगाने और उन्हें हल करने में भी मददगार होते हैं. डिफ़ॉल्ट रूप से, लॉग आउटपुट को छिपा दिया जाता है. हालांकि, GCKLoggerDelegate असाइन करके, भेजने वाला ऐप्लिकेशन SDK टूल से ये मैसेज पा सकता है और उन्हें सिस्टम कंसोल में लॉग कर सकता है.

Swift
@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)
    }
  }
}
Objective-C

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

डिफ़ॉल्ट और वर्बोस मैसेज भी चालू करने के लिए, डेलिगेट सेट करने के बाद (जैसा कि पहले दिखाया गया है) कोड में यह लाइन जोड़ें:

Swift
let filter = GCKLoggerFilter.init()
filter.minimumLevel = GCKLoggerLevel.verbose
GCKLogger.sharedInstance().filter = filter
Objective-C
GCKLoggerFilter *filter = [[GCKLoggerFilter alloc] init];
[filter setMinimumLevel:GCKLoggerLevelVerbose];
[GCKLogger sharedInstance].filter = filter;

GCKLogger से जनरेट हुए लॉग मैसेज को भी फ़िल्टर किया जा सकता है. हर क्लास के लिए, लॉगिंग का कम से कम लेवल सेट करें. उदाहरण के लिए:

Swift
let filter = GCKLoggerFilter.init()
filter.setLoggingLevel(GCKLoggerLevel.verbose, forClasses: ["GCKUICastButton",
                                                            "GCKUIImageCache",
                                                            "NSMutableDictionary"])
GCKLogger.sharedInstance().filter = filter
Objective-C
GCKLoggerFilter *filter = [[GCKLoggerFilter alloc] init];
[filter setLoggingLevel:GCKLoggerLevelVerbose
             forClasses:@[@"GCKUICastButton",
                          @"GCKUIImageCache",
                          @"NSMutableDictionary"
                          ]];
[GCKLogger sharedInstance].filter = filter;

क्लास के नाम, लिटरल नाम या ग्लोब पैटर्न हो सकते हैं. उदाहरण के लिए, GCKUI\* और GCK\*Session.