在 ExoPlayer 中检测暂停/恢复

Posted

技术标签:

【中文标题】在 ExoPlayer 中检测暂停/恢复【英文标题】:Detect pause/resume in ExoPlayer 【发布时间】:2018-05-23 17:28:01 【问题描述】:

我在github 中搜索了两天的这个问题,但我找不到真正的答案。我想要在 ExoPlayer > 2.x 中检测 pause / resume 的示例。 任何人都可以给我一个例子吗?我检查了onPlayerStateChanged,问题没有解决。

onPlayerStateChanged   :   STATE_BUFFERING 
onPlayerStateChanged   :   STATE_READY 

我刚刚从onPlayerStateChanged 得到了这个日志,而且这不是一直被调用的!

【问题讨论】:

【参考方案1】:

编辑---

请参考Player.isPlaying() 方法,该方法将其作为 API 提供。

“不必单独检查这些属性,可以调用 Player.isPlaying。”

https://exoplayer.dev/listening-to-player-events.html#playback-state-changes

--- 编辑结束

您需要使用Player.EventListener 检查playWhenReady。 Playback states of ExoPlayer 与播放器是否暂停无关:

player.addListener(new Player.DefaultEventListener() 
  @Override
  public void onPlayerStateChanged(boolean playWhenReady, int playbackState) 
    if (playWhenReady && playbackState == Player.STATE_READY) 
      // media actually playing
     else if (playWhenReady) 
      // might be idle (plays after prepare()), 
      // buffering (plays when data available) 
      // or ended (plays when seek away from end)
     else 
      // player paused in any state
    
  
);

播放/暂停 ExoPlayer 提供的播放器

player.setPlayWhenReady(boolean)

ExoPlayer 的播放状态序列与媒体文件永不停止重新缓冲在四种状态中的每一种状态中都有一次,并且不表示播放/暂停:

Player.STATE_IDLE;
Player.STATE_BUFFERING;
Player.STATE_READY;
Player.STATE_ENDED;

每次播放器需要缓冲时:

Player.STATE_READY;
Player.STATE_BUFFERING;
Player.STATE_READY;

设置 playWhenReady 不会影响状态。

你的媒体实际上是在什么时候播放的

playWhenReady && playbackState == Player.STATE_READY

准备就绪时播放。 :)

【讨论】:

所提到的常量现在被标记为弃用,但它们仍在工作,这对调试很有用。 在 dev-2 分支(预发布)上,不推荐使用 STATE_XYZ 常量。你认为为什么会这样? 我正在使用 Exo Player 2.7.0,android Studio 告诉我是这样(目标 API 27 到 16)——我只是想留下一些他们仍在工作的信息。我不确定“dev-2 分支”。 当我们在横向模式下暂停视频并更改为纵向模式时,此逻辑会失败。有什么解决办法吗?【参考方案2】:

您可以使用exoplayer.getPlayWhenReady()检查播放器当前是处于暂停状态还是播放状态。

【讨论】:

【参考方案3】:

你可以使用这个功能:

public boolean isPlaying() 
    return exoPlayer.getPlaybackState() == Player.STATE_READY && exoPlayer.getPlayWhenReady();

【讨论】:

【参考方案4】:

我有同样的要求来检测 exoplayer 播放/暂停按钮的点击事件。以上答案主要是在谈论状态而不是 关于按钮点击事件。

这是我为检测播放/暂停按钮点击所做的,效果很好。

第一步:创建自定义控件调度器类并重写方法dispatchSetPlayWhenReady

class PlayerControlDispatcher : DefaultControlDispatcher() 
    override fun dispatchSetPlayWhenReady(player: Player?, playWhenReady: Boolean): Boolean 
        if(playWhenReady) 
           // Play button clicked
         else 
          // Paused button clicked
        
        return super.dispatchSetPlayWhenReady(player, playWhenReady)
    

第 2 步:将自定义控件调度程序类 PlayerControlDispatcher 设置到播放器视图中。

playerView.setControlDispatcher(PlayerControlDispatcher())

其中 playerView 是我们在布局文件中声明的 com.google.android.exoplayer2.ui.PlayerView 的一个实例。

【讨论】:

这是正确答案,完美运行!谢谢@krishna-sharma! 很高兴看到它对您有用@renatoarg,它将帮助其他人现在解决这个问题。 嗨@KrishnaSharma 我试过你的代码,但出错了。你能解释一下我应该把代码位置/位置放在哪里吗? @HiDayurieDave 你可以把它放在任何地方,创建单独的类或内部类。重要的一行是 playerView.setControlDispatcher(PlayerControlDispatcher()) ControlDispatcher 接口在 2.16.0 中被移除,见github.com/google/ExoPlayer/releases/tag/r2.16.0。【参考方案5】:

肯定是自从其他答案贴出来后,Player.EventListener中又提供了一个新方法。 [编辑:现在是 Player.Listener,因为 Player.EventListener 已被弃用]。这对我很有效:

override fun onIsPlayingChanged(isPlaying: Boolean) 
    // your code here

如果 isPlaying 为 false,则暂停,否则播放。

【讨论】:

【参考方案6】:

Kotlin 2020 解决方案方法更新

状态变化和播放错误等事件会报告给已注册的Player.EventListener 实例。

Player.EventListener 有空的默认方法,所以你只需要实现你感兴趣的方法。

首先你的班级,说你的活动,符合Player.EventListener接口。

然后你重写类上的onIsPlayingChanged 方法。 onCreate 方法之外...

将监听器添加到您的播放器实例:

// Adding player listener for tracking events
player?.addListener(this)

您可以使用 Player.isPlaying 检查玩家是否正在播放(即位置在前进):

//Listening to player events
override fun onIsPlayingChanged(isPlaying: Boolean)
    if (isPlaying) 
        // Active playback.
     else 
        // Not playing because playback is paused, ended, suppressed, or the player
        // is buffering, stopped or failed. Check player.getPlaybackState,
        // player.getPlayWhenReady, player.getPlaybackError and
        // player.getPlaybackSuppressionReason for details.
    

就是这样。很简单。

【讨论】:

【参考方案7】:

请尝试以下代码。播放器侦听器(onPlayerStateChanged)不利于观察多次调用的播放/暂停操作,并且在播放器配置时也会调用。

videoView.setControlDispatcher(object : DefaultControlDispatcher() 
            override fun dispatchSetPlayWhenReady(player: Player, playWhenReady: Boolean): Boolean 
                if (playWhenReady)
                  // Tap on Play button  
                else
                 // Tap on Pause button
                return super.dispatchSetPlayWhenReady(player, playWhenReady)
            
        )

【讨论】:

ControlDispatcher 接口在 2.16.0 中被移除,参见 github.com/google/ExoPlayer/releases/tag/r2.16.0。【参考方案8】:

科特林

private fun ExoPlayer.isPlaying() =
    playbackState == Player.STATE_READY && playWhenReady

【讨论】:

【参考方案9】:

我认为回调:

fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int)

来自Player.Listener

【讨论】:

以上是关于在 ExoPlayer 中检测暂停/恢复的主要内容,如果未能解决你的问题,请参考以下文章

ExoPlayer播放视频返回宽高异常

拔下耳机时暂停ExoPlayer

Exoplayer Recyclerview 第二次播放错误的视频

Android Exoplayer,在屏幕旋转时恢复视频

在 Exoplayer IMA 扩展中保存和恢复广告进度

谷歌 ExoPlayer 指南