Queueing
Stay organized with collections
Save and categorize content based on your preferences.
The queue model in Cast is different from that in MediaSession
.
The Cast Connect library doesn't support reading a queue provided by MediaSession
.
Queue loading is done in the same way as loading single items (via starting
activity with an intent). You need to use our client library to parse the intent
into a MediaLoadRequestData
.
The MediaQueueData
field contains the queue information to be loaded.
fun
handleCastLoad
(
requestData
:
MediaLoadRequestData?)
{
if
(
requestData
.
getQueueData
())
{
// If MediaQueueData is specified, this is a queue load request.
myPlayer
.
load
(
requestData
.
getQueueData
().
getItems
().
get
(
0
))
// Set media status.
castReceiverContext
.
getMediaManager
()
.
setDataFromLoad
(
requestData
)
// This clears all status overrides.
// The queue information is updated with
// the MediaQueueData in the request.
...
mediaSession
.
setPlaybackState
(...)
}
}
private
void
handleCastLoad
(
MediaLoadRequestData
requestData
)
{
if
(
requestData
.
getQueueData
())
{
//
If
MediaQueueData
is
specified
,
this
is
a
queue
load
request
.
myPlayer
.
load
(
requestData
.
getQueueData
()
.
getItems
()
.
get
(
0
));
//
Set
media
status
.
castReceiverContext
.
getMediaManager
()
.
setDataFromLoad
(
requestData
)
//
This
clears
all
status
overrides
.
//
The
queue
information
is
updated
with
//
the
MediaQueueData
in
the
request
.
...
;
mediaSession
.
setPlaybackState
(
...
);
}
}
Changing the Queue
When there are changes to the queue (such as from queueInsert()
), you can use MediaQueueManager
to update the queue. If you are creating new queue items, be sure to set the
item ID by calling setItemId()
on the builder using MediaQueueManager.autoGenerateItemId()
to generate the item ID. Items in the queue loaded via setDataFromLoad()
already have their item IDs set.
val
mediaManager
:
MediaManager
=
castReceiverContext
.
getMediaManager
()
val
mediaQueueManager
=
mediaManager
.
getMediaQueueManager
()
mediaQueueManager
.
getQueueItems
().
add
(
/* position= */
index
,
mediaQueueItem
)
mediaManager
.
broadcastMediaStatus
()
MediaManager mediaManager = castReceiverContext.getMediaManager();
MediaQueueManager mediaQueueManager = mediaManager.getMediaQueueManager();
mediaQueueManager.getQueueItems().add(/* position= */ index, mediaQueueItem);
mediaManager.broadcastMediaStatus();
Android TV apps also handle the onQueueUpdate()
callback to support jumping to queue items and skip next/previous:
class
MyMediaCommandCallback
:
MediaCommandCallback
()
{
override
fun
onQueueUpdate
(
queueUpdateRequestData
:
QueueUpdateRequestData
):
Task
{
...
var
newItemId
=
MediaQueueItem
.
INVALID_ITEM_ID
if
(
queueUpdateRequestData
.
getJump
()
!=
null
)
{
newItemId
=
myGetRelativeItemId
(
queueUpdateRequestData
.
getJump
())
}
else
if
(
queueUpdateRequestData
.
getCurrentItemId
()
!=
null
)
{
newItemId
=
queueUpdateRequestData
.
getCurrentItemId
()
}
if
(
newItemId
!=
MediaQueueItem
.
INVALID_ITEM_ID
)
{
castReceiverContext
.
getMediaManager
().
getMediaQueueManager
()
.
setCurrentItemId
(
newItemId
)
castReceiverContext
.
getMediaManager
().
broadcastMediaStatus
()
}
}
}
val
mediaManager
=
CastReceiverContext
.
getInstance
().
getMediaQueueManager
()
mediaManager
.
setMediaCommandCallback
(
MyMediaCommandCallback
())
public
class
MyMediaCommandCallback
extends
MediaCommandCallback
{
@
Override
public
Task
onQueueUpdate
(
QueueUpdateRequestData
queueUpdateRequestData
)
{
...
int
newItemId
=
MediaQueueItem
.
INVALID_ITEM_ID
;
if
(
queueUpdateRequestData
.
getJump
()
!=
null
)
{
newItemId
=
myGetRelativeItemId
(
queueUpdateRequestData
.
getJump
());
}
else
if
(
queueUpdateRequestData
.
getCurrentItemId
()
!=
null
)
{
newItemId
=
queueUpdateRequestData
.
getCurrentItemId
();
}
if
(
newItemId
!=
MediaQueueItem
.
INVALID_ITEM_ID
)
{
castReceiverContext
.
getMediaManager
()
.
getMediaQueueManager
()
.
setCurrentItemId
(
newItemId
);
castReceiverContext
.
getMediaManager
()
.
broadcastMediaStatus
();
}
}
MediaManager
mediaManager
=
CastReceiverContext
.
getInstance
()
.
getMediaManager
();
mediaManager
.
setMediaCommandCallback
(
new
MyMediaCommandCallback
());
You may also want to implement queue-related transport control callbacks, such
as onSkipToNext()
, onSkipToPrevious()
,
or onSkipToQueueItem()
.
class
MyMediaSessionCallback
:
MediaSessionCompat
.
Callback
()
{
override
fun
onSkipToNext
()
{
// Skip to next item in queue
...
}
override
fun
onSkipToPrevious
()
{
// Skip to previous item in queue
...
}
override
fun
onSkipToQueueItem
(
pos
:
Long
)
{
// Skip to specified queue item
...
}
...
}
mediaSession
.
setCallback
(
MyMediaSessionCallback
())
public
class
MyMediaSessionCallback
extends
MediaSessionCompat
.
Callback
{
@
Override
public
void
onSkipToNext
()
{
//
Skip
to
next
item
in
queue
...
}
@
Override
public
void
onSkipToPrevious
()
{
//
Skip
to
previous
item
in
queue
...
}
@
Override
public
void
onSkipToQueueItem
(
long
pos
)
{
//
Skip
to
specified
queue
item
...
}
...
}
mediaSession
.
setCallback
(
new
MyMediaSessionCallback
());
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License
, and code samples are licensed under the Apache 2.0 License
. For details, see the Google Developers Site Policies
. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-09-04 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-04 UTC."],[[["\u003cp\u003eThe Cast queue model differs from the \u003ccode\u003eMediaSession\u003c/code\u003e model and doesn't support reading its queue.\u003c/p\u003e\n"],["\u003cp\u003eQueue loading in Cast involves parsing intents into \u003ccode\u003eMediaLoadRequestData\u003c/code\u003e and utilizing \u003ccode\u003eMediaQueueData\u003c/code\u003e for queue information.\u003c/p\u003e\n"],["\u003cp\u003eQueue modifications are handled using \u003ccode\u003eMediaQueueManager\u003c/code\u003e which allows for adding, updating, and broadcasting changes.\u003c/p\u003e\n"],["\u003cp\u003eAndroid TV apps should implement the \u003ccode\u003eonQueueUpdate()\u003c/code\u003e callback to manage queue navigation and jumps.\u003c/p\u003e\n"],["\u003cp\u003eQueue-related transport controls like \u003ccode\u003eonSkipToNext()\u003c/code\u003e, \u003ccode\u003eonSkipToPrevious()\u003c/code\u003e, and \u003ccode\u003eonSkipToQueueItem()\u003c/code\u003e should be implemented in a \u003ccode\u003eMediaSessionCompat.Callback\u003c/code\u003e.\u003c/p\u003e\n"]]],["Cast uses a distinct queue model compared to `MediaSession`, not supporting direct queue reading from it. Queue loading utilizes `MediaLoadRequestData`, where `MediaQueueData` contains queue details. Use `setDataFromLoad()` to update status and queue information. Queue changes are managed via `MediaQueueManager`, using `setItemId()` and `autoGenerateItemId()` for new items. Android TV apps use `onQueueUpdate()` for queue navigation and implement `onSkipToNext()`, `onSkipToPrevious()`, and `onSkipToQueueItem()` for transport control.\n"],null,["# Queueing\n\nThe queue model in Cast is different from that in\n[`MediaSession`](https://developer.android.com/reference/kotlin/android/support/v4/media/session/MediaSessionCompat).\nThe Cast Connect library doesn't support reading a queue provided by\n`MediaSession`.\n\nHandle Queue Loading and Setting the Queue Information\n------------------------------------------------------\n\nQueue loading is done in the same way as loading single items (via starting\nactivity with an intent). You need to use our client library to parse the intent\ninto a\n[`MediaLoadRequestData`](/android/reference/com/google/android/gms/cast/MediaLoadRequestData).\nThe\n[`MediaQueueData`](/android/reference/com/google/android/gms/cast/MediaQueueData)\nfield contains the queue information to be loaded.\nKotlin \n\n```kotlin\nfun handleCastLoad(requestData: MediaLoadRequestData?) {\n if (requestData.getQueueData()) {\n // If MediaQueueData is specified, this is a queue load request.\n myPlayer.load(\n requestData.getQueueData().getItems().get(0))\n\n // Set media status.\n castReceiverContext.getMediaManager()\n .setDataFromLoad(requestData) // This clears all status overrides.\n // The queue information is updated with\n // the MediaQueueData in the request.\n ...\n\n mediaSession.setPlaybackState(...)\n }\n}\n```\nJava \n\n```gdscript\nprivate void handleCastLoad(MediaLoadRequestData requestData) {\n if (requestData.getQueueData()) {\n // If MediaQueueData is specified, this is a queue load request.\n myPlayer.load(\n requestData.getQueueData().getItems().get(0));\n\n // Set media status.\n castReceiverContext.getMediaManager()\n .setDataFromLoad(requestData) // This clears all status overrides.\n // The queue information is updated with\n // the MediaQueueData in the request.\n ...;\n\n mediaSession.setPlaybackState(...);\n }\n}\n```\n\nChanging the Queue\n------------------\n\nWhen there are changes to the queue (such as from `queueInsert()`), you can use\n[`MediaQueueManager`](/android/reference/com/google/android/gms/cast/tv/media/MediaQueueManager)\nto update the queue. If you are creating new queue items, be sure to set the\nitem ID by calling\n[`setItemId()`](/android/reference/com/google/android/gms/cast/tv/media/MediaQueueItemWriter#setItemId(int))\non the builder using\n[`MediaQueueManager.autoGenerateItemId()`](/android/reference/com/google/android/gms/cast/tv/media/MediaQueueManager#public-int-autogenerateitemid)\nto generate the item ID. Items in the queue loaded via\n[`setDataFromLoad()`](/android/reference/com/google/android/gms/cast/tv/media/MediaManager#setDataFromLoad(com.google.android.gms.cast.MediaLoadRequestData))\nalready have their item IDs set.\nKotlin \n\n```kotlin\nval mediaManager: MediaManager = castReceiverContext.getMediaManager()\n\nval mediaQueueManager = mediaManager.getMediaQueueManager()\n\nmediaQueueManager.getQueueItems().add( /* position= */index, mediaQueueItem)\n\nmediaManager.broadcastMediaStatus()\n```\nJava \n\n```scdoc\nMediaManager mediaManager = castReceiverContext.getMediaManager();\n\nMediaQueueManager mediaQueueManager = mediaManager.getMediaQueueManager();\n\nmediaQueueManager.getQueueItems().add(/* position= */ index, mediaQueueItem);\n\nmediaManager.broadcastMediaStatus();\n```\n\nAndroid TV apps also handle the\n[`onQueueUpdate()`](/android/reference/com/google/android/gms/cast/tv/media/MediaCommandCallback#onQueueUpdate(java.lang.String,%20com.google.android.gms.cast.tv.media.QueueUpdateRequestData))\ncallback to support jumping to queue items and skip next/previous:\nKotlin \n\n```kotlin\nclass MyMediaCommandCallback : MediaCommandCallback() {\n override fun onQueueUpdate(\n queueUpdateRequestData: QueueUpdateRequestData ): Task {\n ...\n var newItemId = MediaQueueItem.INVALID_ITEM_ID\n if (queueUpdateRequestData.getJump() != null) {\n newItemId = myGetRelativeItemId(queueUpdateRequestData.getJump())\n } else if (queueUpdateRequestData.getCurrentItemId() != null) {\n newItemId = queueUpdateRequestData.getCurrentItemId()\n }\n if (newItemId != MediaQueueItem.INVALID_ITEM_ID) {\n castReceiverContext.getMediaManager().getMediaQueueManager()\n .setCurrentItemId(newItemId)\n castReceiverContext.getMediaManager().broadcastMediaStatus()\n }\n }\n}\n\nval mediaManager = CastReceiverContext.getInstance().getMediaQueueManager()\nmediaManager.setMediaCommandCallback(MyMediaCommandCallback())\n```\nJava \n\n```gdscript\npublic class MyMediaCommandCallback extends MediaCommandCallback {\n @Override\n public Task onQueueUpdate(\n QueueUpdateRequestData queueUpdateRequestData) {\n ...\n int newItemId = MediaQueueItem.INVALID_ITEM_ID;\n if (queueUpdateRequestData.getJump() != null) {\n newItemId = myGetRelativeItemId(queueUpdateRequestData.getJump());\n } else if (queueUpdateRequestData.getCurrentItemId() != null) {\n newItemId = queueUpdateRequestData.getCurrentItemId();\n }\n\n if (newItemId != MediaQueueItem.INVALID_ITEM_ID) {\n castReceiverContext.getMediaManager().getMediaQueueManager()\n .setCurrentItemId(newItemId);\n castReceiverContext.getMediaManager().broadcastMediaStatus();\n }\n}\n\nMediaManager mediaManager =\n CastReceiverContext.getInstance().getMediaManager();\nmediaManager.setMediaCommandCallback(new MyMediaCommandCallback());\n```\n\nHandling Queue-related Transport Control\n----------------------------------------\n\nYou may also want to implement queue-related transport control callbacks, such\nas\n[`onSkipToNext()`](https://developer.android.com/reference/kotlin/android/support/v4/media/session/MediaSessionCompat.Callback#onSkipToNext()),\n[`onSkipToPrevious()`](https://developer.android.com/reference/kotlin/android/support/v4/media/session/MediaSessionCompat.Callback#onSkipToPrevious()),\nor\n[`onSkipToQueueItem()`](https://developer.android.com/reference/kotlin/android/support/v4/media/session/MediaSessionCompat.Callback#onSkipToNext()).\nKotlin \n\n```kotlin\nclass MyMediaSessionCallback : MediaSessionCompat.Callback() {\n override fun onSkipToNext() {\n // Skip to next item in queue\n ...\n }\n\n override fun onSkipToPrevious() {\n // Skip to previous item in queue\n ...\n }\n\n override fun onSkipToQueueItem(pos: Long) {\n // Skip to specified queue item\n ...\n }\n ...\n}\n\nmediaSession.setCallback(MyMediaSessionCallback())\n```\nJava \n\n```gdscript\npublic class MyMediaSessionCallback extends MediaSessionCompat.Callback {\n @Override\n public void onSkipToNext() {\n // Skip to next item in queue\n ...\n }\n\n @Override\n public void onSkipToPrevious() {\n // Skip to previous item in queue\n ...\n }\n\n @Override\n public void onSkipToQueueItem (long pos) {\n // Skip to specified queue item\n ...\n }\n ...\n}\n\nmediaSession.setCallback(new MyMediaSessionCallback());\n```"]]