Android音視訊之MediaPlayer音視訊播放

總李寫程式碼發表於2016-06-15

前言:

      昨天總結了視訊錄製,今天來學習一下視訊的播放,Android的視訊播放主要採用MediaPlayer類。

MediaPlayer介紹

     MediaPlayer類可用於控制音訊/視訊檔案或流的播放。

MediaPlayer函式

 1.)例項化方式

使用直接new的方式:

  MediaPlayer mp = new MediaPlayer();

使用create的方式

MediaPlayer mp = MediaPlayer.create(this, R.raw.test);
  2.)設定播放源
setDataSource(String path)//指定裝載path路徑所代表的檔案。
setDataSource(Context context, Uri uri, Map<String, String headers)//指定裝載uri所代表的檔案。
setDataSource(Context context, Uri uri)//指定裝載uri所代表的檔案。
setDataSource(FileDescriptor fd, long offset, long length)//指定裝載fd所代表的檔案中從offset開始長度為length的檔案內容。
setDataSource(FileDescriptor fd)//指定裝載fd所代表的檔案。
 3.)配置播放引數
setAudioStreamType(int streamtype)//設定音訊流的型別。
setDisplay(SurfaceHolder sh)//設定顯示方式。
setLooping(boolean looping)//設定是否迴圈播放。
setNextMediaPlayer(MediaPlayer next)//設定當前流媒體播放完畢,下一個播放的MediaPlayer。
setScreenOnWhilePlaying(boolean screenOn)//設定是否使用SurfaceHolder來顯示。
setSurface(Surface surface)//設定Surface。
setVideoScalingMode(int mode)//設定視訊縮放的模式。
setVolume(float leftVolume, float rightVolume)//設定播放器的音量。
setWakeMode(Context context, int mode)//為MediaPlayer設定低階電源管理行為。
 4.)播放控制函式
start()//開始或恢復播放。
stop()//停止播放。
pause()//暫停播放。
prepare()//準備播放(裝載音訊),呼叫此方法會使MediaPlayer進入Prepared狀態。
prepareAsync()//準備播放非同步音訊。
release()//釋放媒體資源
reset()//重置MediaPlayer進入未初始化狀態。
seekTo(int msec)//指定的時間位置。
5.)監聽事件函式
setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener listener)//註冊一個回撥函式,在網路視訊流緩衝變化時呼叫。
setOnCompletionListener(MediaPlayer.OnCompletionListener listener)//為Media Player的播放完成事件繫結事件監聽器。
setOnErrorListener(MediaPlayer.OnErrorListener listener)//為MediaPlayer的播放錯誤事件繫結事件監聽器。
setOnPreparedListener(MediaPlayer.OnPreparedListener listener)//當MediaPlayer呼叫prepare()方法時觸發該監聽器。
setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener listener)//當MediaPlayer呼叫seek()方法時觸發該監聽器。
setOnVideoSizeChangedListener(MediaPlayer.OnVideoSizeChangedListener listener)//註冊一個用於監聽視訊大小改變的監聽器。
6.)獲取引數函式
getCurrentPosition()//獲取當前播放的位置。
getDuration()//獲取音訊的時長。
getVideoHeight()//獲取視訊的高度。
getVideoWidth()//獲取視訊的寬度。
isLooping()//判斷MediaPlayer是否正在迴圈播放。
isPlaying()//判斷MediaPlayer是否正在播放。

MediaPlayer音視訊播放示例

 1.)新增許可權
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 2.)視訊播放簡單示例
public class MediaPlayerActivity extends Activity implements SurfaceHolder.Callback, View.OnClickListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener {
    private MediaPlayer player;
    private SurfaceView surface;
    private SurfaceHolder surfaceHolder;
    private Button play, pause, stop;
    private SeekBar seekBar;
    private String videoPath;
    private int seekProgress;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_media_player);
        initParams();
        initViews();
    }

    private void initParams() {
        videoPath = getIntent().getStringExtra("videoPath");
    }


    private void initViews() {
        play = (Button) findViewById(R.id.btn_play);
        pause = (Button) findViewById(R.id.btn_pause);
        stop = (Button) findViewById(R.id.btn_stop);
        seekBar = (SeekBar) findViewById(R.id.skb_video);
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                seekProgress = progress * player.getDuration()
                        / seekBar.getMax();
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                seekTo(seekProgress);
            }
        });
        surface = (SurfaceView) findViewById(R.id.video_surface);
        surfaceHolder = surface.getHolder();
        surfaceHolder.setFormat(PixelFormat.TRANSPARENT);
        surfaceHolder.setKeepScreenOn(true);
        surfaceHolder.addCallback(this);
        play.setOnClickListener(this);
        pause.setOnClickListener(this);
        stop.setOnClickListener(this);
    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
    }

    @Override
    public void surfaceCreated(SurfaceHolder arg0) {
        autoPlay();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder arg0) {
        stop();
        release();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stop();
        release();
    }

    /**
     * 自動播放
     */
    private void autoPlay() {
        //必須在surface建立後才能初始化MediaPlayer,否則不會顯示影像
        player = new MediaPlayer();
        player.setAudioStreamType(AudioManager.STREAM_MUSIC);
        //設定顯示視訊顯示在SurfaceView上
        player.setDisplay(surfaceHolder);
        try {
            player.setDataSource(videoPath);
            player.setOnPreparedListener(this);
            player.setOnCompletionListener(this);
            player.setOnBufferingUpdateListener(this);
            player.prepare();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 開始播放
     */
    private void start() {
        if (player == null || player.isPlaying()) {
            return;
        }
        player.start();
    }

    /**
     * 暫停播放
     */
    private void pause() {
        if (player == null || player.isPlaying()) {
            return;
        }
        player.pause();
    }

    /**
     * 停止播放
     */
    private void stop() {
        if (player == null || player.isPlaying()) {
            return;
        }
        player.stop();
    }

    /**
     * 釋放資源
     */
    private void release() {
        if (player == null) {
            return;
        }
        player.release();
    }

    /**
     * 重置播放器
     */
    private void reset() {
        if (player == null) {
            return;
        }
        player.reset();
    }

    /**
     * 指定位置播放
     *
     * @param pos
     */
    private void seekTo(int pos) {
        if (player == null) {
            return;
        }
        player.seekTo(pos);
        start();
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_play:
                start();
                break;
            case R.id.btn_pause:
                pause();
                break;
            case R.id.btn_stop:
                stop();
                break;
        }
    }

    @Override
    public void onPrepared(MediaPlayer mp) {
        start();
    }

    @Override
    public void onBufferingUpdate(MediaPlayer mp, int percent) {
        seekBar.setSecondaryProgress(percent);
        int currentProgress = seekBar.getMax() * player.getCurrentPosition() / player.getDuration();
        Log.e("currentProgress", "currentProgress----->" + currentProgress);
    }

    @Override
    public void onCompletion(MediaPlayer mp) {
        seekBar.setProgress(0);
    }
}
3.)佈局檔案
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <SurfaceView
        android:id="@+id/video_surface"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_gravity="center"
        android:layout_weight="1" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal|bottom"
        android:orientation="vertical">

        <SeekBar
            android:id="@+id/skb_video"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_margin="10dp"
            android:max="100"
            android:focusable="true"
            android:maxHeight="4.0dip"
            android:minHeight="4.0dip"
            android:paddingLeft="16.0dip"
            android:paddingRight="16.0dip"
            android:thumb="@drawable/seekbar_thumb"
            android:progressDrawable="@drawable/po_seekbar" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal|bottom"
            android:layout_margin="10dp"
            android:gravity="center"
            android:orientation="horizontal">

            <Button
                android:id="@+id/btn_play"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="播放" />

            <Button
                android:id="@+id/btn_pause"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="暫停" />

            <Button
                android:id="@+id/btn_stop"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="停止" />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>
 4.)播放音訊簡單示例
         if (player == null) {
                player = new MediaPlayer();
                player.setDataSource(url);
                player.setVolume(0.7f, 0.7f);
                player.setAudioStreamType(AudioManager.STREAM_MUSIC);
                player.prepare();
                player.start();
                player.setOnCompletionListener(completionListener);
                player.setOnErrorListener(errorListener);
                return true;
            }
5.)知識擴充套件

  用上面的示例只能播放部分片源,有些片源會播放不了,所以我公司專案後來未採用原生的MediaPlayer進行視訊播放。這裡推薦大家使用B站開源視訊播放解決方案ijkplayer。地址:https://github.com/Bilibili/

 

      

相關文章