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);
}

특정 채널이 연결되거나 연결 해제될 때 실행해야 하는 로직을 제공하려면 -[didConnect]-[didDisconnect] 메서드를 재정의하거나 -[castChannelDidConnect:]-[castChannelDidDisconnect:] 메서드에 구현을 제공합니다.GCKCastChannelGCKGenericChannelDelegateGCKGenericChannel

자동 재생 지원

자동 재생 및 대기열 API를 참고하세요.

이미지 선택 및 캐싱 재정의

프레임워크의 다양한 구성요소(즉, Cast 대화상자, 미니 컨트롤러, 확장된 컨트롤러, GCKUIMediaController (구성된 경우))는 현재 전송 중인 미디어의 아트워크를 표시합니다. 이미지 아트워크의 URL은 일반적으로 미디어의 GCKMediaMetadata 에 포함되지만 발신자 앱에 URL의 대체 소스가 있을 수 있습니다.

GCKUIImagePicker 프로토콜은 특정 용도 와 원하는 크기에 적합한 이미지를 선택하는 방법을 정의합니다. -[getImageWithHints:fromMetadata:] GCKUIImageHints 객체와 GCKMediaMetadata 객체를 매개변수로 사용하고 GCKImage 객체를 결과로 반환하는 단일 메서드 가 있습니다. 프레임워크는 GCKUIImagePicker의 기본 구현을 제공하며, 이는 GCKMediaMetadata 객체의 이미지 목록에서 항상 첫 번째 이미지를 선택하지만 앱은 imagePicker 속성을 설정하여 대체 구현을 제공할 수 있습니다. GCKCastContext 싱글톤.

The GCKUIImageCache 프로토콜은 HTTPS를 사용하여 프레임워크에서 다운로드한 이미지를 캐싱하는 방법도 정의합니다. 프레임워크는 다운로드한 이미지 파일을 앱의 캐시 디렉터리에 저장하는 GCKUIImageCache의 기본 구현을 제공하지만 앱은 imageCache 속성을 설정하여 대체 구현을 제공할 수 있습니다. GCKCastContext 싱글톤.

다음 단계

이것으로 iOS Sender 앱에 추가할 수 있는 기능이 마무리되었습니다. 이제 다른 플랫폼 (Android 또는 )용 발신자 앱을 빌드하거나 웹 수신기를 빌드할 수 있습니다.