iOS 앱에 고급 기능 추가

광고 시점

iOS Sender SDK는 지정된 미디어 스트림 내에서 광고 시점 및 컴패니언 광고를 지원합니다.

광고 시점의 작동 방식에 관한 자세한 내용은 웹 수신기 광고 시점 개요를 참고하세요.

휴식 시간은 발신기와 수신기 모두에서 지정할 수 있지만, 플랫폼 전반에서 일관된 동작을 유지하려면 웹 수신기Android TV 수신기에서 지정하는 것이 좋습니다.

iOS에서는 GCKAdBreakClipInfoGCKAdBreakInfo를 사용하여 로드 명령어에서 광고 시점을 지정합니다.

Swift
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())
Objective-C
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:]를 사용하여 속도를 설정하고, GCKUIMediaControllerplaybackRateController를 사용하여 GCKUIPlaybackRateController에 액세스하고, GCKUIPlaybackRateControllerplaybackRate를 사용하여 현재 재생 속도를 표시할 수 있습니다.

샘플 코드

다음 두 파일은 '일반', '절반 속도', '두 배 속도' 버튼이 있는 세그먼트 컨트롤을 사용하여 재생 속도를 제어하는 GCKUIPlaybackRateController를 구현합니다.

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

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 프레임워크는 웹 수신기에 맞춤 메시지를 전송하는 채널을 만드는 두 가지 방법을 제공합니다.

  1. GCKCastChannel는 연결된 상태가 있는 간단하지 않은 채널을 구현하기 위해 서브클래스화할 수 있습니다.
  2. GCKGenericChannel는 서브클래싱의 대안으로 제공됩니다. 수신된 메시지를 다른 곳에서 처리할 수 있도록 대리인에게 전달합니다.

다음은 GCKCastChannel 구현의 예입니다.

Swift
class HGCTextChannel: GCKCastChannel {
  override func didReceiveTextMessage(_ message: String) {
    print("received message: \(message)")
  }
}
Objective-C

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). 각각 고유한 네임스페이스가 있는 맞춤 채널을 여러 개 보유할 수 있습니다. 웹 수신기 앱은 동일한 네임스페이스를 사용하여 메시지를 주고받을 수도 있습니다.

Swift
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)")
}
Objective-C
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 또는 )용 송신기 앱을 빌드하거나 웹 수신기를 빌드할 수 있습니다.