ExoPlayer
ExoPlayer copied to clipboard
Caused by org.json.JSONException: No value for mediaItem when casting (Chromecast)
ExoPlayer Version
2.18.1
Devices that reproduce the issue
All Android devices
Devices that do not reproduce the issue
No response
Reproducible in the demo app?
Not tested
Reproduction steps
When casting the video to Chromecast, mediaitem
is getting null and getting JSONException. It is working fine in 2.15.1 version. I am using exoplayer with exoplayer:extension-cast
private val castPlayer = CastPlayer(castContext)
val mediaInfo = MediaInfo.Builder(streamItem.streamUrl)
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setMetadata(createMetadata(streamItem)).setCustomData(customJson)
.build()
mediaClient.load(
MediaLoadRequestData.Builder()
.setMediaInfo(mediaInfo)
.setAutoplay(true)
.setCurrentTime(startPosition)
.build()
)
Expected result
With normal exoplayer video is playing, also I am able to connect Chromecast device
Actual result
Caused by org.json.JSONException: No value for mediaItem at org.json.JSONObject.get(JSONObject.java:400) at org.json.JSONObject.getJSONObject(JSONObject.java:620) at com.google.android.exoplayer2.ext.cast.DefaultMediaItemConverter.getMediaItem(DefaultMediaItemConverter.java:148) at com.google.android.exoplayer2.ext.cast.DefaultMediaItemConverter.toMediaItem(DefaultMediaItemConverter.java:85) at com.google.android.exoplayer2.ext.cast.CastTimelineTracker.getCastTimeline(CastTimelineTracker.java:129) at com.google.android.exoplayer2.ext.cast.CastPlayer.updateTimeline(CastPlayer.java:982) at com.google.android.exoplayer2.ext.cast.CastPlayer.updateTimelineAndNotifyIfChanged(CastPlayer.java:907) at com.google.android.exoplayer2.ext.cast.CastPlayer.updateInternalStateAndNotifyIfChanged(CastPlayer.java:783) at com.google.android.exoplayer2.ext.cast.CastPlayer.access$800(CastPlayer.java:81) at com.google.android.exoplayer2.ext.cast.CastPlayer$StatusListener.onStatusUpdated(CastPlayer.java:1319) at com.google.android.gms.cast.framework.media.zzbo.zzm(com.google.android.gms:play-services-cast-framework@@20.1.0:6) at com.google.android.gms.cast.internal.zzap.zzaa(com.google.android.gms:play-services-cast@@20.1.0:1) at com.google.android.gms.cast.internal.zzap.zzQ(com.google.android.gms:play-services-cast@@20.1.0:63) at com.google.android.gms.cast.framework.media.RemoteMediaClient.onMessageReceived(com.google.android.gms:play-services-cast-framework@@20.1.0:1) at com.google.android.gms.cast.zzbn.run(com.google.android.gms:play-services-cast@@20.1.0:4) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:250) at android.app.ActivityThread.main(ActivityThread.java:7877) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)
Media
![image](https://user-images.githubusercontent.com/70998600/188856269-367cf8a8-9993-4577-97ca-7a05dbed8b53.png)
Bug Report
- [X] You will email the zip file produced by
adb bugreport
to [email protected] after filing this issue.
If the DefaultMediaItemConverter
is sending a MediaItemQueueItem
to the cast device it includes the data of the MediaItem
in a JSON document that is stored as the custom data.
In the case that generated the stack trace from above the mediaItem
in the map is null like you mention. So it tries to read from the custom JSON data that is not available.
I wonder a) why the media item is null in this case and b) why there isn't such a JSON in the media item that should have been created by us.
Did you override DefaultMediaItemConverter.toMediaQueueItem
?
Probably not. So I'm trying to understand in which situation CastPlayer
ends up in this invalid state:
Do you know at which moment this happens? Are you trying to connect to a Cast device that is already playing? Like with a second Android device that reads the queue that has been added to the cast device by another Android device running your app? Or is this after you restart/redeploy your app and the cast device has still the queue loaded from the previous app instance that was running?
I think we would want to support either cases, so something is not working as expected. So I'm trying to repro this behaviour. Can you give me some more information when in the application life-cycle and in what situation this happens?
You are correct that this has been introduced by 2.18.x. We didn't read the JSON from the session custom data before.
I am not overriding DefaultMediaItemConverter.toMediaQueueItem
.
Just passing castContext
to CastPlayer
The Chromecast was already connected and just trying to play the video in the Casting device. The video is playing in the TV and the app got crashed with this Exception.
I have checked remoteMediaClient
for the CastSession
mediaInfo
and currentItem
are null here. Our video format is DASH.
val mediaClient = castContext.sessionManager.currentCastSession?.remoteMediaClient
mediaClient?.let {
val sameItemPlaying = (it.isPlaying && it.mediaInfo?.contentId == streamItem.streamUrl)
if (sameItemPlaying) {
listenersHandler.sendPlayerStateEvent( Player.STATE_READY)
} else {
startPlayback(it, streamItem, startPosition)
}
}
i have same Problem, when i create json object by myself and add to media item it works:
JSONObject jsonObject = new JSONObject();
try {
JSONObject mediaItem = new JSONObject();
mediaItem.put("uri", channelUrl);
mediaItem.put("mediaId", tvgId);
jsonObject.put("mediaItem", mediaItem);
} catch (JSONException e) {
e.printStackTrace();
}
MediaInfo.Builder mediaInfoBuilder = new MediaInfo.Builder(channelUrl);
mediaInfoBuilder.setStreamType(MediaInfo.STREAM_TYPE_LIVE);
mediaInfoBuilder.setCustomData(jsonObject);
mediaInfoBuilder.setContentType(mimeType);
mediaInfoBuilder.setStreamDuration(castPlayer.getDuration() * 1000);
mediaInfoBuilder.setMetadata(metadata);
MediaInfo mediaInfo = mediaInfoBuilder.build();
RemoteMediaClient remoteMediaClient = castContext.getSessionManager().getCurrentCastSession().getRemoteMediaClient();
remoteMediaClient.load(new MediaLoadRequestData.Builder().setCustomData(jsonObject).setMediaInfo(mediaInfo).build());
I'm experiencing this problem, but I'm seeing this issue only when adding items to a queue, and with r2.17.1. (Same outcome, same failure in DefaultMediaItemConverter.getMediaItem
parsing the JSONObject at line 145 of the 2.17.1 version of that class). Considering the difference in ExoPlayer versions, I'm not sure whether I've come across a different issue entirely, or a different way to make this issue happen.
In our case, we are configuring the queuing like this:
The goal is to call castPlayer.addMediaItems(List<MediaItem>)
In order to do that:
2. Add items to be queued to a List<MediaQueueItem>
3. Convert each MediaQueueItem
in this List<MediaQueueItem>
to a MediaItem
, using DefaultMediaItemConverter.toMediaItem(MediaQueueItem)
- the failure occurs here:
java.lang.RuntimeException: org.json.JSONException: No value for mediaItem
at com.google.android.exoplayer2.ext.cast.DefaultMediaItemConverter.getMediaItem(DefaultMediaItemConverter.java:159)
at com.google.android.exoplayer2.ext.cast.DefaultMediaItemConverter.toMediaItem(DefaultMediaItemConverter.java:85)
at com.brightcove.cast.GoogleCastComponent.convertMediaQueueItemToMediaItem(GoogleCastComponent.java:656)
I'm going to give @koshisinthehouse 's approach a try to see if that provides a workaround to my circumstance.
I'm going to give @koshisinthehouse 's approach a try to see if that provides a workaround to my circumstance.
Turns out that our Cast receiver app does not have support for queueing, however I was able to try @koshisinthehouse 's approach, and it worked, as far as sending a mediaItem to the receiver (which ultimately ignored it).