為您的 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。有可能有多個自訂管道,而每個管道的命名空間都不重複。Web Receiver 應用程式也可以使用相同的命名空間收發訊息

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] 方法,或針對 GCKGenericChannelDelegate-[castChannelDidConnect:]-[castChannelDidDisconnect:] 方法提供實作 (如果使用 GCKGenericChannel)。

支援自動播放

請參閱自動播放與佇列 API

覆寫圖片選取及快取設定

架構的各個元件 (包括投放對話方塊、小型控制器、展開的控制器和 GCKUIMediaController (如有設定)) 會顯示目前投放媒體的圖片。圖片圖片的網址通常會包含在媒體的 GCKMediaMetadata 中,但傳送方應用程式可能有網址的替代來源。

GCKUIImagePicker 通訊協定定義了針對特定使用方式和所需大小選取適當圖片的方式。其中包含單一方法 -[getImageWithHints:fromMetadata:],此方法會將 GCKUIImageHints 物件和 GCKMediaMetadata 物件做為參數,並傳回 GCKImage 物件做為結果。該架構提供預設的 GCKUIImagePicker 實作方式,一律會從 GCKMediaMetadata 物件的圖片清單中選取第一張圖片,但應用程式可設定 GCKCastContext 單例模式的 imagePicker 屬性,提供替代實作方式。

GCKUIImageCache 通訊協定也定義了快取映像檔,並以 HTTPS 下載的圖片。這個架構提供預設的 GCKUIImageCache 實作方式,會將下載的圖片檔儲存在應用程式的快取目錄中,但應用程式可設定 GCKCastContext 單例的 imageCache 屬性來提供替代實作方式。

後續步驟

以上是可新增至 iOS 寄件者應用程式的功能。您現在可以為其他平台 (Android網頁版) 建構傳送端應用程式,或是建構網路接收器