美文网首页android 开发程序员
MediaPlayer:昨个回顾了一下

MediaPlayer:昨个回顾了一下

作者: Arnold_J | 来源:发表于2017-04-23 15:26 被阅读0次

    最近项目需要用到 MediaPlayer + SurfaceView 来播放短视频,回忆了一下之前的做法写了一下,但是出现不少问题,这边干脆就看了一下 api 从头学习了一下。


    MediaPlayer

    参考:链接

    这个类主要用于音视频的播放,而使用它只要了解这个类的几个状态就能很好地运用。上面链接中有相应的状态图,我就不再费时画了。但是这个图是一定要看的,比我这长篇容易理解得多。


    一、快速使用:播放功能

    我们用 MediaPlayer 如果只是图个省事,可以通过下面的方式快速实现播放功能:

    • 1.创建 MediaPlayer 对象
    • 2.确认要加载的音视频流或文件:setDataSource()
    • 3.加载音视频流或文件:prepare()
    • 4.播放:start()

    这之后可以通过 pause()、stop()、release() 等方法进行控制,但是如果需要切换播放资源,则需先调用 reset() 方法使 MediaPlayer 对象回到 Idle 状态,才能再次调用 setDataSource() 切换资源。

    二、快速使用:setDataSource的使用

    如果是正在学习 Android 的新人,初次使用对于 setDataSource() 这个方法应该也会有疑惑,这里也讲解一下使用方法:

    Sets the data source as a content Uri.
    @param context the Context to use when resolving the Uri
    @param uri the Content URI of the data you want to play
    public void setDataSource(Context context, Uri uri)
    
    Sets the data source (file-path or http/rtsp URL) to use.
    @param path the path of the file, or the http/rtsp URL of the stream you want to play
    public void setDataSource(String path)
    
    Sets the data source (FileDescriptor) to use. It is the caller’s responsibility
    to close the file descriptor. It is safe to do so as soon as this call returns.
    @param fd the FileDescriptor for the file you want to play
    public void setDataSource(FileDescriptor fd)
    
    Sets the data source (FileDescriptor) to use. The FileDescriptor must be
    seekable (N.B. a LocalSocket is not seekable). It is the caller’s responsibility
    to close the file descriptor. It is safe to do so as soon as this call returns.
    @param fd the FileDescriptor for the file you want to play
    @param offset the offset into the file where the data to be played starts, in bytes
    @param length the length in bytes of the data to be played
    public void setDataSource(FileDescriptor fd, long offset, long length)
    

    上面是这个方法的多个不同参数的重载,现在对上面方法的使用进行说明:

    • setDataSource(Context context, Uri uri)
      假设 test.mp3 放在 res/raw/ 目录下
    mMediaPlayer= new MediaPlayer(); 
    Uri setDataSourceuri = Uri.parse("android.resource://"+getPackageName()+"/"+R.raw.test);
    mMediaPlayer.setDataSource(this, uri)
    
    • public void setDataSource(String path)
      这里可以直接填外部存储路径或者音视频 Url
      1.播放本地音视频:
    mMediaPlayer.setDataSource("/mnt/sdcard/test.mp3");
    

    2.播放网络音视频:

    Uri uri = Uri.parse("http://**");  
    mMediaPlayer.setDataSource(Context, uri);  
    
    • public void setDataSource(FileDescriptor fd, long offset, long length)
      假设 test.mp3 文件放在 assets 目录下
    AssetManager assetMg = this.getApplicationContext().getAssets();
    AssetFileDescriptor fileDescriptor = assetMg.openFd("test.mp3");  
    mMediaPlayer.setDataSource(fileDescriptor.getFileDescriptor(), fileDescriptor.getStartOffset(), fileDescriptor.getLength()); 
    

    三、状态讲解

    • Idle状态:当使用new()方法创建一个MediaPlayer对象或者调用了其reset()方法时,该MediaPlayer对象处于idle状态。在处于Idle状态时,调用getCurrentPosition(),getDuration(),getVideoHeight(),getVideoWidth(),setAudioStreamType(int), setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(int), prepare()或者 prepareAsync()方法都会出现相应错误。这两种方法的一个重要差别就是:当一个MediaPlayer对象刚被构建的时候,内部的播放引擎和对象的状态都没有改变,在这个时候调用以上的那些方法,框架将无法回调客户端程序注册的OnErrorListener.onError()方法,所以不会进入Error状态;但若这个MediaPlayer对象调用了reset()方法之后,再调用以上的那些方法,内部的播放引擎就会回调客户端程序注册的OnErrorListener.onError()方法,这时MediaPlayer会进入Error状态。
      提示:使用new操作符创建的MediaPlayer对象处于Idle状态,而那些通过重载的create()便利方法创建的MediaPlayer对象却不是处于Idle状态。事实上,如果成功调用了重载的create()方法,那么这些对象已经是Prepare状态了。

    • End状态:通过release()方法可以进入End状态,只要MediaPlayer对象不再被使用,就应当尽快将其通过release()方法释放掉,以释放相关的软硬件组件资源,这其中有些资源是只有一份的(相当于临界资源)。如果MediaPlayer对象进入了End状态,则不会再进入任何其他状态了。

    • Initialized状态:这个状态比较简单,MediaPlayer调用setDataSource()方法就进入Initialized状态,表示此时要播放的文件已经设置好了。
      提示:若当此MediaPlayer处于其它的状态下,调用setDataSource()方法,会抛出IllegalStateException异常。

    • Prepared状态:初始化完成之后还需要通过调用prepare()或prepareAsync()方法,这两个方法一个是同步的一个是异步的,只有进入Prepared状态,才表明MediaPlayer到目前为止都没有错误,可以进行文件播放。
      提示:在不合适的状态下调用prepare()和prepareAsync()方法会抛出IllegalStateException异常。当MediaPlayer对象处于Prepared状态的时候,可以调整音频/视频的属性,如音量,播放时是否一直亮屏,循环播放等。

    • Preparing状态:这个状态比较好理解,主要是和prepareAsync()配合,如果异步准备完成,会触发OnPreparedListener.onPrepared(),进而进入Prepared状态。

    • Started状态:显然,MediaPlayer一旦准备好,就可以调用start()方法,这样MediaPlayer就处于Started状态,这表明MediaPlayer正在播放文件过程中。可以使用isPlaying()测试MediaPlayer是否处于了Started状态。如果播放完毕,而又设置了循环播放,则MediaPlayer仍然会处于Started状态,类似的,如果在该状态下MediaPlayer调用了seekTo()或者start()方法均可以让MediaPlayer停留在Started状态。

    • Paused状态:Started状态下MediaPlayer调用pause()方法可以暂停MediaPlayer,从而进入Paused状态,MediaPlayer暂停后再次调用start()则可以继续MediaPlayer的播放,转到Started状态,暂停状态时可以调用seekTo()方法,这是不会改变状态的。

    • Stop状态:Started或者Paused状态下均可调用stop()停止MediaPlayer,而处于Stop状态的MediaPlayer要想重新播放,需要通过prepareAsync()和prepare()回到先前的Prepared状态重新开始才可以。

    • PlaybackCompleted状态:文件正常播放完毕,而又没有设置循环播放的话就进入该状态,并会触发OnCompletionListener的onCompletion()方法。此时可以调用start()方法重新从头播放文件,也可以stop()停止MediaPlayer,或者也可以seekTo()来重新定位播放位置。

    • Error状态:在一般情况下,由于种种原因一些播放控制操作可能会失败,如不支持的音频/视频格式,缺少隔行扫描的音频/视频,分辨率太高,流超时等原因,等等会触发会触发OnErrorListener.onError()事件,此时MediaPlayer会进入Error状态,及时捕捉并妥善处理这些错误是很重要的,可以帮助我们及时释放相关的软硬件资源,也可以改善用户体验。


    本想自己看看顺便翻译一点,结果捡了现成的翻译,参考链接:
    http://www.itnose.net/detail/6090452.html

    相关文章

      网友评论

        本文标题:MediaPlayer:昨个回顾了一下

        本文链接:https://www.haomeiwen.com/subject/jlfyzttx.html