All CastPlayer bugs I found and possiblie solutions
- Dominant language
- Java
- Stars
- 21.9k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
I work for some chromecast-ready apps and CastPlayer make it a lot of easier but I found a lot of troubles with it too:
**1. Wrong getCurrentWindowIndex after setting media sources when CastPlayer is connected to Chromecast device.**
There is use case where you connect to your chromecast device and after that you select media source.
How to recreate:
- connect to Chromecast device by tapping MediaRouteButton button
- create CastPlayer and set sources (castPlayer.loadItems(mediaItems, window, time, Player.REPEAT_MODE_OFF)) after some time (you can do it with some button)
- get currentWindowIndex (it's always 0)
Cause:
StatusListener don't invoke onSessionStarted which don't invoke setRemoteMediaClient when we set new sources so statusListener is no added to remoteMediaClient.
Solution:
Add statusListener to remoteMediaClient in contructor:
```java
if (remoteMediaClient != null) {
try {
remoteMediaClient.addListener(statusListener);
remoteMediaClient.addProgressListener(statusListener, PROGRESS_REPORT_PERIOD_MS);
updateInternalState();
} catch (NullPointerException ignored) {
}
}
```
**2. I get 0 from getCurrentWindowIndex() which is not true.**
How to recreate:
- invoke getCurrentWindowIndex() in onPositionDiscontinuity
Cause:
We get the value from fetchCurrentWindowIndex() when there is no media session. So current window is not actually 0.
Solution:
Change 0 to other value in fetchCurrentWindowIndex() when there is no media session. You will be able to recognize the real current window index from "no media session":
```java
/**
* Retrieves the current item index from {@code mediaStatus} and maps it into a window index. If
* there is no media session, returns -1.
*/
private static int fetchCurrentWindowIndex(@Nullable MediaStatus mediaStatus) {
Integer currentItemId = mediaStatus != null
? mediaStatus.getIndexById(mediaStatus.getCurrentItemId()) : null;
return currentItemId != null ? currentItemId : -1;
}
```
You should change getDuration and some other methods (isCurrentWindowDynamic(), isCurrentWindowSeekable()) in this case too to avoid some exceptions:
```java
@Override
public long getDuration() {
return currentTimeline.isEmpty() ? C.TIME_UNSET
: currentTimeline.getWindow(getCurrentWindowIndex() < 0 ? 0 : getCurrentWindowIndex(),
window).getDurationMs();
}
```
**3. ArrayIndexOutOfBoundsException: length=2; index=2 when setting new media sources and some other problems with wrong current position.**
How to recreate:
- create a pleyer with 3 sources
- seekTo 3'rd sources
- loadItems() with 2 sources
Cause:
The getCurrentWindowIndex() returns old value for some time.
Solution:
Update currentWindowIndex and pendingSeekWindowIndex values in loadItem and loadItems:
```java
/**
* Loads a single item media queue. If no session is available, does nothing.
*
* @param item The item to load.
* @param positionMs The position at which the playback should start in milliseconds relative to
* the start of the item at {@code startIndex}. If {@link C#TIME_UNSET} is passed, playback
* starts at position 0.
* @return The Cast {@code PendingResult}, or null if no session is available.
*/
public PendingResult loadItem(MediaQueueItem item, long positionMs) {
pendingSeekWindowIndex = 0;
currentWindowIndex = 0;
return loadItems(new MediaQueueItem[]{item}, 0, positionMs, REPEAT_MODE_OFF);
}
/**
* Loads a media queue. If no session is available, does nothing.
*
* @param items The items to load.
* @param startIndex The index of the item at which playback should start.
* @param positionMs The position at which the playback should start in milliseconds relative to
* the start of the item at {@code startIndex}. If {@link C#TIME_UNSET} is passed, playback
* starts at position 0.
* @param repeatMode The repeat mode for the created media queue.
* @return The Cast {@code PendingResult}, or null if no session is available.
*/
public PendingResult loadItems(MediaQueueItem[] items, int startIndex,
long positionMs, @RepeatMode int repeatMode) {
if (remoteMediaClient != null) {
positionMs = positionMs != C.TIME_UNSET ? positionMs : 0;
waitingForInitialTimeline = true;
pendingSeekWindowIndex = startIndex;
currentWindowIndex = startIndex;
return remoteMediaClient.queueLoad(items, startIndex, getCastRepeatMode(repeatMode),
positionMs, null);
}
return null;
}
```
**4. There is no indicator to get to know that the media sources are finished.**
[https://github.com/google/ExoPlayer/issues/4130](https://github.com/google/ExoPlayer/issues/4130)
I have no solution for now.
Hope it is helpful :) If you need some more info (videos with examples or something like that) let me know.
I will do pull request soon.
Contributor guide
Assessment
This issue has not been assessed yet.