Android 視頻播放器 (二):使用MediaPlayer播放視頻

在 Android 視頻播放器 (一):使用VideoView播放視頻 咱們講了一下如何使用VideoView播放視頻,瞭解了基本的播放器的一些知識和內容。也知道VideoView內部封裝的就是MediaPlayer,本文就介紹如何使用MediaPlayer播放視頻。html

1、簡介

MediaPlayer是Android中的一個多媒體播放類,其提供的API能知足簡單的大部分音視頻的播放需求。android

下面簡單介紹一下MediaPlayer:數組

  • MediaPlayer是使用Surface進行視頻的展現的。
  • MediaPlayer只支持mp四、avi、3gp格式的視頻,支持格式相對單一。
  • MediaPlayer能夠播放網絡視頻,支持的網絡視頻的協議爲:Http協議和RTSP協議兩種。

2、MediaPlayer 使用方法

MediaPlayer 的提供的方法以下:網絡

  • void setDataSource(String path) :經過一個具體的路徑來設置MediaPlayer的數據源,path能夠是本地的一個路徑,也能夠是一個網絡路徑
  • void setDataSource(Context context, Uri uri): 經過給定的Uri來設置MediaPlayer的數據源,這裏的Uri能夠是網絡路徑或是一個ContentProvider的Uri。
  • void setDataSource(MediaDataSource dataSource) :經過提供的MediaDataSource來設置數據源
  • void setDataSource(FileDescriptor fd): 經過文件描述符FileDescriptor來設置數據源
  • int getCurrentPosition() :獲取當前播放的位置
  • int getAudioSessionId() :返回音頻的session ID
  • int getDuration() :獲得文件的時間
  • TrackInfo[] getTrackInfo() :返回一個track信息的數組
  • boolean isLooping (): 是否循環播放
  • boolean isPlaying(): 是否正在播放
  • void pause () :暫停
  • void start () :開始
  • void stop () : 中止
  • void prepare(): 同步的方式裝載流媒體文件。
  • void prepareAsync(): 異步的方式裝載流媒體文件。
  • void reset(): 重置MediaPlayer至未初始化狀態。
  • void release (): 回收流媒體資源。
  • void seekTo(int msec): 指定播放的位置(以毫秒爲單位的時間)
  • void setAudioStreamType(int streamtype) :指定流媒體類型
  • void setLooping(boolean looping) :設置是否單曲循環
  • void setNextMediaPlayer(MediaPlayer next) : 當前這個MediaPlayer播放完畢後,MediaPlayer next開始播放
  • void setWakeMode(Context context, int mode):設置CPU喚醒的狀態。
  • setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener listener) :網絡流媒體的緩衝變化時回調 
  • setOnCompletionListener(MediaPlayer.OnCompletionListener listener) :網絡流媒體播放結束時回調
  • setOnErrorListener(MediaPlayer.OnErrorListener listener) :發生錯誤時回調 
  • setOnPreparedListener(MediaPlayer.OnPreparedListener listener):當裝載流媒體完畢的時候回調。

Android經過MediaPlayer控制播放器的狀態的方式來控制媒體文件的播放,其中: session

  • prepare()和prepareAsync() 提供了同步和異步兩種方式設置播放器進入prepare狀態,須要注意的是,若是MediaPlayer實例是由create方法建立的,那麼第一次啓動播放前不須要再調用prepare()了,由於create方法裏已經調用過了。
  • start()是真正啓動文件播放的方法, 
  • pause()和stop()比較簡單,起到暫停和中止播放的做用, 
  • seekTo()是定位方法,可讓播放器從指定的位置開始播放,須要注意的是該方法是個異步方法,也就是說該方法返回時並不意味着定位完成,尤爲是播放的網絡文件,真正定位完成時會觸發OnSeekComplete.onSeekComplete(),若是須要是能夠調用setOnSeekCompleteListener(OnSeekCompleteListener)設置監聽器來處理的。 
  • release()能夠釋放播放器佔用的資源,一旦肯定再也不使用播放器時應當儘早調用它釋放資源。 
  • reset()可使播放器從Error狀態中恢復過來,從新會到Idle狀態。

使用MediaPlayer播放視頻的步驟以下:異步

  1. 建立MediaPlayer對象,並讓它加載指定的視頻文件;
  2. 在界面佈局文件中定義SurfaceView控件,或在程序中建立SurfaceView控件,併爲SurfaceView的SurfaceHolder添加Callback監聽器;
  3. 調用MediaPlayer對象的setDisney(SurfaceHolder sh)方法將所播放的視頻圖像輸出到指定的SurfaceView控制;
  4. 調用MediaPlayer的start()、stop()、pause()方法來控制視頻播放。
下圖是一個MediaPlayer對象被支持的播放控制操做驅動的聲明週期和狀態。其中,橢圓表明MediaPlayer可能駐留的狀態,弧線表示驅動MediaPlayer在各個狀態之間遷移的播放控制操做。這裏有兩種類型的弧線。由單箭頭開始的弧線表明同步方法調用,而以雙箭頭開頭的弧線表明異步方法調用。

 

3、使用MediaPlayer實現視頻播放

下面咱們將展現如何使用MediaPlayer播放香港衛視的視頻流:ide

1. 聲明權限

須要在AndroidManifest.xml添加權限。oop

<uses-permission android:name="android.permission.INTERNET" />

2. 編寫SurfaceView佈局

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <SurfaceView
            android:id="@+id/surface_view"
            android:layout_width="match_parent"
            android:layout_height="195dp" />
    </LinearLayout>
</android.support.constraint.ConstraintLayout>

3. 編寫播放視頻代碼

public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {

    SurfaceView surfaceView;

    SurfaceHolder surfaceHolder;

    MediaPlayer mediaPlayer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        surfaceView = findViewById(R.id.surface_view);

        surfaceHolder = surfaceView.getHolder();

        surfaceHolder.addCallback(this);

        mediaPlayer = new MediaPlayer();

        try {
            mediaPlayer.setDataSource("http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                mp.start();
            }
        });
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Surface surface = holder.getSurface();
        mediaPlayer.setSurface(surface);
        mediaPlayer.prepareAsync();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }
}

4、MediaPlayer使用注意事項

  1. 在使用start()播放流媒體以前,須要裝載流媒體資源。這裏最好使用prepareAsync()用異步的方式裝載流媒體資源。由於流媒體資源的裝載是會消耗系統資源的,在一些硬件不理想的設備上,若是使用prepare()同步的方式裝載資源,可能會形成UI界面的卡頓,這是很是影響用於體驗的。由於推薦使用異步裝載的方式,爲了不尚未裝載完成就調用start()而報錯的問題,須要綁定MediaPlayer.setOnPreparedListener()事件,它將在異步裝載完成以後回調。異步裝載還有一個好處就是避免裝載超時引起ANR((Application Not Responding)錯誤。
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setDataSource(path);
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    // 經過異步的方式裝載媒體資源
    mediaPlayer.prepareAsync();
    mediaPlayer.setOnPreparedListener(new OnPreparedListener() {                    
         @Override
         public void onPrepared(MediaPlayer mp) {
              // 裝載完畢回調
              mediaPlayer.start();
         }
    });
  1. 使用完MediaPlayer須要回收資源。MediaPlayer是很消耗系統資源的,因此在使用完MediaPlayer,不要等待系統自動回收,最好是主動回收資源
    if (mediaPlayer != null && mediaPlayer.isPlaying()) {
          mediaPlayer.stop();
          mediaPlayer.release();
          mediaPlayer = null;
    }
相關文章
相關標籤/搜索