Warning: The IMA SDK for Cast SDK v2 has been officially deprecated, as of November 17th, 2021. All existing users are urged to migrate to CAF native Ad Breaks.

iOS sender app

This guide shows you how to create a cast-enabled iOS Sender App by walking you through an existing example app.

To follow along with this guide, download our cast example, which is a complete iOS app that implements casting functionality for videos with ads using the IMA iOS SDK.

Prerequisites

This guide builds upon existing knowledge of the Google Cast SDK and the IMA SDK for iOS. Users should familiarize themselves with:

This guide discusses the specific setup used in the Cast Example to communicate with the receiver. It doesn't cover standard Cast setup code or normal IMA ad playback. For more details on implementing the receiver, see our HTML5 Receiver Guide.

Sending messages

The casting logic for CastExample is implemented in CastViewController.m. It uses a cast channel defined in CastMessageChannel.h to route messages between receiver and sender. The castVideo function attempts to load the content URL, it then sends a custom messsage to the receiver telling it to request ads using the same ad tag and seek to the sender's current timestamp.

CastViewController.m

- (IBAction)castVideo:(id)sender {
  // Show alert if not connected.
  if (!self.deviceManager ||
      self.deviceManager.connectionState != GCKConnectionStateConnected) {
    UIAlertController *alert = [UIAlertController
        alertControllerWithTitle:@"Not Connected"
                         message:@"Please connect to Cast device"
                  preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *action =
        [UIAlertAction actionWithTitle:@"OK"
                                 style:UIAlertActionStyleDefault
                               handler:nil];
    [alert addAction:action];
    [self presentViewController:alert animated:YES completion:nil];
    return;
  }

  [self.viewController pauseVideo];
  NSString *contentUrl = self.viewController.kContentUrl;
  GCKMediaMetadata *metadata = [[GCKMediaMetadata alloc] init];
  GCKMediaInformation *mediaInformation =
      [[GCKMediaInformation alloc] initWithContentID:contentUrl
                                          streamType:GCKMediaStreamTypeBuffered
                                         contentType:@"video/mp4"
                                            metadata:metadata
                                      streamDuration:0
                                          customData:nil];
  [self.mediaControlChannel loadMedia:mediaInformation
                             autoplay:NO
                         playPosition:0];
  if (self.viewController.adIsVmap || !self.viewController.adHasStarted) {
    [self sendMessage:[NSString
                          stringWithFormat:@"requestAd,%@,%f",
                                           self.viewController.kAdTagUrl,
                                           CMTimeGetSeconds(
                                               self.viewController.contentPlayer
                                                   .currentTime)]];
  } else {
    [self sendMessage:[NSString
                          stringWithFormat:@"seek,%f",
                                           CMTimeGetSeconds(
                                               self.viewController.contentPlayer
                                                   .currentTime)]];
  }
}

- (void)sendMessage:(NSString *)message {
  NSLog(@"Sending message: %@", message);
  [self.messageChannel sendTextMessage:message];
}

Two messages are defined: seek, to resume playback on the receiver without ads, and requestAd, which re-requests the same ad tag on the receiver. This is used for ad playlists and VMAP in this example, but you can define your own behavior for what should happen when you cast. These messages are comma-delimited, where the first parameter is the message name, and the remaining parameters are ad-tag and seek time.

Receiving messages

The receiver provides notices of time updates from a casting video and when a casted ad stops and content starts. This is handled in the sender by two messages:

  • onContentPauseRequested
  • onContentResumeRequested

These messages are comma-delimited and formatted similarly to the seek and requestAd messages described above.

- (void)onCastMessageReceived:(CastMessageChannel *)channel
                  withMessage:(NSString *)message {
  // handle the delegate being called here
  NSLog(@"Receiving message: %@", message);
  NSArray *splitMessage = [message componentsSeparatedByString:@","];
  NSString *event = splitMessage[0];
  if ([event isEqualToString:@"onContentPauseRequested"]) {
    self.castAdPlaying = true;
    self.castContentTime =
        CMTimeMakeWithSeconds([splitMessage[1] floatValue], 1);
  } else if ([event isEqualToString:@"onContentResumeRequested"]) {
    self.castAdPlaying = false;
  }
}

The variables castAdPlaying and castContentTime are used to determine whether an ad is playing on the cast device and to store the content time at which the ad was started. In the event the receiver stops casting, the sender knows where to resume content from.

Next steps

At this point you have a good understanding of how the iOS sender app interacts with the receiver. To try it out, create a receiver app and register your receiver in order to receive an app ID that's used with API calls from the sender app.