基于MediaPlayer的Android播放器控件

Android自身的播放控件在界面定制上不是很方便,而且没有针对播放流进行加工处理的相关接口。于是自己写了一个基于MediaPlayer的播放器控件。该控件有以下特点:

  1. 支持开发者对播放界面进行任意的定制。
  2. 支持开发者对播放流进行加工处理,比如加解密等。
  3. 支持开发者进行插件开发。
  4. 自带了三个插件:外挂字幕插件,图片广告插件和弹幕插件

效果图


横屏弹幕.png

竖屏播放列表.png

Demo下载

github地址:https://github.com/thfhongfeng/PinePlayer

Demo解析

一、项目结构
项目结构.png
二、播放器控件图层结构
  1. 播放器View图层结构:


    PineMediaPlayerView图层.png

    最外层为PineMediaPlayerView,由下往上依次为:
    a). 播放器画面的surfaceview,位于最底层。
    b). PineMediaController View,覆盖于播放器surfaceview之上。

  2. 播放器控件PineMediaController图层结构:


    PineMediaController图层.png

    控制器控件界面由下往上依次为:
    a). 背景view,位于PineMediaController底层。
    b). 各类插件View:广告,外挂字幕,弹幕等,覆盖于背景View之上。
    c). 内置控制器View,覆盖于插件View之上。
    d). 加载等待View,覆盖于内置控制器View之上。
    e). 右侧View,覆盖于加载等待View之上。
    具体可参考PineMediaController的attachToParentView方法中添加各个View的顺序。

  3. 播放器插件Plugin View图层结构:


    PluginView图层.png

    由下往上依次为:
    a). 宽高与播放画面SurfaceView相同的插件View,比如自带的外挂字幕插件。


    PluginMatchSurfaceView图层.png

    b). 宽高与PineMediaController相同的插件View,比如自带的图片广告插件。
    PluginMatchControllerView图层.png
三、类结构
  1. 组件类图


    组件类图.png

    PineSurfaceView为播放画面的surface view,PineMediaController是控制器界面管理类,管理控制器界面。PineMediaPlayerView则是控件的最外层View,surface view和控制器View都是其子View,其中控制器View 覆盖在surface view上面。
    a). PineMediaPlayerView,PineMediaController,PineSurfaceView为界面View。
    b). PineMediaPlayerComponent封装具体的播放器(本项目封装的是MediaPlayer),通过代理PineMediaPlayerProxy与界面进行交互。

  2. 控件适配类图


    界面适配类图.png

    开发者通过实现PineMediaController.AbstractMediaControllerAdapter来进行适配:
    a). onCreateBackgroundViewHolder:背景View定制,返回PineBackgroundViewHolder给播放器控件,该View会通过attachToParentView加入到控件中。
    b). onCreateInRootControllerViewHolder:内置控制器View定制,返回PineControllerViewHolder给播放器控件,该View会通过attachToParentView加入到控件中。
    c). onCreateOutRootControllerViewHolder:外置控制器View,返回PineControllerViewHolder给播放器控件,该View不会加入到控件中,而由用户自己指定显示的位置,但依然需生成PineControllerViewHolder给播放器,使得播放器播放行为与该View相关联。
    d). onCreateWaitingProgressViewHolder:加载等待View定制,返回PineWaitingProgressViewHolder给播放器控件,该View会通过attachToParentView加入到控件中。
    e). onCreateRightViewHolderList:全屏下的右侧View定制,返回PineRightViewHolder列表给播放器控件,该View List会通过attachToParentView加入到控件中(主要应用有播放列表View,清晰度列表View等)。
    f). onCreateControllerMonitor:返回界面更新适配器ControllerMonitor。
    g). onCreateControllersActionListener:返回点击及手势事件适配器接口IControllersActionListener。
    适配分两类:
    a). 界面适配:onCreateXXXViewholder
    b). 事件适配,事件适配又分两类:
    界面更新事件适配-onCreateControllerMonitor;
    点击及手势事件适配-onCreateControllersActionListener。

  3. 插件类图


    插件类图.png

    插件使得开发者可以对控件进行界面和功能性的扩展。开发者通过实现IPinePlayerPlugin接口来定制自己的功能。该接口主要的API
    a). onInit:用于插件初始化。
    b). createViewHolder:插件界面的创建。
    c). getContainerType:插件界面宽高匹配类别,TYPE_MATCH_CONTROLLER-与控制器界面的宽高相同,TYPE_MATCH_SURFACE-与surface view的宽高相同。
    d). onMediaPlayerXXX:播放器播放状态回调。
    e). onTime:播放器播放时间间隔(每200毫秒回调一次)回调。
    f). onRelease:播放器释放后回调。

本demo内置了三个插件:外挂字幕插件,图片广告插件和弹幕插件,开发者可以参考这三个插件来定制自己的插件。

四、常用的API说明
  1. PineMediaPlayerView:
/**
* 播放器控件初始化
* @param mediaPlayerTag   播放器唯一标识,如果mediaPlayerTag标识的播放器已经初始化,
*                         则将控件绑定到该播放器上,否则初始化一个新的mediaPlayerTag标识的播放器,
*                         并绑定控件到播放器上。
* @param controller   IPineMediaController 实例,即播放器控制器
* @param enableSurface   是否需要SurfaceView来呈现播放画面(默认为true),对于音频则可以设置为false
* @param saveMediaStateWhenHide   当控件View隐藏时(比如控件所在Activity被pause,或者失去焦点)是否自动保存当前播放状态,
*                                 用于再次显示之后的恢复到之前的播放状态(默认为true)。
*/
void init(String mediaPlayerTag, PineMediaWidget.IPineMediaController controller,
                     boolean enableSurface, boolean saveMediaStateWhenHide);

/**
* 获取播放器控件绑定的播放器接口
*/
PineMediaWidget.IPineMediaPlayer getMediaPlayer()
  1. IPineMediaPlayer
/**
* 开始播放
*/
void start();

/**
* 暂停播放
*/
void pause();

/**
* 恢复播放
*/
void resume();

/**
* 设置多媒体播放参数
*
* @param pineMediaPlayerBean 多媒体播放参数对象
*/
void setPlayingMedia(PineMediaPlayerBean pineMediaPlayerBean);

/**
* 保存播放状态和进度
*/
void savePlayMediaState();

/**
* 设置是否为独立播放模式(是否与播放界面共生命周期)
*
* @param isAutocephalyPlayMode 设置是否为独立播放模式
* @param shouldDestroyWhenDetach   在非独立模式下,当控件View从上下文环境中(Context)移除时,
*                            播放器是销毁(destroy)还是释放(release)
* true: destroy模式下,从Context中移除后,非独立播放器所有状态清除,对象销毁,无法使用resume来恢复播放状态
* false: release模式下,从Context中移除后,非独立播放器所有状态清除,对象不会销毁,可以使用resume来恢复播放状态
*/
void setAutocephalyPlayMode(boolean isAutocephalyPlayMode, boolean destroyWhenDetach);

更多API请参考PineMediaWidget.IPineMediaPlayer接口

  1. PineMediaController
/**
* 设置播放器控制器适配器(自定义自己的播放器控制器界面及显示方式)
*
* @param adapter 适配器
*/
void setMediaControllerAdapter(AbstractMediaControllerAdapter adapter)
  1. AbstractMediaControllerAdapter
/**
* 适配器初始化
*
* @param player
* @return
*/
protected boolean init(PineMediaWidget.IPineMediaPlayer player) {
    return true;
}

/**
* 背景布局,会被添加到PineMediaPlayerView布局中,
* 位于PineMediaController View最底层。用于播放切换过程中的背景布置,或者播放音频时的背景图
*
* @param player
* @param isFullScreenMode
* @return
*/
protected abstract PineBackgroundViewHolder onCreateBackgroundViewHolder(
                PineMediaWidget.IPineMediaPlayer player, boolean isFullScreenMode);

/**
* Controller内置控件布局的view holder,会被添加到PineMediaPlayerView布局中,
* 与onCreateOutRootControllerViewHolder互斥,优先使用OutRoot布局。
* 覆盖在BackgroundView上,请使用透明背景
* 需要在该方法中绑定布局的相应控件到ViewHolder中,对应的控件功能才能被激活
*
* @param player
* @param isFullScreenMode
* @return
*/
protected abstract PineControllerViewHolder onCreateInRootControllerViewHolder(
                PineMediaWidget.IPineMediaPlayer player, boolean isFullScreenMode);

/**
* Controller外置控件布局的view holder,不会被添加到PineMediaPlayerView布局中,
* 与onCreateInRootControllerViewHolder互斥,优先使用OutRoot布局。
* 需要在该方法中绑定布局的相应控件到ViewHolder中,对应的控件功能才能被激活
*
* @param player
* @param isFullScreenMode
* @return
*/
protected abstract PineControllerViewHolder onCreateOutRootControllerViewHolder(
                PineMediaWidget.IPineMediaPlayer player, boolean isFullScreenMode);

/**
* 播放准备过程中的等待界面的view holder,会被添加到PineMediaPlayerView布局中,
* 覆盖在ControllerView上
*
* @param player
* @param isFullScreenMode
* @return
*/
protected abstract PineWaitingProgressViewHolder onCreateWaitingProgressViewHolder(
                PineMediaWidget.IPineMediaPlayer player, boolean isFullScreenMode);

/**
* 内置的右侧view holder List,会被添加到PineMediaPlayerView布局中,
* 覆盖在WaitingProgressView上
*
* @param player
* @param isFullScreenMode
* @return
*/
protected abstract List<PineRightViewHolder> onCreateRightViewHolderList(
                PineMediaWidget.IPineMediaPlayer player, boolean isFullScreenMode);

/**
* Controller各个显示部件及显示状态更新回调器
*
* @return
*/
protected ControllerMonitor onCreateControllerMonitor() {
    return new ControllerMonitor();
}

/**
* Controller各个控制部件的事件的listener
*
* @return
*/
protected ControllersActionListener onCreateControllersActionListener() {
    return new ControllersActionListener();
}

/**
* 设置当前播放媒体在播放列表中的位置
*
* @param position
*/
public void setCurrentMediaPosition(int position) {

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容