android media player实现一个可手势滑动控制 + 可以调节分辨率|字幕|倍速的视频播放器(MediaPlayer + ExoPlayer实现)

该博客介绍了如何使用Android的MediaPlayer和ExoPlayer实现一个支持手势滑动控制播放进度、亮度、音量,并可调节分辨率、字幕和倍速的视频播放器。通过面向接口编程和代理方法动态修改播放参数,实现了界面与播放器的解耦。同时,还提供了自动旋屏功能和自定义UI组件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章来自:http://blog.youkuaiyun.com/intbird 转载请说明出处

五一第一天在家休息(后续休息有空会进行升级)
看了一下视频播放的相关东西
写了一个简单的触摸视频播放器
(使用 MediaPlayer 和 ExoPlayer )
我喜欢从自己的使用感受做些调整
所以在里面有一个 触摸平滑进度 的实现
还有就是代码面向抽象,方便后续一些功能替换
有空的话我就会继续写写它

Github源码地址: https://github.com/intbird/VideoPlayerLib

GitHub issues(持续维护,待开发):
https://github.com/intbird/VideoPlayerLib/issues/2

基础功能:

播放不同的 分辨率/字幕/倍速/初始进度
在屏幕中间双击: 切换播放/暂停
在屏幕中间滑动: 拖动进度
在屏幕左侧滑动: 控制亮度
在屏幕右侧滑动: 控制声音
点击锁定按钮: 锁定当前所有操作
点击上一个/下一个/播放/暂定/停止: 执行对应动作
横竖屏方向自动切换

有时间的话会继续开发......

完成效果:
  1. 自动旋屏: https://blog.youkuaiyun.com/intbird/article/details/109077762

111

  1. 部分截图:
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


Github源码地址: https://github.com/intbird/VideoPlayerLib
文章来自:http://blog.youkuaiyun.com/intbird 转载请说明出处

结构解析:

0.权限检查: 读取媒体权限
1.播放器层: 播放器的接口 + 实现
2.触控层: 触摸区域识别 + 手势识别 + 触摸灵敏度和进度反馈
3.控制面板层: 可视UI按钮(上一个,下一个,播放/暂停/停止)
4.锁定层: 锁(锁播放器+ 锁触控 + 锁面板+ 锁屏幕方向等)

代码结构:

用mvc简单实现一下,有空了可以把view这层在做层封装,方便后续更换UI的最小代价

1.项目结构
1.api: 使用Fragment(推荐此方式)
 VideoPlayerFragment.newInstance(array, index, style, autoPlay)

在这里插入图片描述

2.api: 使用Activity(模块解耦实现)
 ServicesLoader.load(IVideoPlayer::class.java)?.startActivity(this,array, index, autoPlay)

显示声明外部api和实现默认的api
在这里插入图片描述在这里插入图片描述

3.总体结构

逐步升级, 代码结构有些许调整
在这里插入图片描述

4.资源前缀

在这里插入图片描述

5.播放实现

在这里插入图片描述

  1. MediaPlayerImpl
	intbird.soft.lib.video.player.main.player.player.MediaPlayerImpl
  1. ExoPlayerImpl(有空会继续实现)
	intbird.soft.lib.video.player.main.player.player.ExoPlayerImpl
6.自动旋屏

自动旋转视频和抖动恢复屏幕方向 : https://blog.youkuaiyun.com/intbird/article/details/109077762

2. 大体思路
1. 不同播放器不同布局, 统一接口多个回调
1.面向接口, 抽象代码
    private var playerCall: PlayerCallbacks? = null
    private var playerView: MediaViewInfo<out View, out View>? = null
    private var player: IPlayer? = null
    
    private fun instanceMediaPlayer(mediaPlayerType: MediaPlayerType?) {
        when(mediaPlayerType) {
            MediaPlayerType.PLAYER_STYLE_1, MediaPlayerType.PLAYER_STYLE_2 -> {
                playerCall = PlayerCallbacks(playerCallback, videoPlayerCallback)
                playerView = MediaViewProvider(view).by(mediaPlayerType)
                player = MediaPlayerImpl(getInternalActivity(), playerView?.display as? TextureView, subtitleText, intentHelper, playerCall)
            }
            MediaPlayerType.PLAYER_STYLE_3 -> {
                playerCall = PlayerCallbacks(playerCallback, videoPlayerCallback)
                playerView = MediaViewProvider(view).by(mediaPlayerType)
                player = ExoPlayerImpl(getInternalActivity(), playerView?.display as? TextureView, playerCall)
            }
        }
    }
2.面向复杂, 抽象配置

通过一个UI的配置项,强制让不同类型的播放自己选择如何和界面关联

enum class MediaPlayerType(
    open val layoutDisplay: Int,
    open val viewDisplay: Int,
    open val layoutControl: Int,
    open val viewControl: Int
) {
    PLAYER_STYLE_1(
        R.layout.lib_media_player_diaplay_texture,
        R.id.textureView,
        R.layout.lib_media_player_control_style_1,
        R.id.mediaRootControl
    ),
    PLAYER_STYLE_2(
        R.layout.lib_media_player_diaplay_texture,
        R.id.textureView,
        R.layout.lib_media_player_control_style_2,
        R.id.mediaRootControl
    ),
    PLAYER_STYLE_3(
        R.layout.lib_media_player_diaplay_ijkplayer
        R.id.ijkplayer,
        R.layout.lib_media_player_control_style_2,
        R.id.mediaRootControl
    )
}
2. 动态修改播放参数,回传到播放器/界面等外部
1. IntentHelper

IntentHelper: 获取外部传入的Intent列表 的 某个Index
进而进行组装当前播放的数据
但:我想如果一个player实现类,他的数据不是外部传入的
那么:他也可以替换掉这个IntentHelper,在少量修改后要
能将 切换播放/上一首/下一首 等改为自己的内部方法

始终根据index获取数据
在这里插入图片描述

2. 实现代理方法

在这里插入图片描述

3. 参数更新

MediaItemInfoRecord: 通过它来保存播放状态,
以便在切换分辨率,字幕等需要强行进行状态改变后
继续操作前的进度进行播放

onReceivePlayFile: 这个在收到播放参数变更时会通知到播放器/控制层等等
在这里插入图片描述

4.
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值