iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 11
0
Mobile Development

Android 音樂播放器自己來系列 第 11

播放器架構實作 (4) - ExoPlayer 設定實作

  • 分享至 

  • xImage
  •  

昨天設定好了 MediaSession,今天來加入 Player 了,會參考 uamp 專案內所使用的方式,就直接使用 ExoPlayer,使用 Kotin lazy 語法,在使用時在初始化,並使用 builder 設定參數。

private val exoPlayer: ExoPlayer by lazy {
        SimpleExoPlayer.Builder(this).build().apply {
            setAudioAttributes(musicAudioAttributes, true)
            setHandleAudioBecomingNoisy(true)
            addListener(playerListener)
        }
    }

private val musicAudioAttributes = AudioAttributes.Builder()
        .setContentType(C.CONTENT_TYPE_MUSIC)
        .setUsage(C.USAGE_MEDIA)
        .build()

AudioAttributes 設定播放的類型(ContentType),設定會後會連動一些相對應的設定,比方說打開音量的設定介面,會看到有好幾個音量設定可以設定,透過這邊的設定,讓 Android 系統知道現在播放的類型,使用者調整音量時,才會對的起來。
https://ithelp.ithome.com.tw/upload/images/20200911/201297280z5jq1rwRz.png

AudioAttributes 第二個參數(handleAudioFocus) 是設定要不要處理 AudioFocus,AudioFocus 是什麼呢?

在電腦上播音樂,可能用 KKBOX 播了音樂,這時候再去看 Youtube 看影片,兩個聲音就會疊在一起,同時一起播出來,必須手動去停止一邊的播放。但在手機上就不是這個情況,後面的音樂軟體在播時,前面的音樂就會暫停播放,這在音樂播放 App 上是個良好的設計,想像如果有電話或是 Line 鈴響時,但音樂還是繼續播,這時候還需需要手動就暫停,就稍嫌麻煩了。

音樂 App 在播放時會須要向系統註冊 AudioFocus(執行 requestAudioFocus),通知系統要播放音樂了並觀察 AudioFocus 是否有改變(聽 onAudioFocusChange),一個目的是跟別的正在使用聲音的 App 通知,有其播音樂要播放囉,這時候就會看其他 App 是怎麼處理這個行為,通常的方式是暫停。觀察 AudioFocus 的功能就是有其他 App 需要播放向系統取得 AudioFocus,音樂 App 就會做對應的處理可能是暫停或是變小聲。

官網有介紹要怎麼處理這塊行為,Android 8 以前還有不同的寫法,程式碼比較多,可以參考這邊的介紹:Managing audio focus,ExoPlayer 幫開發者處理好了上述的行為,就不用另外在寫 code,收到什麼事件來控制 Player 播放或是暫停了。

setHandleAudioBecomingNoisy(true) 這個設定的用途是,在播放音樂時,如果拔掉耳機,這是音樂就會自動暫停了,這也是一個貼心的設計。背後的原理是註冊 BroadcastReceiver 去聽 ACTION_AUDIO_BECOMING_NOISY 事件,收到後就要暫停音樂播放,官網的介紹在這邊:Don't be noisy。這在 ExoPlayer 也幫開發者處理好了,就設定這行就可以了。

再來設定 listener,去監聽播放器的狀態,裡面其實有蠻多 callback 的,參考 uamp 專案,先處理 onPlayerStateChanged 和 onPlayerError,onPlayerStateChanged 會處理顯示或隱藏 notification 的邏輯,onPlayerError 就顯示 Toast,通知使用者

private inner class PlayerEventListener : Player.EventListener {
      override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
            when (playbackState) {
                Player.STATE_BUFFERING,
                Player.STATE_READY -> {
                    //TODO: show notification
                }
                else -> {
                    //TODO: hide notification
                }
            }
        }

      override fun onPlayerError(error: ExoPlaybackException) {
          var message = R.string.generic_error
          Toast.makeText(applicationContext, message, Toast.LENGTH_LONG).show() 
      } 
}

明天會繼續介紹,關於 ExoPlayer 播歌的內容,就再一起提供程式碼。


上一篇
播放器架構實作 (3) - MediaSession 實作
下一篇
播放器架構實作 (5) - ExoPlayer 播歌實作
系列文
Android 音樂播放器自己來30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言