ExoPlayer 2 播放列表监听器
ExoPlayer 2 Playlist Listener
我正在使用 ExoPlayer 2.x 的新功能来播放这样的音频文件列表:
List<MediaSource> playlist = new ArrayList<>();
...
ConcatenatingMediaSource concatenatedSource = new ConcatenatingMediaSource(
playlist.toArray(new MediaSource[playlist.size()]));
mExoPlayer.prepare(concatenatedSource);
mExoPlayer.setPlayWhenReady(true);
这工作正常,但为了相应地更新我的 UI,我需要知道当前正在播放哪个曲目以及该曲目的进度。有ExoPlayer的听众吗?
谢谢!
您可以执行以下事件并根据玩家的状态更新您的ui。
mExoPlayer.addListener(new ExoPlayer.Listener() {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == PlaybackStateCompat.STATE_PLAYING) {
//do something
}
}
@Override
public void onPlayWhenReadyCommitted() {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
mExoPlayer.stop();
}
});
所以我遇到了类似的情况,需要知道播放列表中的下一个视频何时开始播放。我发现 ExoPlayer.EventListener
有一个名为 onPositionDiscontinuity()
的方法,每当视频更改或播放列表中的下一个 "seeks" 时都会调用该方法。
我没有广泛使用过这种方法,但据我目前所见,这是您应该关注的方法。触发该方法时不会传递任何参数,因此您必须保留某种计数器或队列以跟踪在任何给定时刻正在播放的内容。
希望这对您有所帮助!
编辑: Exoplayer.getCurrentWindowIndex()
返回的索引变化是 recommended way 以检测播放列表 MediaSource
中的项目变化。
int lastWindowIndex = 0; // global var in your class encapsulating exoplayer obj (Activity, etc.)
exoPlayer.addListener(new ExoPlayer.EventListener() {
@Override
public void onLoadingChanged(boolean isLoading) {
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
}
@Override
public void onPositionDiscontinuity() {
//THIS METHOD GETS CALLED FOR EVERY NEW SOURCE THAT IS PLAYED
int latestWindowIndex = exoPlayer.getCurrentWindowIndex();
if (latestWindowIndex != lastWindowIndex) {
// item selected in playlist has changed, handle here
lastWindowIndex = latestWindowIndex;
// ...
}
}
});
由于这里的答案对我不起作用,我将在 Kotlin 中添加我的工作解决方案。
还有很多方法从那时起就被弃用了。
您可以在创建播放列表时通过设置 mediaId 来跟踪当前曲目(视频)
Gradle:
implementation 'com.google.android.exoplayer:exoplayer:2.14.1'
布局xml:
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/player_view"
android:layout_width="match_parent"
android:layout_height="100dp"
app:show_buffering="when_playing"/>
代码:
private lateinit var exoPlayer: SimpleExoPlayer
private lateinit var playerView: PlayerView
private lateinit var fileList: List<FileModel>
private fun initPlayer() {
playerView = findViewById(R.id.player_view)
playerView.controllerShowTimeoutMs = 0
playerView.cameraDistance = 30F
exoPlayer = SimpleExoPlayer.Builder(this).build()
playerView.player = exoPlayer
setPlaylist()
exoPlayer.prepare()
exoPlayer.seekTo(position, C.TIME_UNSET) // position = current song or video
exoPlayer.playWhenReady = true
addPlayerListeners()
}
private fun setPlaylist() {
for ((pos, file) in fileList.withIndex()) {
val mediaItem = MediaItem.Builder().setUri(file.url).setMediaId(pos.toString()).build()
exoPlayer.addMediaItem(mediaItem)
}
}
private fun addPlayerListeners() {
exoPlayer.addListener(object : Player.Listener{
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
super.onMediaItemTransition(mediaItem, reason)
val item = mediaItem?.mediaMetadata
val bmp = item?.artworkData
Log.i(TAG, "position = ${mediaItem?.mediaId}")
val currentPos = mediaItem?.mediaId
updateViews(currentPos, bmp)
}
})
}
private fun updateViews(currentPos: String?, bmp: ByteArray?) {
position = currentPos?.toInt() ?: 0
val title = fileList[position].title
textview_title.text = title
if (bmp == null) {
image_view.setImageResource(R.drawable.exo_ic_default_album_image)
return
}
val bitmap = BitmapFactory.decodeByteArray(bmp, 0, bmp.size)
image_view.setImageBitmap(bitmap)
}
我正在使用 ExoPlayer 2.x 的新功能来播放这样的音频文件列表:
List<MediaSource> playlist = new ArrayList<>();
...
ConcatenatingMediaSource concatenatedSource = new ConcatenatingMediaSource(
playlist.toArray(new MediaSource[playlist.size()]));
mExoPlayer.prepare(concatenatedSource);
mExoPlayer.setPlayWhenReady(true);
这工作正常,但为了相应地更新我的 UI,我需要知道当前正在播放哪个曲目以及该曲目的进度。有ExoPlayer的听众吗?
谢谢!
您可以执行以下事件并根据玩家的状态更新您的ui。
mExoPlayer.addListener(new ExoPlayer.Listener() {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == PlaybackStateCompat.STATE_PLAYING) {
//do something
}
}
@Override
public void onPlayWhenReadyCommitted() {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
mExoPlayer.stop();
}
});
所以我遇到了类似的情况,需要知道播放列表中的下一个视频何时开始播放。我发现 ExoPlayer.EventListener
有一个名为 onPositionDiscontinuity()
的方法,每当视频更改或播放列表中的下一个 "seeks" 时都会调用该方法。
我没有广泛使用过这种方法,但据我目前所见,这是您应该关注的方法。触发该方法时不会传递任何参数,因此您必须保留某种计数器或队列以跟踪在任何给定时刻正在播放的内容。
希望这对您有所帮助!
编辑: Exoplayer.getCurrentWindowIndex()
返回的索引变化是 recommended way 以检测播放列表 MediaSource
中的项目变化。
int lastWindowIndex = 0; // global var in your class encapsulating exoplayer obj (Activity, etc.)
exoPlayer.addListener(new ExoPlayer.EventListener() {
@Override
public void onLoadingChanged(boolean isLoading) {
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
}
@Override
public void onPositionDiscontinuity() {
//THIS METHOD GETS CALLED FOR EVERY NEW SOURCE THAT IS PLAYED
int latestWindowIndex = exoPlayer.getCurrentWindowIndex();
if (latestWindowIndex != lastWindowIndex) {
// item selected in playlist has changed, handle here
lastWindowIndex = latestWindowIndex;
// ...
}
}
});
由于这里的答案对我不起作用,我将在 Kotlin 中添加我的工作解决方案。 还有很多方法从那时起就被弃用了。
您可以在创建播放列表时通过设置 mediaId 来跟踪当前曲目(视频)
Gradle:
implementation 'com.google.android.exoplayer:exoplayer:2.14.1'
布局xml:
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/player_view"
android:layout_width="match_parent"
android:layout_height="100dp"
app:show_buffering="when_playing"/>
代码:
private lateinit var exoPlayer: SimpleExoPlayer
private lateinit var playerView: PlayerView
private lateinit var fileList: List<FileModel>
private fun initPlayer() {
playerView = findViewById(R.id.player_view)
playerView.controllerShowTimeoutMs = 0
playerView.cameraDistance = 30F
exoPlayer = SimpleExoPlayer.Builder(this).build()
playerView.player = exoPlayer
setPlaylist()
exoPlayer.prepare()
exoPlayer.seekTo(position, C.TIME_UNSET) // position = current song or video
exoPlayer.playWhenReady = true
addPlayerListeners()
}
private fun setPlaylist() {
for ((pos, file) in fileList.withIndex()) {
val mediaItem = MediaItem.Builder().setUri(file.url).setMediaId(pos.toString()).build()
exoPlayer.addMediaItem(mediaItem)
}
}
private fun addPlayerListeners() {
exoPlayer.addListener(object : Player.Listener{
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
super.onMediaItemTransition(mediaItem, reason)
val item = mediaItem?.mediaMetadata
val bmp = item?.artworkData
Log.i(TAG, "position = ${mediaItem?.mediaId}")
val currentPos = mediaItem?.mediaId
updateViews(currentPos, bmp)
}
})
}
private fun updateViews(currentPos: String?, bmp: ByteArray?) {
position = currentPos?.toInt() ?: 0
val title = fileList[position].title
textview_title.text = title
if (bmp == null) {
image_view.setImageResource(R.drawable.exo_ic_default_album_image)
return
}
val bitmap = BitmapFactory.decodeByteArray(bmp, 0, bmp.size)
image_view.setImageBitmap(bitmap)
}