광고 시점
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
를 구현합니다.
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); }
특정 채널이 연결되거나 연결 해제될 때 실행해야 하는 로직을 제공하려면 GCKCastChannel
를 사용하는 경우 -[didConnect]
및 -[didDisconnect]
메서드를 재정의하거나 GCKGenericChannel
를 사용하는 경우 GCKGenericChannelDelegate
의 -[castChannelDidConnect:]
및 -[castChannelDidDisconnect:]
메서드 구현을 제공합니다.
자동재생 지원
자동재생 및 현재 재생목록 API를 참고하세요.
이미지 선택 및 캐싱 재정의
프레임워크의 다양한 구성요소 (예: Cast 대화상자, 미니 컨트롤러, 확장 컨트롤러, 구성된 경우 GCKUIMediaController
)는 현재 전송 중인 미디어의 아트워크를 표시합니다. 이미지 아트워크의 URL은 일반적으로 미디어의 GCKMediaMetadata
에 포함되지만 발신자 앱에 URL의 대체 소스가 있을 수 있습니다.
GCKUIImagePicker
프로토콜은 특정 사용량 및 원하는 크기에 적합한 이미지를 선택하는 수단을 정의합니다. GCKUIImageHints
객체와 GCKMediaMetadata
객체를 매개변수로 사용하고 GCKImage
객체를 결과로 반환하는 단일 메서드 -[getImageWithHints:fromMetadata:]
가 있습니다. 프레임워크는 항상 GCKMediaMetadata
객체의 이미지 목록에서 첫 번째 이미지를 선택하는 GCKUIImagePicker
의 기본 구현을 제공하지만 앱은 GCKCastContext
싱글톤의 imagePicker
속성을 설정하여 대체 구현을 제공할 수 있습니다.
GCKUIImageCache
프로토콜은 프레임워크에서 HTTPS를 사용하여 다운로드한 이미지를 캐시하는 수단도 정의합니다. 프레임워크는 다운로드한 이미지 파일을 앱의 캐시 디렉터리에 저장하는 GCKUIImageCache
의 기본 구현을 제공하지만 앱은 GCKCastContext
싱글톤의 imageCache
속성을 설정하여 대체 구현을 제공할 수 있습니다.
다음 단계
iOS 송신기 앱에 추가할 수 있는 기능은 여기까지입니다. 이제 다른 플랫폼(Android 또는 웹)용 송신기 앱을 빌드하거나 웹 수신기를 빌드할 수 있습니다.