1. 程式人生 > >SurfaceView+MediaPlayer 實現簡單的視訊播放

SurfaceView+MediaPlayer 實現簡單的視訊播放

一、實現原理

由於MediaPlayer沒有播放視訊的介面,所以需要通過SurfaceView顯示視訊。SurfaceView相當於一個容器,可以把內嵌的MediaPlayer的視訊資料顯示出來。

二、實現步驟

1、佈局檔案中新增SurfaceView控制元件

2、通過SurfaceView.getHolder()獲得SurfaceHolder

3、為SurfaceHolder新增一個Callback物件

4、重寫SurfaceView的Callback類,並在該類中的surfaceCreate()方法中,為MediaPlayer設定顯示控制元件(mediaPlayer.setDisplay(SurfaceHolder))

三、例項參考

該例實現了利用SurfaceView+MediaPlayer播放SD卡上儲存的視訊。

package com.example.pc.externalstoragetest;
import android.media.MediaPlayer;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.io.File;
import java.io.IOException;
import java.net.URL;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
     private URL url;
     private ImageView showPic;
     private SurfaceView sv ;
     private SurfaceHolder holder;
     private MediaPlayer mp;
     private int vWidth,vHeight;
     private Display currDisplay;
     private DownloadAsyncTask task;
     private ProgressBar pb;
     private Button startDownload,startPlay;
     private TextView showProgressNub;

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

        initView();
        holder=sv.getHolder();
        mp=new MediaPlayer();
        holder.addCallback(new SurfaceHolder.Callback(){

            @Override
            public void surfaceCreated(SurfaceHolder surfaceHolder) {

                mp.setDisplay(sv.getHolder());

            }

            @Override
            public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

            }
        });

    }

    private void StartPlay() {
        //url=new URL("http ://vt1.doubanio.com/201806051925/5a95ce9e62a5473be84dfbaa1b69302b/view/movie/M/402300072.mp4");
        currDisplay = this.getWindowManager().getDefaultDisplay();
        //獲取儲存在SD卡上的視訊檔案
        final String  path= Environment.getExternalStorageDirectory().getPath()+ File.separator+"dahuangfeng.mp4";

        try {
            //設定MediaPlayer的資料
            mp.setDataSource(path);
            mp.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }


        mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mediaPlayer) {
                adjustVideoSize();
                mp.start();
            }
        });
        mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mediaPlayer) {
                mp.stop();
            }
        });
        System.out.println("........已設定資源.........");


    }

    private void adjustVideoSize() {
        vWidth = mp.getVideoWidth();
        vHeight = mp.getVideoHeight();
        System.out.println("mp.getvideowith():"+mp.getVideoWidth());
        System.out.println("mp.getvideoheight():"+mp.getVideoHeight());
        System.out.println("currDisplay.getWidth():"+currDisplay.getWidth());
        System.out.println("currDisplay.getHeight():"+currDisplay.getHeight());

        if(vWidth > currDisplay.getWidth() || vHeight > currDisplay.getHeight()){
            //如果video的寬或者高超出了當前螢幕的大小,則要進行縮放
            float wRatio = (float)vWidth/(float)currDisplay.getWidth();
            float hRatio = (float)vHeight/(float)currDisplay.getHeight();

            //選擇大的一個進行縮放
            float ratio = Math.max(wRatio, hRatio);

            vWidth = (int)Math.ceil((float)vWidth/ratio);
            vHeight = (int)Math.ceil((float)vHeight/ratio);

            //設定surfaceView的佈局引數
            sv.setLayoutParams(new RelativeLayout.LayoutParams(vWidth, vHeight));

            //然後開始播放視訊
            //如果視訊寬度或高度小於SurfaceViewd的寬高,則調整將SurfaceView的寬高適應視訊。
        }else if(vWidth<currDisplay.getWidth()||vHeight<currDisplay.getHeight()){

            RelativeLayout.LayoutParams layoutParams= new RelativeLayout.LayoutParams(vWidth,vHeight);
            layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
            layoutParams.topMargin=20;
            sv.setLayoutParams(layoutParams);
        }
    }

    private void initView() {
        sv=findViewById(R.id.suView);
        pb=findViewById(R.id.progressBar0);
        showProgressNub=findViewById(R.id.showProgressNub);
        startDownload=findViewById(R.id.startDownload);
        startPlay=findViewById(R.id.startPlay);
        startDownload.setOnClickListener(this);
        startPlay.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {

        switch (view.getId()){
            case R.id.startDownload:
                task=new DownloadAsyncTask(pb,showProgressNub);
                task.execute();
                break;
            case R.id.startPlay:
                StartPlay();

                break;
        }

    }
}

效果圖