SimpleExoPlayer 简单使用

前言:
依赖版本:
implementation 'com.google.android.exoplayer:exoplayer-core:2.13.3'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.13.3'

自定义统一接口IPlayer (interface)

interface IPlayer {


    companion object {
        const val PLAYER_NULL = -1
        const val PLAYER_INIT = 0
        const val PLAYER_PREPARE = 1
        const val PLAYER_PLAY = 2
        const val PLAYER_PAUSE = 3
        const val PLAYER_STOP = 4

        const val PLAYER_RELEASE = 7
        const val PLAYER_SET_SURFACE = 8
    }

    fun play()

    fun setRepeatMode(mode: Int) {

    }

    fun getRepeatMode(): Int {
        return 0
    }

    //异步
    fun prepare(url: String)

    fun stop()

    fun pause()

    fun release()


    fun seekTo(time: Long, autoPlay: Boolean = true)


    fun getCurrentPosition(): Long

    fun getDuration(): Long {
        return 0L
    }

    fun getVolume(): Float {
        return 0F
    }

    fun setVolume(value: Float): Boolean {
        return false
    }


}

封装 ExoPlayer
封装参考:SimpleExoPlayer extends BasePlayer

class ExoPlayer(private val context: Context) : IPlayer {


    private var currentPlayerUrl = ""
    private var playStatus = PLAYER_PLAY

    private var exoPlayer: SimpleExoPlayer? = null
    private var contentFrame: AspectRatioFrameLayout? = null
    private var surfaceView: View? = null
    private var textureViewRotation = 0
    private var repeatMode = Player.REPEAT_MODE_ONE
    private var currentVolume = 0F

    private var mComponentListener: ComponentListener? = null
    private var mPlayerEventListener: PlayerEventListener? = null


    init {
//        val extractors = DefaultExtractorsFactory()
//        exoPlayer = SimpleExoPlayer.Builder(
//            context,
//            DefaultRenderersFactory(context),
//            DefaultTrackSelector(context),
//            DefaultMediaSourceFactory(context, extractors),
//            TmpLoadControl(),
//            DefaultBandwidthMeter.getSingletonInstance(context),
//            AnalyticsCollector(Clock.DEFAULT)
//        ).build()
        exoPlayer = SimpleExoPlayer.Builder(context).build()
    }

    fun setVideoTextureView(view: TextureView) {
        surfaceView = view
        mComponentListener = ComponentListener()
        exoPlayer?.let {
            it.setVideoTextureView(view)
            it.videoComponent?.let { component ->
                component.addVideoListener(mComponentListener!!)
            }
            it.addListener(mComponentListener!!)
        }


    }

    fun setAspectRatioFrameLayout(view: AspectRatioFrameLayout?) {
        contentFrame = view
    }

    override fun play() {
        exoPlayer?.let {
            playStatus = PLAYER_PLAY
            it.play()
            currentVolume = it.volume
        }
    }


    /**
     *
     */
    override fun setRepeatMode(mode: Int) {
        var tmp = Player.REPEAT_MODE_ONE
        when (mode) {
            0 -> {
                tmp = Player.REPEAT_MODE_OFF
            }
        }
        this.repeatMode = tmp

    }

    override fun getRepeatMode(): Int {
        var tmp = 0
        exoPlayer?.let {
            when (it.repeatMode) {
                Player.REPEAT_MODE_ONE -> {
                    tmp = 1
                }
                Player.REPEAT_MODE_OFF -> {
                    tmp = 0
                }
            }
        }
        return tmp
    }

    override fun getVolume(): Float {
        return currentVolume
    }

    override fun setVolume(value: Float): Boolean {
        exoPlayer?.volume = value
        return true
    }

    override fun prepare(url: String) {
        currentPlayerUrl = url
        playStatus = PLAYER_PREPARE
        val mediaItem = MediaItem.fromUri(url)
        exoPlayer?.let {
            it.setMediaItem(mediaItem)
            it.repeatMode = repeatMode
            it.playWhenReady = false
            it.prepare()
            IKLog.d("$TAG prepare volume:${it.volume}")
        }
    }

    override fun stop() {
        exoPlayer?.let {
            playStatus = PLAYER_STOP
            it.stop()
        }
    }

    override fun pause() {
        exoPlayer?.let { player ->
            playStatus = PLAYER_PAUSE
            player.pause()
        }
    }

    override fun release() {
        exoPlayer?.let { player ->
            playStatus = PLAYER_RELEASE
            mComponentListener?.let {
                player.removeListener(it)
            }
            player.stop()
            player.release()
            exoPlayer = null
        }
    }

    override fun seekTo(time: Long, autoPlay: Boolean) {
        exoPlayer?.let {
            it.seekTo(time)
            if (autoPlay) {
                it.play()
            }
        }
    }

    override fun getCurrentPosition(): Long {
        return exoPlayer?.contentPosition ?: 0L
    }

    override fun getDuration(): Long {
        return exoPlayer?.duration ?: 0L
    }


    private inner class ComponentListener : Player.EventListener, VideoListener, View.OnLayoutChangeListener {

        override fun onVideoSizeChanged(width: Int, height: Int, unappliedRotationDegrees: Int, pixelWidthHeightRatio: Float) {
            var videoAspectRatio: Float = if (height == 0 || width == 0) 1F else width * pixelWidthHeightRatio / height
            surfaceView?.let { view ->
                if (view is TextureView) {
                    if (unappliedRotationDegrees == 90 || unappliedRotationDegrees == 270) {
                        videoAspectRatio = 1 / videoAspectRatio
                    }
                    if (textureViewRotation != 0) {
                        view.removeOnLayoutChangeListener(this)
                    }
                    textureViewRotation = unappliedRotationDegrees
                    if (textureViewRotation != 0) {
                        view.addOnLayoutChangeListener(this)
                    }
                    PlayerUtils.applyTextureViewRotation(view, textureViewRotation)
                }
            }
            onContentAspectRatioChanged(videoAspectRatio, contentFrame, surfaceView)

        }

        override fun onLayoutChange(v: View?, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) {
            PlayerUtils.applyTextureViewRotation(v as TextureView, textureViewRotation)
        }

        override fun onEvents(player: Player, events: Player.Events) {
            super.onEvents(player, events)
            IKLog.d(TAG, "onEvents: events:${events} ${events.contains(Player.EVENT_PLAYER_ERROR)} ")
            if (events.contains(Player.EVENT_PLAYER_ERROR)) {
                IKLog.e("$TAG  onEvents: playerError:${player.playerError}")
            }
            mPlayerEventListener?.onEvent(events)
        }

        override fun onRenderedFirstFrame() {
            super.onRenderedFirstFrame()
            IKLog.d("$TAG onRenderedFirstFrame")
            mPlayerEventListener?.onRenderedFirstFrame()
        }

        override fun onPlaybackStateChanged(state: Int) {
            super.onPlaybackStateChanged(state)
            IKLog.e(TAG, "onEvents: events:${state}")
            mPlayerEventListener?.onPlaybackStateChanged(state)
        }
    }

    private fun onContentAspectRatioChanged(
        contentAspectRatio: Float,
        contentFrame: AspectRatioFrameLayout?,
        contentView: View?
    ) {
        contentFrame?.setAspectRatio(
            if (contentView is SphericalGLSurfaceView) 0F else contentAspectRatio
        )
    }


    fun setPlayerEventListener(listener: PlayerEventListener) {
        mPlayerEventListener = listener
    }

    interface PlayerEventListener {
        fun onEvent(events: Player.Events)

        fun onPlaybackStateChanged(state: Int) {

        }

        fun onRenderedFirstFrame() {

        }
    }
}
其中:图像纠正相关
ComponentListener{
  onVideoSizeChanged
  onLayoutChange
}
PlayerUtils
object PlayerUtils {
    fun applyTextureViewRotation(textureView: TextureView, textureViewRotation: Int) {
        val transformMatrix = Matrix()
        val textureViewWidth = textureView.width.toFloat()
        val textureViewHeight = textureView.height.toFloat()
        if (textureViewWidth != 0f && textureViewHeight != 0f && textureViewRotation != 0) {
            val pivotX = textureViewWidth / 2
            val pivotY = textureViewHeight / 2
            transformMatrix.postRotate(textureViewRotation.toFloat(), pivotX, pivotY)

            // After rotation, scale the rotated texture to fit the TextureView size.
            val originalTextureRect = RectF(0F, 0F, textureViewWidth, textureViewHeight)
            val rotatedTextureRect = RectF()
            transformMatrix.mapRect(rotatedTextureRect, originalTextureRect)
            transformMatrix.postScale(
                textureViewWidth / rotatedTextureRect.width(),
                textureViewHeight / rotatedTextureRect.height(),
                pivotX,
                pivotY
            )
        }
        textureView.setTransform(transformMatrix)
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一.榜单介绍 排行榜包括四大类: 单一框架:仅提供路由、网络层、UI层、通信层或其他单一功能的框架 混合开发框架:...
    伟子男阅读 5,271评论 0 161
  • 请允许我借鉴前辈们的东西~~~~ 感激不尽~~~~~ 以下为Android 框架排行榜 么么哒~ Android...
    嗯_新阅读 2,127评论 3 32
  • 一、概述 ExoPlayer谷歌源码地址:https://github.com/google/ExoPlayer[...
    放羊娃华振阅读 7,990评论 0 1
  • 前言RxJava和Retrofit也火了一段时间了,不过最近一直在学习ReactNative和Node相关的姿势,...
    AFinalStone阅读 561评论 0 0
  • 使用: 添加依赖(依赖的是整个ExoPlayer库): implementation 'com.google.an...
    Brilliancess阅读 5,220评论 0 0