分享

Android MediaPlayer生命周期详解

 爱因思念l5j0t8 2017-07-29


Android开发中那些你必备的堪称黑科技的神器APP

吊炸天!74款APP完整源码!

Android自定义View之自己动手绘制一个折线图控件ChartView

关于Android播放器的生命周期,是我们在Android上开发视频播放的基础,必须熟练掌握。我们知道,Android官方给出了一张经典的生命周期状态图,如下图:



今天我们就根据这张图来详细聊聊MediaPlayer的生命周期。


音频/视频流生命周期回调和控制是通过如上图所示的状态机管理的。其中使用到了状态模式(一种设计模式,后续文章我们会详细讨论)。上图所示,MediaPlayer的生命周期回调是通过想逛播放操作时间控制的。椭圆圈展示了MediaPlayer可能处于的播放状态。箭头表示播放回调控制操作驱动MediaPlayer状态转换:单向箭头代表同步方法回调,而双向箭头代表异步方法回调。


而具体状态转化和操作如下:


MediaPlayer在new出来之后或者调用了reset()方法之后就进入了Idle状态,直到调用release()方法进入End状态结束。

     

 

       在new出来之后和调用reset()方法之间有一点微小的差别,如果MediaPlayer仅仅只是new出来而没有调用reset()方法,播放器内部的播放引擎和对象的状态都还没有改变,如果此时调用getCurrentPosition()、getDuration()、getVideoHeight()、getVideoHeigh()、setVideoStreamType(int)、setLooping(boolean)、setVolume(float,float)、pause()、start()、stop()、seekTo(int)、prepare()和prepareAsync()方法都无法返回,因为框架无法回调客户端程序注册的OnErrorListener.OnError()方法,调用reset()方法之后,调用这些方法的错误信息就将被OnError()方法捕捉并返回。

       MediaPlayer对象一旦确定不再使用就应该立即调用release()方法,释放与MediaPlayer对象关联的资源,以免占有硬件资源。导致之后创建的MediaPlayer对象无法使用资源。

 


        MediaPlayer方法可以调用多个重载的setDataSource()方法从idle状态进入initialized状态。如果调用setDataSource()方法的时候,MediaPlayer对象不是出于idle状态,会报出IllegalStateException异常。SetDataSource()方法在调用的时候可能会发生IllegalArgumentException和IOException。

       如果MediaPlayer是调用的自己的重载方法Create()传入资源文件的,那么此时MediaPlayer没有进入initialized状态,而是直接进入了prepared状态。

       MediaPlayer可以调用prepared()方法和preparedAsync()方法进入prepared状态。调用prepared()方法直接进入parpared状态,调用preparedAsync()方法会进入preparing状态并返回,内部的播放引擎会继续完成未完成的工作。这两个方法可能发生IllegalStateException异常。

       进入prepared状态后,会自动调用客户端程序注册的OnPreparedListener.OnPrepared()方法,可以在此方法里对MediaPlayer对象进行播放,及各种数据的获得,以及调整音量或者屏幕尺寸等操作。

       在prepared状态下就可以调用start()方法进行播放了,此时进入started()状态,处于此状态下再次调用start()方法则没有影响。此状态下也会自动调用客户端注册的OnBufferingUpdateListener.OnBufferingUpdate()回调方法,对流播放缓冲的状态进行追踪。




        pause()方法和start()方法是对应的,调用pause()方法会进入paused状态,调用start()方法继续播放。

        stop()方法会使处于started、paused、prepared、playbackCompleted状态的MediaPlayer对象进入stoped状态,播放停止。

        seekTo()方法可以调整播放的位置。seekTo方法是异步执行的,所以它可以马上返回。但是对于流媒体的播放,可能seekTo()方法会需要几秒钟的时间去完成。当seekTo完成时,会调用客户端注册的OnSeekCompleteListener.OnSeekComplete()回调方法。可以在此方法里做一些播放屏幕上的更新变化,比如发送隐藏控制界面的消息。

       当资源播放完毕时,如果调用了setLooping(boolean)方法,会自动进入started状态重新播放,如果没有调用则会自动调用客户端播放器注册的OnCompletionListener.OnCompletion()方法,此时MediaPlayer对象进入playbackCompleted状态,在此状态里可以调用start()方法重新进入started状态。



       播放View是继承SurfaceView的自定义View,继承SurfaceView后可以注册surfaceHolder的callback回调接口,实现其surfaceCreated()、surfaceChanged()及surfaceDestoryed()方法,surfaceCreated()方法在自定义播放View被创建的时候调用,surfaceChanged()方法在其改变的时候调用,surfaceDestoryed()方法在其销毁的时候调用。SurfaceHolder的生命周期是MediaPlayer在播放音频和视频时候的最大区别。通过SurfaceHolder的三个生命周期函数可以创建和释放某些资源。

       Android内置的播放器并不是可以播放所有格式的视频文件,不能播放时videoHeight=0,videoWidth=0,以此来判断是否播放视频。

       有的视频尺寸和播放View不一致时,可以重写OnMeasure(int,int)方法去调整视频播放时候的尺寸,以适应整个屏幕。其中在重写OnMeasure(int,int)方法时需要注意必须调用setMeasuredDimension(int,int)方法。


看完本文有收获?请分享给更多人


Java和Android架构

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多