廣告插播
iOS Sender SDK 支援指定媒體串流中的廣告插播和隨播廣告。
如要進一步瞭解廣告插播的運作方式,請參閱「網路接收器廣告插播總覽」。
雖然您可以在傳送端和接收端上指定插播,但建議您在網頁接收端和 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]];
可變播放速率
應用程式可以顯示及變更目前媒體項目的播放速率。您可以使用 GCKRemoteMediaClient
的 -[setPlaybackRate:]
或 -[setPlaybackRate:customData:]
設定播放速率,使用 GCKUIMediaController
的 playbackRateController
存取 GCKUIPlaybackRateController
,並使用 GCKUIPlaybackRateController
的 playbackRate
顯示目前的播放速率。
程式碼範例
以下兩個檔案會實作 GCKUIPlaybackRateController
,該檔案會使用具有「normal」、「half speed」和「double speed」按鈕的分段控制項控制播放速度:
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 架構提供兩種建立管道的方法,以便將自訂訊息傳送至 Web 接收器:
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
您可以隨時註冊管道;如果目前的會話狀態並未處於已連線狀態,只要管道名稱空間位於 Web Receiver 應用程式中支援的名稱空間清單中,管道就會在會話本身連線時自動連線。
每個自訂管道都由專屬命名空間定義,且必須以前置字元 urn:x-cast:
開頭,例如 urn:x-cast:com.example.custom
。您可以建立多個自訂管道,每個管道都有專屬的命名空間。Web Receiver 應用程式也可以使用相同的命名空間傳送及接收訊息。
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); }
如要提供在特定管道連線或中斷連線時需要執行的邏輯,請在使用 GCKCastChannel
時覆寫 -[didConnect]
和 -[didDisconnect]
方法,或是在使用 GCKGenericChannel
時為 GCKGenericChannelDelegate
的 -[castChannelDidConnect:]
和 -[castChannelDidDisconnect:]
方法提供實作項目。
支援自動播放
請參閱「自動播放與排隊 API」。
覆寫圖片選取和快取
架構的各種元件 (即投放對話方塊、迷你控制器、展開式控制器,以及已設定的 GCKUIMediaController
) 會顯示目前投放媒體的圖片。圖片圖片的網址通常會包含在媒體的 GCKMediaMetadata
中,但傳送端應用程式可能會提供網址的替代來源。
GCKUIImagePicker
通訊協定定義了一種方法,可根據特定用途和所需大小選取適當的圖片。它只有一個 -[getImageWithHints:fromMetadata:]
方法,會將 GCKUIImageHints
物件和 GCKMediaMetadata
物件做為參數,並傳回 GCKImage
物件做為結果。此架構會提供 GCKUIImagePicker
的預設實作方式,該方式一律會選取 GCKMediaMetadata
物件圖片清單中的第一張圖片,但應用程式可以透過設定 GCKCastContext
單例的 imagePicker
屬性,提供其他實作方式。
GCKUIImageCache
通訊協定也定義了一種快取圖片的方式,這些圖片是由架構使用 HTTPS 下載。此架構會提供 GCKUIImageCache
的預設實作方式,將下載的圖片檔案儲存在應用程式的快取目錄中,但應用程式可以設定 GCKCastContext
單例的 imageCache
屬性,以提供其他實作方式。
後續步驟
這就是您可以新增至 iOS 傳送端應用程式的所有功能。現在,您可以為其他平台 (Android 或 網頁) 建構傳送端應用程式,或是建構網頁接收端。