一、
视频播放一般从load()开始,加载视频,第一步肯定是需要loadUrl()。loadUrl()有两种结果,一种是mediaplayer为我们发送了就绪事件,此时会回调onPrepareed(),在onPrepared()中回调我们正常的处理逻辑。另一种就是error,也就是加载失败了。通常情况下加载失败后会重试,会清空播放器然后重新load()一次,如果load()失败后会调用stop(),stop()里会清空mediaplayer,然后重新调用load()方法,这样就循环起来的,但是不会让它无限循环,在实际开发中,一般会让它重复加载三次,如果加载三次还是失败,那么会进入到stop()状态中
1、
在代码中的实现:
load():加载我们的视频url
首先检查一下播放器是否处于IDLE状态,如果不是直接return;
如果处于IDLE状态,则显示loading框,设置当前状态为IDLE,由于mediaplayer可能为空,所以要先检查一下mediaplayer是否为空,如果为空的话,会去创建播放器并设置监听事件,并设置surface。创建mediaplayer成功后,会为它设置datasource为url,然后进行异步准备prepareAsync()。出现异常后调用stop()方法进行重新加载。如果加载正常,也就是说服务器没有问题,也顺利加载完成了,会调用onPrepared()方法
2、
stop():清空当前mediaplayer并重新load
如果出现异常则调用stop()方法。stop()方法的主要作用有两点,一点是清空mediaplayer,然后把handler的消息也移除掉。handler的主要作用是对外通知视频播放到了第几秒,,同时将当前状态设置为IDLE。另一点是重写加载
3、onPrepared()
如果加载成功,那么就可以进行播放了。
首先判断mediaplayer是否为空,这个判断纯粹是为了代码的健壮性来考虑的。如果不为空,则为它设置bufferingupdatelistener,即加载成功后就可以监听它的缓存进度,加载成功后,需要将重试此时置为0。
判断一下监听是否为空,不为空的话调用onAdVideoLoadSuccess()通知外部视频加载成功了。
在一系列准备工作完成后,就可以进入播放或者暂停状态了,但是为什么不直接进入播放状态呢?因为视频播放是有一定的限制的,这里的限制主要有两个条件,一个是视频要在屏幕中的显示超过50%,另一个限制是用户的设置与当前的网络状态是一致的。所以这里调用decideCanPlay()来决定进入播放还是进入暂停状态。
4、decideCanPlay()
如果满足了两个条件,则进入resume()播放状态,否则进入pause()暂停状态
5、resume()
加载成功后,会调resume()或者pause()。从流程图中可以看到,如果调用pause()的话,播放器会进入到一个暂停状态。而如果调用resume()的话,会让播放器进入到播放状态。而当播放器进入到resume()状态,也就是播放状态后呢,又会引申出两种状态,一种是正常播放完成,回调onComplete(),一种是在播放过程中由于一些特殊原因导致播放失败了,那么就会回调onError().
resume():恢复视频播放
与load()差不多,首先判断mediaplayer的状态是否为IDLE,如果不为空闲状态则return。
判断mediaplayer是否正在播放,如果正在播放,不需要进行任何处理,因为已经是在播放中了,如果不是在播放中,才会调用start()方法,去让它进行播放。紧接着通过handler发送TIME_MSG消息。此时播放器就播放起来了。视频播放起来,就会出现两种情况。一种是正常播放完成,一种是播放出现异常,这两种情况都会有相应的回调
6、onCompletetion()
播放完成后回调。
首先通知外部视频播放完成了。其次,设置播放完成的标志位,同时设置setIsPausedClicke(true),表示视频现在真正地处于暂停状态了。因为视频暂停有两种,一种是划出屏幕以后的自动暂停,这种情况下当回来后是需要自动播放的,另一种是播放完成以后进入真正的暂停状态,这种情况下,回来以后是不能自动播放的。这里通过了一个变量说明真正地处于暂停状态了。状态标志完成后,调用playBack()方法,让它回到初始状态。
7、playBack()
播放完成后回到初始状态
所做的工作与stop()有点类似,但是不会将播放器置为空,因为我们已经播放完成一次了,如果用户想看第二次,我们没有销毁播放器,那么用户就可以直接去看第二次了,不需要再重新load,这样既节省流量,又节省时间,还提高了效率。
因为最终是要进入到暂停状态,所以先将状态置为暂停,状态暂停以后,同样移除事件的发送。在mediaplayer不为空的时候,将它重置。如何重置呢?将mediaplayer seek到0,让它跳转到第0秒,然后让它进入暂停状态,这样下次再播放就会从0点开始播放,这是一个比较高效的实现方式。最后显示pause相关的view
8、onError():
播放产生异常时回调
onError()方法有一个boolean类型的返回值,如果返回true,Android系统会任务你自己处理了这个异常,它就不会再帮你去处理了。同时false也是默认值,Android系统会任务你并没有去处理这个error类型的事件,它会帮你去做一些默认的处理。但是我们通常是自己处理的,所以在自己处理完以后,返回一个true回去。
这里已经判断了重试次数了,为什么还要调用stop()这个重新加载方法?stop有两个作用,一个是清空我们的播放器mediaplayer,另一部分才是重新load。而我们超过重试次数后,只会清空mediaplayer,不会再去重新load()了,所以这里的stop()并不一定会重新加载
9、pause()
暂停视频
10、onSurfaceTextureAvailable()
表明TextureView处于就绪状态
到此,生命周期及功能性方法基本完成了,那么load()方法应该在什么时候调用呢?
应该在onCreate()方法里面吗?这样是不可以的,因为数据的显示是在textureview可用的时候才能真正地去显示出数据来,而在构造方法中调用时texttureview可能并没有准备好,这时候调用可能并没有一个真正有效的texttureview,所以要在textrueview avilable以后也就是onSurfaceTextureAvailable()方法中调用
使用方法和surfaceview是一样的。首先创建surface,创建好以后真正地调用load()方法进行加载,这样才是一个合理的过程。这样Android系统在接收到onSurfaceTextureAvailable的时候会调用load(),调用load()后会看到上面图中的prepare()、stop(),而进入prepare()后又会根据条件进入resume()或者是pause(),而进入resume()后又可以进入onCompletetion()和onError(),这样整个流程就串起来了。
二、处理常见的事件类型
1、屏幕锁屏
也就是当用户锁屏的时候,暂停视频播放。
如果是用户解锁,那么就需要根据情况决定是暂停还是继续播放
2、在view的显示发送改变时进行的处理
播放器还有一种比较常见的状态是在A 的activity中点击了播放器,此时点击了 A Activity中的一个按钮跳转到了B Activity,那么A Activity就被挂在了后台,那么此时的视频播放也需要被暂停,此时需要继续处理,如果不处理,视频播放器就会继续播放