推动历史发展的不是法律,而是金钱. —— JP摩根
1. 应用场景
视频播放要循环播放,另外要在视频第一遍播放结束时出现某种提示。
循环播放:我们可以通过设置setRepeatMode() 进行设置。另外在Player.EventListener的onPlaybackStateChanged(int state) 对播放过程进行监听。
具体过程如下:
public void onPlaybackStateChanged(int state) {
Log.d(TAG, "onPlaybackStateChanged 播放状态:" + state);
switch (state) {
case Player.STATE_READY:
Log.d(TAG, "加载就绪,可以播放");
...
break;
case Player.STATE_BUFFERING:
Log.d(TAG, "缓冲中...");
...
break;
case Player.STATE_ENDED:
Log.d(TAG, "播放结束...");
...
break;
case Player.STATE_IDLE:
...
break;
}
}
一切看起来都是那么的完美…
2. 问题
重点来袭:Player.STATE_ENDED 在开启循环模式下是不会被触发的。
静下来想一下,不难理解,这个状态:表示播放器结束播放媒体。(PS: 循环模式当然是不会结束的啦…)
难道我们只能采取QAQ的方式(关闭循环模式然后在播放结束的时候重新播放…)。如果是这样做的话,费时费力暂且不谈,那还需要我在这里BB,那人生还有什么意趣儿?
3. 解决方案
public void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) {
if(reason == DISCONTINUITY_REASON_PERIOD_TRANSITION){
// TODO...
}
}
请自行翻译:
/**
* Automatic playback transition from one period in the timeline to the next. The period index may
* be the same as it was before the discontinuity in case the current period is repeated.
*/
int DISCONTINUITY_REASON_PERIOD_TRANSITION = 0;
4. 原理
其本质跟QAQ方案是有着异曲同工之妙。
根据timeline(时间轴)的变化,来调用onPositionDiscontinuity()。【PS: 循环播放他也是 0 ----> 终点 ,0 ----> 终点,…进行循环的】
没什么好解释的,请直接看代码注释:
/**
* Listener of changes in player state. All methods have no-op default implementations to allow
* selective overrides.
*/
interface EventListener {
/**
* Called when the timeline has been refreshed.
*
* <p>Note that if the timeline has changed then a position discontinuity may also have
* occurred. For example, the current period index may have changed as a result of periods being
* added or removed from the timeline. This will <em>not</em> be reported via a separate call to
* {@link #onPositionDiscontinuity(int)}.
*
* @param timeline The latest timeline. Never null, but may be empty.
* @param reason The {@link TimelineChangeReason} responsible for this timeline change.
*/
@SuppressWarnings("deprecation")
default void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) {
Object manifest = null;
if (timeline.getWindowCount() == 1) {
// Legacy behavior was to report the manifest for single window timelines only.
Timeline.Window window = new Timeline.Window();
manifest = timeline.getWindow(0, window).manifest;
}
// Call deprecated version.
onTimelineChanged(timeline, manifest, reason);
}
...
}
附上参考链接:ExoPlayer STATE_ENDED not called after song is finished
最后废话一句,对ExoPlayer不了解的朋友,可以参考:ExoPlayer-Study点滴