排队

Cast 框架提供了队列类,这些类支持创建 MediaQueueItem 实例列表,这些实例可由 MediaInfo 实例(例如视频或音频串流)构建,以便在接收器上按顺序播放。您可以修改、重新排序、更新此内容项队列,等等。

只要队列中至少有一项内容当前处于活动状态(正在播放或已暂停),接收器 SDK 就会维护队列并响应队列中的操作。发送者可以加入会话并向队列中添加内容。接收器会维护队列项的会话,直到最后一项完成播放、发送器停止播放并终止会话,或者发送器在接收器上加载新队列。默认情况下,接收器不会维护有关已终止队列的任何信息。队列中的最后一项内容播放完毕后,媒体会话即会结束,队列也会消失。

创建和加载媒体队列项

媒体队列项在 Cast 框架中表示为 MediaQueueItem 实例。创建媒体队列项时,如果您将媒体播放器库与自适应内容搭配使用,则可以设置预加载时间,以便播放器在队列中位于该项前面的项播放完毕之前开始缓冲该媒体队列项。将内容的 autoplay 属性设置为 true,即可让接收端自动播放该内容。例如,您可以使用构建器模式创建媒体队列项,如下所示:

Kotlin
val queueItem: MediaQueueItem = MediaQueueItem.Builder(mediaInfo)
    .setAutoplay(true)
    .setPreloadTime(20.0)
    .build()
Java
MediaQueueItem queueItem = new MediaQueueItem.Builder(mediaInfo)
  .setAutoplay(true)
  .setPreloadTime(20)
  .build();

使用 RemoteMediaClient 的相应 queueLoad 方法在队列中加载媒体队列项数组。

接收媒体队列状态更新

当接收器加载媒体队列项时,它会为该项分配一个唯一 ID,该 ID 会在会话期间(以及队列的生命周期内)保持不变。您的应用可以了解队列的状态,包括当前加载(可能未播放)、正在加载或预加载的内容。MediaStatus 类可提供以下状态信息:

  • getPreloadedItemId() 方法 - 如果下一项已预加载,则返回预加载的商品 ID。
  • getLoadingItemId() 方法 - 返回接收器上当前正在加载(但未在队列中处于活动状态)的商品的商品 ID。
  • getCurrentItemId() 方法 - 返回媒体状态发生变化时队列中处于活动状态(可能未在播放)的项的项 ID。
  • getQueueItems()(已弃用,请改用 MediaQueue)方法 - 以不可修改的列表形式返回 MediaQueueItem 实例列表。

您的应用还可以使用 MediaQueue 类获取商品列表。该类是媒体队列的稀疏数据模型。它会将商品 ID 列表保留在队列中,该队列会自动与接收器同步。 MediaQueue 不会保留所有 MediaQueueItem,因为当队列很长时,这会占用过多内存。而是按需提取内容,并保留最近访问内容的 LruCache。您可以使用以下方法访问媒体队列:

  • getItemIds() 方法 - 按顺序返回所有商品 ID 的列表。
  • getItemAtIndex() 方法 - 返回指定索引处的缓存项。如果内容未缓存,MediaQueue 将返回 null 并安排提取该内容。提取内容后,系统会调用 MediaQueue.Callback#itemsUpdatedAtIndexes(),再次使用同一 ID 调用 getItemAtIndex() 将返回该内容。
  • 当用户将队列界面滚动到顶部或底部,并且您的应用想要从云端提取更多内容时,系统会使用 fetchMoteItemsRelativeToIndex()。

将这些方法与其他媒体状态方法结合使用,可让您的应用了解队列和队列中内容的状态。除了接收器发出的媒体状态更新之外,您的应用还可以通过实现 RemoteMediaClient.Callback 和 MediaQueue.Callback 来监听队列的变化。

此外,Cast SDK 还提供了两个实用程序类,用于创建队列界面。

例如,如需使用 MediaQueueRecyclerViewAdapter 创建 RecyclerView,请运行以下命令:

Kotlin
class MyRecyclerViewAdapter(mediaQueue: MediaQueue?) :
    MediaQueueRecyclerViewAdapter<MyViewHolder?>(mediaQueue) {
    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val item = getItem(position)

        // Update the view using `item`.
        ...
    }
}

class MyViewHolder : RecyclerView.ViewHolder {
    // Implement your own ViewHolder.
    ...
}

fun someMethod() {
    val adapter = MyRecyclerViewAdapter(
        mCastSession.remoteMediaClient.getMediaQueue())
    val recyclerView =
        activity.findViewById(R.id.my_recycler_view_id) as RecyclerView
    recyclerView.adapter = adapter
}
Java
public class MyRecyclerViewAdapter extends MediaQueueRecyclerViewAdapter<MyViewHolder> {
    public MyRecyclerViewAdapter(MediaQueue mediaQueue) {
        super(mediaQueue);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
      MediaQueueItem item = getItem(position);

      // Update the view using `item`.
      ...
    }
}

public class MyViewHolder implements RecyclerView.ViewHolder {
  // Implement your own ViewHolder.
  ...
}

public void someMethod() {
    RecyclerView.Adapter adapter = new MyRecyclerViewAdapter(
        mCastSession.getRemoteMediaClient().getMediaQueue());
    RecyclerView recyclerView =
        (RecyclerView) getActivity().findViewById(R.id.my_recycler_view_id);
    recyclerView.setAdapter(adapter);
}

修改队列

如需对队列中的项执行操作,请使用 RemoteMediaClient 类的队列方法。这些方法可让您将一组内容加载到新队列中、将内容插入现有队列中、更新队列中内容的属性、使内容在队列中向前或向后跳转、设置队列本身的属性(例如,更改选择下一个内容的 repeatMode 算法)、从队列中移除内容,以及对队列中的内容重新排序。