广告插播时间点
iOS 发送端 SDK 支持在给定的媒体流中插入广告插播时间点和随播广告。
如需详细了解广告插播时间点的工作原理,请参阅 Web 接收器广告插播时间点概览。
虽然可以在发送端和接收端指定插播时间点,但建议在 Web 接收器和 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,使用 playbackRateController 访问 GCKUIPlaybackRateController
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 框架提供了两种创建渠道以向 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 接收器应用元数据的受支持命名空间列表中。
每个自定义渠道都由唯一的命名空间定义,并且必须以
前缀 urn:x-cast: 开头,例如 urn:x-cast:com.example.custom。可以有多个自定义渠道,每个渠道都有唯一的命名空间。Web 接收器应用还可以
使用相同的命名空间发送和接收
消息
。
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。
替换图片选择和缓存
框架的各种组件(即 Cast 对话框、迷你
控制器、展开的控制器和
GCKUIMediaController
,如果已配置)将显示当前投放媒体的艺术作品。图片艺术作品的网址
通常包含在媒体的
GCKMediaMetadata
中,但发送端应用可能有其他网址来源。
The
GCKUIImagePicker
协议定义了一种为给定用途
和所需尺寸选择合适图片的方法。它有一个方法 -[getImageWithHints:fromMetadata:],
该方法接受一个
GCKUIImageHints
对象和一个
GCKMediaMetadata
对象作为参数,并返回一个
GCKImage 对象作为
结果。该框架提供了
GCKUIImagePicker 的默认实现,该实现始终选择
GCKMediaMetadata 对象中的图片列表中的第一张图片,但应用可以通过设置imagePicker 属性来提供替代
实现
GCKCastContext
单例。
The
GCKUIImageCache
协议还定义了一种缓存
框架使用 HTTPS 下载的图片的方法。该框架提供了
GCKUIImageCache的默认实现,该实现将下载的图片文件存储在应用的缓存
目录中,但应用可以通过设置
imageCache属性来提供
GCKCastContext
单例的替代实现。
后续步骤
至此,您已了解可以添加到 iOS 发送端应用的功能。 现在,您可以为其他平台 (Android 或 Web)构建发送端应用, 也可以构建 Web 接收器。