Coupures publicitaires
Le SDK iOS Sender est compatible avec les coupures publicitaires et les annonces associées dans un flux multimédia donné.
Pour en savoir plus sur le fonctionnement des coupures publicitaires, consultez la présentation des coupures publicitaires du Web Receiver.
Bien que les coupures puissent être spécifiées à la fois sur l'expéditeur et le récepteur, il est recommandé de les spécifier sur le Web Receiver et récepteur Android TV pour maintenir un comportement cohérent sur toutes les plates-formes.
Sur iOS, spécifiez les coupures publicitaires dans une commande de chargement à l'aide de
GCKAdBreakClipInfo
et 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]];
Vitesse de lecture variable
Votre application peut afficher et modifier la vitesse de lecture de l'élément multimédia actuel.
Vous pouvez définir la vitesse à l'aide de -[setPlaybackRate:] ou
-[setPlaybackRate:customData:] de la
GCKRemoteMediaClient,
accéder à GCKUIPlaybackRateController à l'aide de playbackRateController de la
GCKUIMediaController,
et afficher la vitesse de lecture actuelle à l'aide de playbackRate de la
GCKUIPlaybackRateController.
Exemple de code
Les deux fichiers suivants implémentent GCKUIPlaybackRateController, qui contrôle la vitesse de lecture à l'aide d'un contrôle segmenté comportant les boutons "normal", "demi-vitesse" et "double vitesse" :
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
Ajouter un canal personnalisé
Le framework Cast offre deux façons de créer un canal pour envoyer des messages personnalisés à un Web Receiver :
GCKCastChannelest destiné à être sous-classé pour implémenter des canaux non triviaux ayant un état associé.GCKGenericChannelest fourni comme alternative à la sous-classe. Il transmet les messages reçus à un délégué afin qu'ils puissent être traités ailleurs.
Voici un exemple d'implémentation 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
Un canal peut être enregistré à tout moment. Si la session n'est pas actuellement dans un état connecté, le canal se connecte automatiquement lorsque la session elle-même est connectée, à condition que l'espace de noms du canal soit présent dans la liste des espaces de noms compatibles des métadonnées de l'application Web Receiver.
Chaque canal personnalisé est défini par un espace de noms unique et doit commencer par le
préfixe urn:x-cast:, par exemple, urn:x-cast:com.example.custom. Il est possible d'avoir plusieurs canaux personnalisés, chacun avec un espace de noms unique. L'
application Web Receiver peut également envoyer et recevoir
des messages
à l'aide du même espace de noms.
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); }
Pour fournir une logique qui doit s'exécuter lorsqu'un canal particulier devient
connecté ou déconnecté, remplacez les -[didConnect] et -[didDisconnect]
méthodes si vous utilisez
GCKCastChannel, ou
fournissez des implémentations pour les -[castChannelDidConnect:] et
-[castChannelDidDisconnect:] méthodes de la
GCKGenericChannelDelegate
si vous utilisez GCKGenericChannel.
Compatibilité avec la lecture automatique
Consultez la section API de lecture automatique et de mise en file d'attente.
Remplacer la sélection et la mise en cache des images
Différents composants du framework (à savoir la boîte de dialogue Cast, le mini
contrôleur, le contrôleur étendu et le
GCKUIMediaController
si configuré) affichent l'illustration du contenu multimédia en cours de diffusion. Les URL
des illustrations sont généralement incluses dans le
GCKMediaMetadata
pour le contenu multimédia, mais l'application émettrice peut avoir une autre source pour les URL.
Le
GCKUIImagePicker
protocole définit un moyen de sélectionner une image appropriée pour une utilisation
et une taille souhaitées. Il comporte une seule méthode, -[getImageWithHints:fromMetadata:],
qui prend un
GCKUIImageHints
objet et un
GCKMediaMetadata
objet comme paramètres, et renvoie un
GCKImage objet comme
résultat. Le framework fournit une implémentation par défaut de
GCKUIImagePicker qui sélectionne toujours la première image de la liste d'images de
l'objet GCKMediaMetadata, mais l'application peut fournir une autre
implémentation en définissant la propriété imagePicker du
GCKCastContext
singleton.
Le
GCKUIImageCache
protocole définit également un moyen de mettre en cache les images téléchargées par le
framework à l'aide du protocole HTTPS. Le framework fournit une implémentation par défaut de
GCKUIImageCache qui stocke les fichiers image téléchargés dans le cache de l'application
répertoire, mais l'application peut fournir une autre implémentation en définissant la propriété
imageCache du
GCKCastContext
singleton.
Étapes suivantes
Vous avez terminé d'ajouter des fonctionnalités à votre application iOS Sender. Vous pouvez maintenant créer une application émettrice pour une autre plate-forme (Android ou Web), ou créer un Web Receiver.