Android開發 MediaPlayer入門_播放本地視頻

前言

  MediaPlayer,能夠播放視頻/音頻,而且它支持本地和網絡文件的播放.本片博客做爲入門教程,先以最通俗的方式解釋播放文件本地視頻.(若是你嫌MediaPlayer仍是太麻煩能夠試試選擇VideoView)java

 

實現流程

  •   獲取權限
  •   保持屏幕常亮
  •   初始化SurfaceView的狀態監聽
  •   初始化MediaPlayer
  •   給MediaPlayer添加預覽SurfaceView的SurfaceHolder
  •   添加須要播放的視頻而且配置MediaPlayer
  •   播放視頻
  •   暫停視頻
  •   中止視頻
  •   釋放內存

 

獲取權限

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

播放本地視頻,那就須要讀寫存儲權限,注意別忘記了動態受權android

保持屏幕常亮

音視頻開發的基本操做,在xml的根佈局上添加下面這個屬性,也能夠在SurfaceView上添加數組

android:keepScreenOn="true"

初始化SurfaceView

做爲顯示播放視頻的曲面View,若是你還不瞭解它.那麼建議你先學習一些SurfaceView的知識.網絡

咱們須要監聽SurfaceView狀態,肯定它啓動完畢以後咱們在開始加載播放視頻.在onCreate執行下面的初始化initSurfaceviewStateListenersession

private void initSurfaceviewStateListener() {
        mSurfaceHolder = mVideoPlaySurfaceview.getHolder();
        mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                mMediaPlayer.setDisplay(holder);//給mMediaPlayer添加預覽的SurfaceHolder
                setPlayVideo(mPath);//添加播放視頻的路徑
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                Log.e(TAG, "surfaceChanged觸發: width=" + width + "height" + height);

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {

            }
        });
    }

surfaceCreated方法裏執行了2個方法:(固然能夠先不關注,下面依然會從新提到它們)app

  1. 給MediaPlayer添加預覽的SurfaceHolder.
  2. 添加播放視頻的路徑與配置MediaPlayer

初始化MediaPlayer

private void initMediaPalyer() {
        mMediaPlayer = new MediaPlayer();

    }

直接new,沒說明好說的,也是能夠先在onCreate執行initMediaPalyer異步

給MediaPlayer添加預覽SurfaceView的SurfaceHolder

SurfaceView初始化完成後直接給MediaPlayer設置SurfaceHolder >>>>> mMediaPlayer.setDisplay(holder);ide

mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                mMediaPlayer.setDisplay(holder);//給mMediaPlayer添加預覽的SurfaceHolder
                setPlayVideo(mPath);//添加播放視頻的路徑
            }

添加須要播放的視頻而且配置MediaPlayer

    private void setPlayVideo(String path) {
        try {
            mMediaPlayer.setDataSource(path);//設置播放視頻文件
            mMediaPlayer.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT);//縮放模式
            mMediaPlayer.setLooping(true);//設置循環播放
            mMediaPlayer.prepareAsync();//異步準備
//            mMediaPlayer.prepare();//同步準備,由於是同步在一些性能較差的設備上會致使UI卡頓
            mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { //準備完成回調
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mp.start();//啓動播放視頻
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
setPlayVideo方法,在surfaceCreated接口回調方法裏執行便可.上面已經有寫就不在重複交代了

播放視頻

private void startPlay(){
        if (!mMediaPlayer.isPlaying()){ //判斷視頻是否在播放
            mMediaPlayer.start();
        }
    }

暫停視頻

 private void pausePlay(){
        if (mMediaPlayer.isPlaying()){
            mMediaPlayer.pause();
        }
    }

中止視頻

private void stopPlay(){
        if (mMediaPlayer.isPlaying()){
            mMediaPlayer.stop();
        }
    }

釋放內存

這是必要的,由於MediaPlayer底層是運行C++的函數方法.不要使用後,必需釋放內存函數

@Override
    protected void onDestroy() {
        super.onDestroy();
        if (mMediaPlayer != null){
            if (mMediaPlayer.isPlaying()){
                mMediaPlayer.stop();
            }
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

 

API總彙

  • 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):當裝載流媒體完畢的時候回調。

 貼心周到,貼全demo代碼,給你查缺補漏

xml文件oop

 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:keepScreenOn="true"
    android:background="@color/colorBlack1"
    tools:context=".work.share.VideoPlayActivity">

    <SurfaceView
        android:id="@+id/video_play_surfaceview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintVertical_bias="0.5"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>

    <ImageView
        android:id="@+id/start_and_stop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_start"
        android:layout_marginBottom="50dp"
        android:layout_marginLeft="20dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

activity

 

 

import androidx.constraintlayout.widget.ConstraintLayout;
import android.content.pm.ActivityInfo;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageView;
import com.yt.kangaroo.R;
import com.yt.kangaroo.app.BaseActivity;
import java.io.File;
import java.io.IOException;
/**
 *@content:視頻播放activity
 *@time:2019-6-13
 *@build:
 */

public class VideoPlayActivity extends BaseActivity implements View.OnClickListener {
    private static final String TAG = VideoPlayActivity.class.getSimpleName();
    private SurfaceView mVideoPlaySurfaceview;
    private ImageView mStartAndStop;
    private MediaPlayer mMediaPlayer;
    private String mPath;
    private boolean isInitFinish = false;
    private SurfaceHolder mSurfaceHolder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        File file = new File(getExternalCacheDir(), "demo.mp4");
        mPath = file.getAbsolutePath();
        initMediaPalyer();
        initSurfaceviewStateListener();

    }

    @Override
    protected void onPause() {
        super.onPause();
        pausePlay();
    }

    @Override
    public int getLayout() {
        return R.layout.activity_video_play;
    }

    @Override
    public void initView() {
        mVideoPlaySurfaceview = findViewById(R.id.video_play_surfaceview);
        mStartAndStop = findViewById(R.id.start_and_stop);
        mStartAndStop.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.start_and_stop:
                if (mMediaPlayer.isPlaying()) {
                    pausePlay();
                    mStartAndStop.setImageResource(R.mipmap.ic_start);
                } else {
                    startPlay();
                    mStartAndStop.setImageResource(R.mipmap.ic_stop);
                }
                break;
            default:
                break;
        }

    }

    private void initSurfaceviewStateListener() {
        mSurfaceHolder = mVideoPlaySurfaceview.getHolder();
        mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                mMediaPlayer.setDisplay(holder);//給mMediaPlayer添加預覽的SurfaceHolder
                setPlayVideo(mPath);//添加播放視頻的路徑
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                Log.e(TAG, "surfaceChanged觸發: width=" + width + "height" + height);

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {

            }
        });
    }

    private void initMediaPalyer() {
        mMediaPlayer = new MediaPlayer();

    }

    private void setPlayVideo(String path) {
        try {
            mMediaPlayer.setDataSource(path);//
            mMediaPlayer.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT);//縮放模式
            mMediaPlayer.setLooping(true);//設置循環播放
            mMediaPlayer.prepareAsync();//異步準備
//            mMediaPlayer.prepare();//同步準備,由於是同步在一些性能較差的設備上會致使UI卡頓
            mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { //準備完成回調
                @Override
                public void onPrepared(MediaPlayer mp) {
                    isInitFinish = true;
                    mp.start();
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void startPlay(){
        if (!mMediaPlayer.isPlaying()){
            mMediaPlayer.start();
        }
    }

    private void stopPlay(){
        if (mMediaPlayer.isPlaying()){
            mMediaPlayer.stop();
        }
    }

    private void pausePlay(){
        if (mMediaPlayer.isPlaying()){
            mMediaPlayer.pause();
        }
    }

    private void seekTo(int time){
        mMediaPlayer.seekTo(time);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mMediaPlayer != null){
            if (mMediaPlayer.isPlaying()){
                mMediaPlayer.stop();
            }
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

}

 

end

相關文章
相關標籤/搜索