הפסקות למודעות
ה-SDK של iOS Sender תומך בהפסקות למודעות ובמודעות נלוות זרם מדיה נתון.
לצפייה סקירה כללית של הפסקות למודעות אצל מקלטי אינטרנט מידע על אופן הפעולה של הפסקות למודעות.
אפשר לציין הפסקות גם אצל השולח וגם אצל המקבל, אבל מומלץ שהן יופיעו שצוינו ב-WebReceiver וגם המקלט של Android TV לשמירה על עקביות התנהגות המשתמשים בפלטפורמות שונות.
ב-iOS, מציינים הפסקות למודעות בפקודת טעינה באמצעות
GCKAdBreakClipInfo
וגם GCKAdBreakInfo
:
let breakClip1Builder = GCKAdBreakClipInfoBuilder(adBreakClipID: "bc0") breakClip1Builder.title = "Clip title" if let posterUrl = URL(string: "https://www.some.url") { breakClip1Builder.posterURL = posterUrl } breakClip1Builder.duration = 60 breakClip1Builder.whenSkippable = 5 // Set this field so that the ad is skippable let breakClip1 = breakClip1Builder.build() let breakClip2 = ... let breakClip3 = ... let break1 = GCKAdBreakInfoBuilder(adBreakID: "b0", adBreakClipIds: ["bc0", "bc1", "bc2"]).build() let mediaInfoBuilder = GCKMediaInformationBuilder(entity: "entity") ... mediaInfoBuilder.adBreaks = [break1] mediaInfoBuilder.adBreakClips = [breakClip1, breakClip2, breakClip3] ... mediaInformation = mediaInfoBuilder.build() let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder() mediaLoadRequestDataBuilder.mediaInformation = mediaInformation sessionManager.currentSession?.remoteMediaClient?.loadMedia(with: mediaLoadRequestDataBuilder.build())
GCKAdBreakClipInfoBuilder *breakClipInfoBuilder = [[GCKAdBreakClipInfoBuilder alloc] initWithAdBreakClipID:@"bc0"]; breakClipInfoBuilder.title = @"Clip title"; breakClipInfoBuilder.posterURL = [[NSURL alloc] initWithString:@"https://www.some.url"]; breakClipInfoBuilder.duration = 60; breakClipInfoBuilder.whenSkippable = 5; GCKAdBreakClipInfo *breakClip1 = breakClipInfoBuilder.build; GCKAdBreakClipInfo *breakClip2 = ... GCKAdBreakClipInfo *breakClip3 = ... GCKAdBreakInfo *break1 = [[GCKAdBreakInfoBuilder alloc] initWithAdBreakID:@"b0" adBreakClipIds:@[@"bc0", @"bc1", @"bc2"]].build; GCKMediaInformationBuilder *mediaInfoBuilder = [[GCKMediaInformationBuilder alloc] initWithEntity:@"entity"]; ... mediaInfoBuilder.adBreaks = @[break1]; mediaInfoBuilder.adBreakClips = @[breakClip1, breakClip2, breakClip3]; ... self.mediaInformation = [mediaInfoBuilder build]; GCKMediaLoadRequestDataBuilder *mediaLoadRequestDataBuilder = [[GCKMediaLoadRequestDataBuilder alloc] init]; mediaLoadRequestDataBuilder.mediaInformation = self.mediaInformation; // Send a load request to the remote media client. GCKRequest *request = [self.sessionManager.currentSession.remoteMediaClient loadMediaWithLoadRequestData:[mediaLoadRequestDataBuilder build]];
קצב הפעלה משתנה
האפליקציה יכולה להציג ולשנות את קצב ההפעלה של פריט המדיה הנוכחי.
אפשר להגדיר את התעריף באמצעות -[setPlaybackRate:]
או
-[setPlaybackRate:customData:]
מתוך
GCKRemoteMediaClient
,
לגשת אל GCKUIPlaybackRateController
באמצעות playbackRateController
GCKUIMediaController
,
ולהציג את קצב ההפעלה הנוכחי באמצעות playbackRate
GCKUIPlaybackRateController
.
קוד לדוגמה
שני הקבצים הבאים מטמיעים את GCKUIPlaybackRateController
,
קצב ההפעלה באמצעות פקד מקטעים בעל 'רגיל', 'חצי מהירות', וגם
"מהירות כפולה" לחצנים:
import GoogleCast /** * An implementation of GCKUIPlaybackRateController that controls playback rate * using a segmented control that has "normal", "half speed", and "double speed" * buttons. */ class SegmentedButtonPlaybackRateController: GCKUIPlaybackRateController { static let kSegmentNormal = 0; static let kSegmentHalfSpeed = 1; static let kSegmentDoubleSpeed = 2; var segmentedControl: UISegmentedControl! override var playbackRate: Float { didSet { var buttonIndex = 0 // Map the playback rate to one of our three supported speeds. if playbackRate == 1.0 { buttonIndex = SegmentedButtonPlaybackRateController.kSegmentNormal } else if playbackRate < 1.0 { buttonIndex = SegmentedButtonPlaybackRateController.kSegmentHalfSpeed } else { buttonIndex = SegmentedButtonPlaybackRateController.kSegmentDoubleSpeed } segmentedControl?.selectedSegmentIndex = buttonIndex } } override var inputEnabled: Bool { didSet { segmentedControl?.isEnabled = inputEnabled } } /** * Designated initializer. * * @param segmentedControl The segmented control for changing/displaying the * playback rate. */ convenience init(_ segmentedControl: UISegmentedControl) { self.init() self.segmentedControl = segmentedControl; segmentedControl.addTarget(self, action: #selector(segmentedControlTapped(sender:)), for: UIControl.Event.valueChanged) } @objc func segmentedControlTapped(sender: UISegmentedControl) { var playbackRate: Float = 1.0 switch segmentedControl?.selectedSegmentIndex { case SegmentedButtonPlaybackRateController.kSegmentHalfSpeed: playbackRate = 0.5; case SegmentedButtonPlaybackRateController.kSegmentDoubleSpeed: playbackRate = 2.0; case SegmentedButtonPlaybackRateController.kSegmentNormal: fallthrough default: playbackRate = 1.0; } self.playbackRate = playbackRate } }
SegmentedButtonPlaybackRateController.h
#import <GoogleCast/GoogleCast.h> #import <UIKit/UIKit.h> /** * An implementation of GCKUIPlaybackRateController that controls playback rate * using a segmented control that has "normal", "half speed", and "double speed" * buttons. */ @interface SegmentedButtonPlaybackRateController : GCKUIPlaybackRateController /** * Designated initializer. * * @param segmentedControl The segmented control for changing/displaying the * playback rate. */ - (instancetype)initWithSegmentedControl:(UISegmentedControl *)segmentedControl; @end
SegmentedButtonPlaybackRateController.m
#import "SegmentedButtonPlaybackRateController.h" @interface SegmentedButtonPlaybackRateController () { UISegmentedControl *_segmentedControl; } @end static const NSInteger kSegmentNormal = 0; static const NSInteger kSegmentHalfSpeed = 1; static const NSInteger kSegmentDoubleSpeed = 2; @implementation SegmentedButtonPlaybackRateController - (instancetype)initWithSegmentedControl:(UISegmentedControl *)segmentedControl { if (self = [super init]) { _segmentedControl = segmentedControl; [_segmentedControl addTarget:self action:@selector(segmentedControlTapped:) forControlEvents:UIControlEventValueChanged]; } return self; } - (void)setPlaybackRate:(float)playbackRate { [super setPlaybackRate:playbackRate]; NSInteger buttonIndex = 0; // Map the playback rate to one of our three supported speeds. if (playbackRate == 1.0) { buttonIndex = kSegmentNormal; } else if (playbackRate < 1.0) { buttonIndex = kSegmentHalfSpeed; } else { buttonIndex = kSegmentDoubleSpeed; } _segmentedControl.selectedSegmentIndex = buttonIndex; } - (void)setInputEnabled:(BOOL)inputEnabled { _segmentedControl.enabled = inputEnabled; [super setInputEnabled:inputEnabled]; } - (void)segmentedControlTapped:(id)sender { float playbackRate; switch (_segmentedControl.selectedSegmentIndex) { case kSegmentHalfSpeed: playbackRate = 0.5; break; case kSegmentDoubleSpeed: playbackRate = 2.0; break; case kSegmentNormal: default: playbackRate = 1.0; break; } self.playbackRate = playbackRate; } @end
הוספת ערוץ מותאם אישית
מסגרת ההעברה (cast) מספקת שתי דרכים ליצור ערוץ לשליחת הודעות מותאמות אישית למקלט אינטרנט:
GCKCastChannel
מיועד לסיווג משנה כדי להטמיע ערוצים לא טריים את המצב הקיים.GCKGenericChannel
מסופק כחלופה לסיווג משנה; הוא עובר הודעות למקבל הגישה כדי שיהיה אפשר לעבד אותן במקום אחר.
דוגמה להטמעה של GCKCastChannel
:
class HGCTextChannel: GCKCastChannel { override func didReceiveTextMessage(_ message: String) { print("received message: \(message)") } }
HGCTextChannel.h
#import <GoogleCast/GCKCastChannel.h> @interface HGCTextChannel : GCKCastChannel @end
HGCTextChannel.m
#import "HGCTextChannel.h" @implementation HGCTextChannel - (void)didReceiveTextMessage:(NSString*)message { NSLog(@"received message: %@", message); } @end
אפשר לרשום ערוץ בכל שלב. אם הסשן לא נמצא כרגע במצב מחובר, הערוץ יחובר באופן אוטומטי כאשר הסשן עצמו מחובר, כל עוד מרחב השמות של הערוץ רשימת מרחבי השמות הנתמכים של המטא-נתונים של האפליקציה של מקלט האינטרנט.
כל ערוץ מותאם אישית מוגדר לפי מרחב שמות ייחודי והוא חייב להתחיל
תחילית urn:x-cast:
, לדוגמה urn:x-cast:com.example.custom
. זה כן
אם יש מספר ערוצים מותאמים אישית, שלכל אחד מהם יש מרחב שמות ייחודי.
האפליקציה 'מקלט אינטרנט' יכולה גם לשלוח ולקבל
הודעות
באמצעות אותו מרחב שמות.
var error: GCKError? let textChannel = HGCTextChannel.init(namespace: "urn:x-cast:com.google.cast.sample.helloworld") sessionManager.currentCastSession?.add(textChannel) textChannel.sendTextMessage("Hello World", error: &error) if error != nil { print("Error sending text message \(error.debugDescription)") }
NSError *error; HGCTextChannel *textChannel = [[HGCTextChannel alloc] initWithNamespace:@"urn:x-cast:com.google.cast.sample.helloworld"]; [sessionManager.currentCastSession addChannel:textChannel]; [textChannel sendTextMessage:@"Hello World" error:&error]; if (error != nil) { NSLog(@"Error sending text message: %@", error); }
כדי לספק לוגיקה שצריך לפעול כשערוץ מסוים הופך
מחובר או מנותק, מבטלים את -[didConnect]
ואת -[didDisconnect]
שיטות אם משתמשים
GCKCastChannel
, או
לספק יישומים של -[castChannelDidConnect:]
-[castChannelDidDisconnect:]
של ה-methods
GCKGenericChannelDelegate
אם משתמשים ב-GCKGenericChannel
.
תמיכה בהפעלה אוטומטית
לעיון בקטע הפעלה אוטומטית ו ממשקי API לרשימת תורים.
ביטול בחירה של תמונות ושמירה במטמון
רכיבים שונים במסגרת (למשל תיבת הדו-שיח של הפעלת Cast,
לבקרה המורחבת
GCKUIMediaController
אם הוא מוגדר) יציג גרפיקה עבור המדיה שמופעלת כרגע בהעברה. כתובות ה-URL
לגרפיקה של התמונה. בדרך כלל נכללות
GCKMediaMetadata
למדיה, אבל יכול להיות שלאפליקציית השולח יש מקור חלופי לכתובות ה-URL.
GCKUIImagePicker
מגדיר אמצעי לבחירת תמונה מתאימה לשימוש מסוים.
ובגודל הרצוי. יש לו method יחידה, -[getImageWithHints:fromMetadata:]
,
שלוקחת
GCKUIImageHints
אובייקט,
GCKMediaMetadata
כפרמטרים, ומחזירה את הפונקציה
GCKImage
אובייקט
תוצאה אחת. ה-framework מספק הטמעת ברירת מחדל של
GCKUIImagePicker
שבוחר תמיד את התמונה הראשונה ברשימת התמונות
את האובייקט GCKMediaMetadata
, אבל האפליקציה יכולה לספק חלופה
על ידי הגדרת המאפיין imagePicker
של
GCKCastContext
סינגלטון.
GCKUIImageCache
מגדיר גם אמצעי לשמירה במטמון של תמונות שמורידים
באמצעות HTTPS. ה-framework מספק הטמעת ברירת מחדל של
GCKUIImageCache
שבו קובצי תמונה שהורדו נשמרים במטמון של האפליקציה
אבל האפליקציה יכולה לספק הטמעה חלופית על ידי הגדרה של
imageCache
של המאפיין
GCKCastContext
סינגלטון.
השלבים הבאים
הגענו למסקנה שאפשר להוסיף לאפליקציית השולח ב-iOS. עכשיו אפשר לפתח אפליקציית שולח לפלטפורמה אחרת (Android או אינטרנט), או ליצור WebReceiver.