Adicionar recursos avançados ao app iOS

Intervalos de anúncio

O SDK do remetente do iOS oferece suporte para intervalos de anúncio e anúncios complementares em um em um determinado fluxo de mídia.

Consulte a Visão geral dos intervalos de anúncios do receptor da Web para mais informações sobre como funcionam os intervalos de anúncio.

Embora os intervalos possam ser especificados tanto para quem envia quanto para quem recebe, recomendamos que eles sejam especificado no Receptor da Web e Receptor do Android TV para manter a consistência do comportamento entre as plataformas.

No iOS, especifique intervalos de anúncio em um comando de carregamento usando GCKAdBreakClipInfo e GCKAdBreakInfo:

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]];

Taxa de reprodução variável

Seu app pode mostrar e mudar a velocidade do vídeo do item de mídia atual. É possível definir a taxa usando -[setPlaybackRate:] ou -[setPlaybackRate:customData:] dos GCKRemoteMediaClient, acessar GCKUIPlaybackRateController usando playbackRateController do GCKUIMediaController e mostrar a velocidade do vídeo atual usando playbackRate dos GCKUIPlaybackRateController

Código de amostra

Os dois arquivos a seguir implementam GCKUIPlaybackRateController, que controla a velocidade do vídeo usando um controle segmentado que tem "normal", "meia velocidade" e "velocidade dupla" botões:

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

Adicionar um canal personalizado

O framework do Google Cast oferece duas maneiras de criar um canal para enviar mensagens personalizadas. a um receptor da Web:

  1. GCKCastChannel deve ser uma subclasse para implementar canais não triviais que têm o estado associado.
  2. GCKGenericChannel é fornecido como uma alternativa às subclasses; ele passa a mensagem recebida mensagens a um delegado para que possam ser processadas em outro lugar.

Confira um exemplo de implementação de 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

Um canal pode ser registrado a qualquer momento. se a sessão não estiver em um conectado, o canal será conectado automaticamente quando o sessão em si está conectada, desde que o namespace do canal esteja presente no a lista dos metadados do app receptor da Web de namespaces compatíveis.

Cada canal personalizado é definido por um namespace exclusivo e deve começar com o Prefixo urn:x-cast:, por exemplo, urn:x-cast:com.example.custom. É possível ter vários canais personalizados, cada um com um namespace exclusivo. A O app receptor da Web também pode enviar e receber mensagens usando o mesmo namespace.

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

Para fornecer a lógica que precisa ser executada quando um canal específico se torna conectado ou desconectado, substitua -[didConnect] e -[didDisconnect] se estiver usando GCKCastChannel ou fornecer implementações para -[castChannelDidConnect:] e -[castChannelDidDisconnect:] do GCKGenericChannelDelegate se estiver usando GCKGenericChannel.

Compatibilidade com reprodução automática

Consulte Reprodução automática e APIs de enfileiramento.

Substituir a seleção e o armazenamento em cache de imagens

Vários componentes do framework, como a caixa de diálogo "Transmitir", os de controle, o controle expandido e o GCKUIMediaController se configurado) vai exibir a arte da mídia transmitida no momento. Os URLs à arte da imagem são normalmente incluídos no GCKMediaMetadata para a mídia, mas o app remetente pode ter uma fonte alternativa para os URLs.

A GCKUIImagePicker define um meio de selecionar uma imagem apropriada para um determinado uso e o tamanho desejado. Ele tem um único método, -[getImageWithHints:fromMetadata:], o que leva GCKUIImageHints objeto e um GCKMediaMetadata objeto como parâmetros e retorna uma objeto GCKImage como um resultado. O framework fornece uma implementação padrão GCKUIImagePicker, que sempre seleciona a primeira imagem na lista de imagens em o objeto GCKMediaMetadata, mas o app pode fornecer uma alternativa de implementação definindo a propriedade imagePicker do GCKCastContext singleton.

A GCKUIImageCache também define um meio de armazenar em cache imagens que são baixadas pelo usando HTTPS. O framework fornece uma implementação padrão GCKUIImageCache, que armazena arquivos de imagem transferidos por download no cache do app. mas o aplicativo pode fornecer uma implementação alternativa configurando o propriedade imageCache do GCKCastContext singleton.

Próximas etapas

Isso conclui os recursos que você pode adicionar ao app Sender do iOS. Agora você pode criar um app remetente para outra plataforma (Android ou Web), ou criar um Receptor Web.