向自定义网络接收器添加核心功能

本页包含 Google Cloud 上的代码段, 自定义 Web Receiver 应用。

  1. 表示内置播放器界面的 cast-media-player 元素 Web Receiver 提供的资源。
  2. cast-media-player 元素设置类似于 CSS 的自定义样式,以便设置各种样式 界面元素,例如 background-imagesplash-imagefont-family
  3. 用于加载 Web 接收器框架的脚本元素。
  4. 用于拦截消息和处理事件的 JavaScript 代码。
  5. 加入自动播放队列。
  6. 用于配置播放的选项。
  7. 用于设置 Web 接收器上下文的选项。
  8. 用于设置 Web 接收器应用支持的命令的选项。
  9. 用于启动 Web 接收器应用的 JavaScript 调用。

应用配置和选项

配置应用

通过 CastReceiverContext 是提供给开发者的最外层的类,用于管理 并处理 Web Receiver SDK 的初始化。SDK 提供的 API 可让应用开发者通过 CastReceiverOptions。 这些配置会在应用每次启动时评估一次,然后传递到 在对 start

以下示例展示了如何替换默认行为,以检测 发送者的连接仍处于活跃连接状态当网络接收器尚未收到 能够与发件人通信 maxInactivity 秒,系统会分派 SENDER_DISCONNECTED 事件。以下配置 覆盖此超时。这在调试问题时很有用,因为它可以防止 Web 接收器应用在以下情况下关闭 Chrome 远程调试程序会话: 是零个处于 IDLE 状态的连接的发送者。

const context = cast.framework.CastReceiverContext.getInstance();
const options = new cast.framework.CastReceiverOptions();
options.maxInactivity = 3600; // Development only
context.start(options);

配置播放器

加载内容时,Web Receiver SDK 提供了一种方法来配置播放 变量,例如数字版权管理 (DRM) 信息, 重试配置,并使用 cast.framework.PlaybackConfig。 这些信息的处理方 PlayerManager 并在创建播放器时进行评估。播放器是 系统在每次有新加载的内容传递给 Web Receiver SDK 时触发。对 播放器创建后的 PlaybackConfig 将在下一个 内容加载。SDK 提供了以下用于修改 PlaybackConfig

以下示例展示了如何在初始化PlaybackConfig CastReceiverContext。此配置会覆盖针对 获取清单。该处理程序会指定 CORS Access-Control 请求 使用 Cookie 或授权标头等凭据创建。

const playbackConfig = new cast.framework.PlaybackConfig();
playbackConfig.manifestRequestHandler = requestInfo => {
  requestInfo.withCredentials = true;
};
context.start({playbackConfig: playbackConfig});

以下示例展示了如何使用 getter 替换 PlaybackConfig 和 setter 方法(在 PlayerManager 中提供)。该设置将播放器配置为 在加载 1 个片段后继续播放内容。

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
const playbackConfig = (Object.assign(
            new cast.framework.PlaybackConfig(), playerManager.getPlaybackConfig()));
playbackConfig.autoResumeNumberOfSegments = 1;
playerManager.setPlaybackConfig(playbackConfig);

以下示例展示了如何针对特定加载替换 PlaybackConfig 请求。处理程序会调用应用 实现了 getLicenseUrlForMedia 方法,用于从licenseUrl 当前项的 contentId

playerManager.setMediaPlaybackInfoHandler((loadRequestData, playbackConfig) => {
  const mediaInformation = loadRequestData.media;
  playbackConfig.licenseUrl = getLicenseUrlForMedia(mediaInformation.contentId);

  return playbackConfig;
});

事件监听器

Web Receiver SDK 可让您的 Web 接收器应用处理播放器事件。通过 事件监听器将 cast.framework.events.EventType 参数(或这些参数的数组),用来指定需要触发 触发监听器。预配置的数组 可用于调试的 cast.framework.events.EventType 可在 cast.framework.events.category。 事件参数提供了有关事件的更多信息。

例如,如果您想知道 mediaStatus 则可以使用以下逻辑来处理 事件:

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
playerManager.addEventListener(
    cast.framework.events.EventType.MEDIA_STATUS, (event) => {
      // Write your own event handling code, for example
      // using the event.mediaStatus value
});

消息拦截

Web Receiver SDK 允许您的网络接收器应用拦截消息并 对这些消息执行自定义代码。消息拦截器接受一个 cast.framework.messages.MessageType 用于指定应拦截的消息类型的参数。

拦截器应该返回修改后的请求或解析 替换为修改后的请求值。返回 null 将阻止调用 默认消息处理程序。如需了解详情,请参阅加载媒体

例如,如果您想更改加载请求数据,可以使用 以下逻辑来拦截和修改它:

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_FAILED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      if (!loadRequestData.media.entity) {
        return loadRequestData;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          if (!asset) {
            throw cast.framework.messages.ErrorReason.INVALID_REQUEST;
          }

          loadRequestData.media.contentUrl = asset.url;
          loadRequestData.media.metadata = asset.metadata;
          loadRequestData.media.tracks = asset.tracks;
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

context.start();

错误处理

当消息拦截器中发生错误时,您的 Web 接收器应用应返回 适当的 cast.framework.messages.ErrorTypecast.framework.messages.ErrorReason

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_CANCELLED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      ...

      return fetchAssetAndAuth(loadRequestData.media.entity,
                               loadRequestData.credentials)
        .then(asset => {
          ...
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

消息拦截与事件监听器

消息拦截和事件监听器之间的一些主要区别如下 如下:

  • 事件监听器允许您修改请求数据。
  • 事件监听器最适合用于触发分析或自定义函数。
playerManager.addEventListener(cast.framework.events.category.CORE,
    event => {
        console.log(event);
    });
  • 通过消息拦截,您可以监听、拦截消息,以及 修改请求数据本身
  • 消息拦截最适合用于处理有关 请求数据。

加载媒体

MediaInformation 提供了众多属性来 包含 entitycast.framework.messages.MessageType.LOAD 消息, contentUrlcontentId

  • entity 在实现过程中,建议为发件人和 接收器应用。该属性是一个深层链接网址,可以是播放列表 或媒体内容您的应用程序应该解析此网址,然后 请至少填写其他两个字段中的其中一个。
  • contentUrl 与播放器用来加载内容的可播放网址相对应。 例如,此网址可以指向 DASH 清单。
  • contentId 可以是可播放内容网址(类似于 contentUrl 属性)或正在加载的内容或播放列表的唯一标识符。 如果使用此属性作为标识符,您的应用应填充 contentUrl中的可播放网址。

建议使用 entity 存储实际 ID 或键参数,并且 使用 contentUrl 作为媒体的网址。示例 以下代码段中,entity 出现在 LOAD 请求中, 检索到可播放的 contentUrl

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      ...

      if (!loadRequestData.media.entity) {
        // Copy the value from contentId for legacy reasons if needed
        loadRequestData.media.entity = loadRequestData.media.contentId;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          loadRequestData.media.contentUrl = asset.url;
          ...
          return loadRequestData;
        });
    });

设备功能

通过 getDeviceCapabilities 方法提供已连接的 Cast 设备上的设备信息,以及视频或 音频设备。getDeviceCapabilities 方法提供支持 Google 助理、蓝牙以及已连接的显示屏和音频的信息 设备。

此方法会返回一个对象,您可以通过传入 指定的枚举以获取该枚举的设备功能。枚举是 定义于 cast.framework.system.DeviceCapabilities

此示例会检查 Web Receiver 设备是否能够播放 HDR 视频并 使用 IS_HDR_SUPPORTEDIS_DV_SUPPORTED 键的 DolbyVision (DV), 。

const context = cast.framework.CastReceiverContext.getInstance();
context.addEventListener(cast.framework.system.EventType.READY, () => {
  const deviceCapabilities = context.getDeviceCapabilities();
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED] value
  }
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED] value
  }
});
context.start();

处理用户互动

用户可以通过发送器与您的 Web Receiver 应用互动 应用(Web、Android 和 iOS)、通过内置 Google 助理的语音指令 设备、智能显示屏上的触控功能以及 Android TV 上的遥控器 设备。Cast SDK 提供了各种 API,可让网络接收器应用 处理这些交互,通过 用户操作状态 然后根据需要发送更改以更新任何后端服务。

支持的媒体命令

界面控件状态由 MediaStatus.supportedMediaCommands 适用于 iOS 和 Android 发送器展开的控制器、接收器和遥控器 触摸设备上运行的应用,以及 Android TV 设备上的接收器应用。当 属性中启用了特定的按位 Command, 与该操作相关的一项如果未设置该值,则按钮为 已停用。您可通过以下方式在 Web Receiver 上更改这些值:

  1. 使用 PlayerManager.setSupportedMediaCommands 以便设置 Commands
  2. 使用以下代码添加新命令: addSupportedMediaCommands
  3. 使用以下代码移除现有命令: removeSupportedMediaCommands
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
  cast.framework.messages.Command.PAUSE);

当接收器准备好更新后的 MediaStatus 时,它将包含 更改 supportedMediaCommands 属性。状态为 已连接的发送者应用会更新其界面中的按钮 。

如需详细了解支持的媒体命令和触摸设备,请参阅 Accessing UI controls 指南。

管理用户操作状态

当用户与界面互动或发送语音指令时,可以控制 与所播放项相关的内容和属性的播放次数。请求数 SDK 会自动处理控制播放的音频。请求 修改当前播放项的属性,例如 LIKE 命令、 需要接收方应用处理它们。SDK 提供了一系列 用于处理这些类型请求的 API。为了支持这些请求,以下做法 必须完成的步骤:

  • 设置 MediaInformation userActionStates 加载媒体项时用户的偏好设置。
  • 拦截 USER_ACTION 消息并确定请求的操作。
  • 更新 MediaInformation UserActionState 以更新界面。

以下代码段会拦截 LOAD 请求并填充 LoadRequestDataMediaInformation。在这种情况下,用户喜欢 正在加载的内容。

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, (loadRequestData) => {
      const userActionLike = new cast.framework.messages.UserActionState(
          cast.framework.messages.UserAction.LIKE);
      loadRequestData.media.userActionStates = [userActionLike];

      return loadRequestData;
    });

以下代码段会拦截 USER_ACTION 消息并处理调用 具有所请求更改的后端然后,它会调用更新 针对接收器的 UserActionState

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.USER_ACTION,
  (userActionRequestData) => {
    // Obtain the media information of the current content to associate the action to.
    let mediaInfo = playerManager.getMediaInformation();

    // If there is no media info return an error and ignore the request.
    if (!mediaInfo) {
        console.error('Not playing media, user action is not supported');
        return new cast.framework.messages.ErrorData(messages.ErrorType.BAD_REQUEST);
    }

    // Reach out to backend services to store user action modifications. See sample below.
    return sendUserAction(userActionRequestData, mediaInfo)

    // Upon response from the backend, update the client's UserActionState.
    .then(backendResponse => updateUserActionStates(backendResponse))

    // If any errors occurred in the backend return them to the cast receiver.
    .catch((error) => {
      console.error(error);
      return error;
    });
});

以下代码段模拟了对后端服务的调用。函数检查 UserActionRequestData,以查看用户请求的更改类型 并且仅在后端支持操作时进行网络调用。

function sendUserAction(userActionRequestData, mediaInfo) {
  return new Promise((resolve, reject) => {
    switch (userActionRequestData.userAction) {
      // Handle user action changes supported by the backend.
      case cast.framework.messages.UserAction.LIKE:
      case cast.framework.messages.UserAction.DISLIKE:
      case cast.framework.messages.UserAction.FOLLOW:
      case cast.framework.messages.UserAction.UNFOLLOW:
      case cast.framework.messages.UserAction.FLAG:
      case cast.framework.messages.UserAction.SKIP_AD:
        let backendResponse = {userActionRequestData: userActionRequestData, mediaInfo: mediaInfo};
        setTimeout(() => {resolve(backendResponse)}, 1000);
        break;
      // Reject all other user action changes.
      default:
        reject(
          new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType.INVALID_REQUEST));
    }
  });
}

以下代码段会获取 UserActionRequestData,并添加 或 从 MediaInformation 中移除 UserActionState。更新 MediaInformationUserActionState 会更改用于 与请求的操作相关联。此更改会反映在 显示控制界面、遥控器应用和 Android TV 界面。它还 通过传出的 MediaStatus 消息广播,以更新 适用于 iOS 和 Android 发送器的扩展控制器。

function updateUserActionStates(backendResponse) {
  // Unwrap the backend response.
  let mediaInfo = backendResponse.mediaInfo;
  let userActionRequestData = backendResponse.userActionRequestData;

  // If the current item playing has changed, don't update the UserActionState for the current item.
  if (playerManager.getMediaInformation().entity !== mediaInfo.entity) {
    return;
  }

  // Check for existing userActionStates in the MediaInformation.
  // If none, initialize a new array to populate states with.
  let userActionStates = mediaInfo.userActionStates || [];

  // Locate the index of the UserActionState that will be updated in the userActionStates array.
  let index = userActionStates.findIndex((currUserActionState) => {
    return currUserActionState.userAction == userActionRequestData.userAction;
  });

  if (userActionRequestData.clear) {
    // Remove the user action state from the array if cleared.
    if (index >= 0) {
      userActionStates.splice(index, 1);
    }
    else {
      console.warn("Could not find UserActionState to remove in MediaInformation");
    }
  } else {
    // Add the UserActionState to the array if enabled.
    userActionStates.push(
      new cast.framework.messages.UserActionState(userActionRequestData.userAction));
  }

  // Update the UserActionState array and set the new MediaInformation
  mediaInfo.userActionStates = userActionStates;
  playerManager.setMediaInformation(mediaInfo, true);
  return;
}

语音指令

Web Receiver SDK 目前支持以下媒体命令: 内置 Google 助理的设备。这些命令的默认实现是 发现位置: cast.framework.PlayerManager

命令 说明
Google Play 播放或从暂停状态继续播放。
暂停 暂停当前正在播放的内容。
上一步 跳至媒体队列中的上一个媒体项。
前进 跳至媒体队列中的下一个媒体项。
停止 停止当前正在播放的媒体。
不重复 当队列中的最后一项播放完毕后,禁止重复播放队列中的媒体项。
单曲重复 无限重复播放当前播放的媒体。
全部重复 播放完队列中的最后一项后,重复播放队列中的所有项。
全部重复播放并随机播放 当队列中的最后一项播放完毕后,随机打乱队列,然后重复播放该队列中的所有项。
随机播放 随机播放媒体队列中的媒体项。
字幕开启 / 关闭 为媒体启用 / 停用字幕。启用 / 停用还可以按语言进行选择。
跳转绝对时间 跳转到指定的绝对时间。
跳转相对于当前时间的时间 向前或向后跳转指定时间段(相对于当前播放时间)。
再玩一次 重播当前播放的媒体,或者播放上次播放的媒体项(如果当前未播放任何内容)。
设置播放速率 改变媒体播放速率。默认情况下,系统会处理此事件。您可以使用 SET_PLAYBACK_RATE 消息拦截器来替换传入的速率请求。

支持的语音指令媒体指令

要阻止某个语音指令通过 Google 助理触发媒体命令,请执行以下操作: 必须先设置 支持的媒体命令 以及计划支持的存储类型然后,您必须通过启用 该 CastReceiverOptions.enforceSupportedCommands 属性。Cast SDK 发送器和支持触摸的设备上的界面将更改为 来反映这些配置如果未启用该标志,则传入语音 命令的执行时间。

例如,如果您允许来自您的发件人应用的 PAUSE,并且 那么您还必须配置接收器以反映 设置。配置完成后,系统会舍弃所有收到的语音指令(如果不是) 已包含在受支持的命令列表中。

在下面的示例中,我们在启动应用时提供 CastReceiverOptions CastReceiverContext。我们添加了对 PAUSE 命令和 强制播放器仅支持该命令。现在,如果某个语音指令 请求另一操作(例如 SEEK),它将被拒绝。该用户将 会发出通知,告知您此命令尚不受支持。

const context = cast.framework.CastReceiverContext.getInstance();

context.start({
  enforceSupportedCommands: true,
  supportedCommands: cast.framework.messages.Command.PAUSE
});

您可以针对要限制的每个命令应用单独的逻辑。移除 enforceSupportedCommands 标志。 限制您可以拦截传入消息。在这里,我们拦截了 以便向内置 Google 助理的设备发出 SEEK 命令 不会在 Web Receiver 应用中触发搜索。

对于您的应用不支持的媒体命令,请返回相应的 错误原因,例如 NOT_SUPPORTED

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.SEEK,
  seekData => {
    // Block seeking if the SEEK supported media command is disabled
    if (!(playerManager.getSupportedMediaCommands() & cast.framework.messages.Command.SEEK)) {
      let e = new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType
      .INVALID_REQUEST);
      e.reason = cast.framework.messages.ErrorReason.NOT_SUPPORTED;
      return e;
    }

    return seekData;
  });

从语音 activity 切换到后台运行

如果 Cast 平台因 Google 助理而将应用的声音置于后台 例如聆听用户说话或进行回应, FocusState 收到 NOT_IN_FOCUS 消息后, activity 启动。当 activity 结束时,系统会发送另一条包含 IN_FOCUS 的消息。 根据您的应用和正在播放的媒体,您可能需要 在 FocusStateNOT_IN_FOCUS 时通过拦截消息暂停媒体 类型 FOCUS_STATE

例如,如果遇到以下情况,那么暂停有声读物播放就是一种很好的用户体验 Google 助理正在响应用户询问。

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.FOCUS_STATE,
  focusStateRequestData => {
    // Pause content when the app is out of focus. Resume when focus is restored.
    if (focusStateRequestData.state == cast.framework.messages.FocusState.NOT_IN_FOCUS) {
      playerManager.pause();
    } else {
      playerManager.play();
    }

    return focusStateRequestData;
  });

指定语音的字幕语言

如果用户没有明确说明字幕语言, 字幕使用的语言与说出命令时所用的语言相同。 在这两种情况下, isSuggestedLanguage 参数表明关联的语言是否 或明确请求的内容。

例如,对于命令“Ok Google”,isSuggestedLanguage 会设置为 true。 打开字幕”因为语言是由系统推断出的语言 你说了什么命令如果已明确请求该语言,例如“OK”, Google,请开启英语字幕”isSuggestedLanguage 设置为 false

元数据和语音投放

虽然默认情况下通过网络接收器处理语音命令, 确保内容的元数据完整且准确。这样可以确保 Google 助理会正确处理语音指令,并且元数据 能够在各种新型界面(如 Google Home 应用和 例如 Google Home Hub。

流式传输

保留会话状态是数据流传输的基础, 用户可以使用语音指令、Google Home 跨设备移动现有音频和视频流 应用或智能显示屏媒体在一台设备(源设备)上停止播放,然后在另一台设备(源设备)上继续播放 目标)。任何具有最新固件的投放设备都可以在 流式传输。

视频流传输的事件流程如下:

  1. 在源设备上:
    1. 媒体停止播放。
    2. Web 接收器应用收到保存当前媒体的命令 state.
    3. Web Receiver 应用已关闭。
  2. 在目标设备上:
    1. Web Receiver 应用已加载。
    2. Web 接收器应用收到恢复已保存媒体的命令 state.
    3. 媒体继续播放。

媒体状态的元素包括:

  • 歌曲、视频或媒体内容的具体位置或时间戳。
  • 位于范围更广的队列中(例如播放列表或音乐人电台)。
  • 经过身份验证的用户。
  • 播放状态(例如,正在播放或已暂停)。

启用流式传输

要为网络接收器实现流式传输,请执行以下操作:

  1. 更新 supportedMediaCommands 替换为 STREAM_TRANSFER 命令:
    playerManager.addSupportedMediaCommands(
    cast.framework.messages.Command.STREAM_TRANSFER, true);
  2. (可选)替换 SESSION_STATERESUME_SESSION 消息 拦截器,如保留会话中所述 状态。仅在需要自定义数据时才替换这些设置 存储为会话快照的一部分否则, 用于保留会话状态的实现将支持流传输。

保留会话状态

Web Receiver SDK 为网络接收器应用提供了默认实现, 通过拍摄当前媒体状态的快照来保留会话状态, 并通过该加载请求恢复会话。

Web Receiver 生成的加载请求可在 SESSION_STATE 消息拦截器(如有必要)。如果您想添加自定义数据 添加到加载请求中,我们建议您将它们放入 loadRequestData.customData

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.SESSION_STATE,
    function (sessionState) {
        // Override sessionState.loadRequestData if needed.
        const newCredentials = updateCredentials_(sessionState.loadRequestData.credentials);
        sessionState.loadRequestData.credentials = newCredentials;

        // Add custom data if needed.
        sessionState.loadRequestData.customData = {
            'membership': 'PREMIUM'
        };

        return sessionState;
    });

您可以从 loadRequestData.customDataRESUME_SESSION 消息拦截器中。

let cred_ = null;
let membership_ = null;

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.RESUME_SESSION,
    function (resumeSessionRequest) {
        let sessionState = resumeSessionRequest.sessionState;

        // Modify sessionState.loadRequestData if needed.
        cred_ = sessionState.loadRequestData.credentials;

        // Retrieve custom data.
        membership_ = sessionState.loadRequestData.customData.membership;

        return resumeSessionRequest;
    });

内容预加载

网络接收器支持在当前播放完成后预加载媒体项 队列中的下一个项目。

预加载操作会预先下载 即将推出的内容。规范是在 preloadTime 值(位于 QueueItem 对象 (如未提供,则默认为 20 秒)。该时间以秒为单位 相对于当前播放项的结尾 。只有正值 有效。例如,如果值为 10 秒,则此商品将预加载 10 秒 。如果预加载时间较长 且预加载时间超过 currentItem 的时间,则预加载会在 因此,如果对 queueItem 指定了非常大的预加载值, 只要播放当前列表项,就能实现以下效果: 正在预加载下一项。不过,我们保留了 因为此值可能会影响带宽和流式传输性能 当前播放项的播放进度。

默认情况下,预加载适用于 HLS、DASH 和流畅流式传输内容。

常规 MP4 视频和音频文件(例如 MP3)不会预加载为 Cast 设备仅支持一个媒体元素,在 现有内容项仍在播放。

自定义消息

消息交换是网络接收器应用的关键互动方法。

发件人使用发件人 API 向网络接收器发送 发送方正在运行的平台(Android、iOS、Web)。事件对象( 是消息的清单),且该消息具有 数据元素 (event.data),其中数据采用 特定事件类型。

Web Receiver 应用可选择 命名空间。这样一来,Web 接收器应用便能 支持该命名空间协议然后由所有希望连接的发件人决定 在该命名空间上进行通信,以使用适当的协议。

所有命名空间都由字符串定义,且必须以“urn:x-cast:”开头 后跟任意字符串。例如: “urn:x-cast:com.example.cast.mynamespace”。

这是一个代码段,网络接收器可监听来自 已连接的发件人:

const context = cast.framework.CastReceiverContext.getInstance();

const CUSTOM_CHANNEL = 'urn:x-cast:com.example.cast.mynamespace';
context.addCustomMessageListener(CUSTOM_CHANNEL, function(customEvent) {
  // handle customEvent.
});

context.start();

同样,Web 接收器应用可以让发送器了解 从而向已连接的发件人发送消息网络接收器 应用可以使用 sendCustomMessage(namespace, senderId, message) 已开启 CastReceiverContext。 网络接收器可以向单个发件人发送邮件,无论是响应 或由于应用状态更改而触发。不局限于点对点 消息(上限为 64kb),网络接收器也可以向 所有已连接的发件人。

适用于音频设备的 Cast

请参阅适用于音频设备的 Google Cast 指南,获取关于音频的支持 只能播放。

Android TV

本部分介绍了 Google 网络接收器如何使用您的输入作为播放, 以及 Android TV 兼容性

将您的应用与遥控器集成

在 Android TV 设备上运行的 Google Web Receiver 可将 设备的控制输入(即手持遥控器)作为媒体播放 为 urn:x-cast:com.google.cast.media 命名空间定义的消息,如 媒体播放消息中所述。您的 应用必须支持这些消息,才能控制应用媒体 播放,以便允许通过 Android TV 的控件进行基本的播放控制 输入。

Android TV 兼容性准则

下面是一些建议和要避免的常见误区 您的应用与 Android TV 兼容:

  • 请注意,用户代理字符串中同时包含“Android”和“CrKey”; 有些网站可能会重定向到专门面向移动设备的网站,因为它们 “Android”标签。不要以为“Android”始终位于用户代理字符串中 表示移动用户。
  • Android 的媒体堆栈可能会使用透明的 GZIP 来提取数据。请确保 您的媒体数据可以响应 Accept-Encoding: gzip
  • Android TV HTML5 媒体事件的触发时间可能与 Chromecast,这样可能会发现在 Chromecast 上已隐藏的问题。
  • 更新媒体时,请使用由 <audio>/<video> 触发的媒体相关事件 元素,如 timeupdatepausewaiting。避免使用网络 progresssuspendstalled 等相关事件,因为它们往往 取决于平台查看媒体事件 了解有关在接收器中处理媒体事件的更多信息。
  • 在配置接收方网站的 HTTPS 证书时,请务必包含 中间 CA 证书。请参阅 Qualsys SSL 测试页 验证:您网站的可信认证路径是否包含 CA 标记为“额外下载”的证书,那么可能无法在基于 Android 的设备上加载 平台。
  • Chromecast 在 720p 图形平面上显示接收器页面,其他 投放平台(包括 Android TV)可以显示最高 1080p 的页面。确保 接收器页面在不同分辨率下正常缩放。