視頻播放器

這裏寫圖片描述

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical">

    <SurfaceView
        android:id="@+id/sv"
        android:layout_width="match_parent"
        android:layout_height="300dp" />

    <SeekBar
        android:id="@+id/seekbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:text="00:00/00:00"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

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

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

        <Button
            android:id="@+id/stop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="停止"/>

        <Button
            android:id="@+id/replay"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="重播"/>

    </LinearLayout>

</LinearLayout>

MainActivity.class

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    /**SurfaceView內部採用雙緩存機制,它會緩存視頻中的流數據,將數據進行渲染之後推送到屏幕上做顯示。
       簡單來講,他就是一個顯示視頻的屏幕。*/
    private SurfaceView sv;
    private SurfaceHolder holder;
    private SeekBar seekbar;
    private MediaPlayer player;
    private TextView time;
    private Button play;
    private Button pause;
    private Button stop;
    private Button replay;
    private int duration;
    private boolean isUpdateBar;
    // 獲取視頻路徑
    String path = Environment.getExternalStorageDirectory() + "/Movies/Uptown Funk.mp4";

    // 播放器的幾個狀態,我們可以通過狀態碼來判斷
    public static final int PLAYING = 1; // 播放狀態
    public static final int PAUSING = 2; // 暫停狀態
    public static final int STOPPING = 3; // 停止狀態
    private int CURRENT = 0; // 當前狀態

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

        sv = findViewById(R.id.sv);
        seekbar = findViewById(R.id.seekbar);
        play = findViewById(R.id.play);
        pause = findViewById(R.id.pause);
        stop = findViewById(R.id.stop);
        replay = findViewById(R.id.replay);
        time = findViewById(R.id.time);

        play.setOnClickListener(this);
        pause.setOnClickListener(this);
        stop.setOnClickListener(this);
        replay.setOnClickListener(this);

        holder = sv.getHolder();
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 設置緩衝

        seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                //開始拖動seekbar的時候停止更新seekbar
                stopSeekBar();

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                //停止拖動seekbar的時候定位到相應的位置,並且開始更新seekbar
                if(player != null) {
                   if(CURRENT == PLAYING) {
                       player.seekTo(seekBar.getProgress());
                       updateSeekBar();
                   }
                }

            }
        });

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.play:
                try {

                    if (player != null) {
                        if (CURRENT == PLAYING) { //當前是播放狀態
                            return;
                        } else if (CURRENT == PAUSING) { // 當前是暫停狀態
                            player.seekTo(seekbar.getProgress());
                            player.start();
                            CURRENT = PLAYING;
                            updateSeekBar();
                            return;
                        }
                    }

                    if (CURRENT == 0 || CURRENT == STOPPING) { //如果是最開始的狀態或者是停止狀態
                        // 創建一個播放器對象
                        player = new MediaPlayer();
                        // 設置路徑
                        player.setDataSource(path);
                        // 準備
                        player.prepare();
                        // 獲取視頻最大的時長(毫秒爲單位)
                        duration = player.getDuration();
                        // 設置seekBar的最大值
                        seekbar.setMax(duration);
                        // 格式化最大時間
                        String lastTime = formatTime(duration);
                        time.setText("00:00/" + lastTime);
                        player.seekTo(seekbar.getProgress());
                        // 視頻開始播放
                        player.start();
                        // 更新seekBar
                        updateSeekBar();
                        // 設置輸出畫面
                        player.setDisplay(holder);
                        CURRENT = PLAYING;
                    }
                } catch(IOException e){
                    e.printStackTrace();
                }

                break;
            case R.id.pause: // 暫停
                if(player != null && CURRENT == PLAYING) {
                    player.pause();
                    stopSeekBar();
                    CURRENT = PAUSING;
                }
                break;
            case R.id.stop: // 停止播放
                if(player != null) {
                    if(CURRENT == PLAYING || CURRENT == PAUSING) {
                        stopSeekBar();
                        seekbar.setProgress(0);
                        time.setText("00:00/"+formatTime(duration));
                        player.stop(); // 播放器處於停止狀態 所有設置都清零
                        player.release(); // 釋放資源
                        CURRENT = STOPPING;
                    }
                }
                break;
            case R.id.replay: // 重播
                if(player != null) {
                    try{
                        player.reset(); // 播放器空閒狀態 要想播放必須重新設置路徑還要進入準備狀態
                        player.setDataSource(path);
                        player.prepare(); // 準備狀態
                        player.start();
                        CURRENT = PLAYING;
                    }catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                break;
                default:
                    break;
        }
    }

    //更新進度條
    private void updateSeekBar(){
        isUpdateBar = true;
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(isUpdateBar) {
                    // 每秒更新一次
                    SystemClock.sleep(1000);
                    if(player != null && CURRENT == PLAYING){
                        seekbar.setProgress(player.getCurrentPosition());
                        // 在主線程中更新UI
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                String current = formatTime(player.getCurrentPosition()); // 播放進度
                                String durationString = formatTime(duration); // 最大時間
                                time.setText(current + "/" + durationString);
                            }
                        });
                    }
                }
            }
        }).start();
    }

    private String formatTime(int duration) {
        int second = duration / 1000; // 先轉換成總秒數 270s
        int minute = second / 60; // 在轉換成總分鐘 4
        second = second - minute * 60; // 轉換成秒位置上的秒數 30s
        StringBuilder sb = new StringBuilder();
        sb.append(minute > 10 ? minute + "" : "0" + minute); // 04
        sb.append(":");
        sb.append(second > 10 ? second + "" : "0" + second);// 04:30
        return  sb.toString();
    }

    private void stopSeekBar(){
        isUpdateBar = false;
    }
}

媒體控制器
這裏寫圖片描述

MainActivity.class

public class MainActivity extends AppCompatActivity {
    /**videoView播放器*/
    private VideoView mVideoView;
    /**媒體控制器*/
    private MediaController mController;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 設置窗口格式爲半透明
        getWindow().setFormat(PixelFormat.TRANSLUCENT);
        setContentView(R.layout.activity_main);
        // 綁定videoView控件
        mVideoView = findViewById(R.id.video_view);
        // 創建MediaController對象
        mController = new MediaController(this);
        // 準備播放文件
        File video = new File(Environment.getExternalStorageDirectory()+"/Movies/小城大事-張學友.mp4");
        // 如果文件存在
        if(video.exists()) {
            mVideoView.setVideoPath(video.getPath());
            // 設置VideoView與Controller建立關聯
            mVideoView.setMediaController(mController);
            // 設置controller和videoView建立關聯
            mController.setMediaPlayer(mVideoView);
            //讓VideoView獲取焦點
            mVideoView.requestFocus();
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章