使用SurfaceView&MediaPlayer播放视频

SurfaceView

关于SurfaceView 的api

个人理解:SurfaceView跟普通的如TextView、Button等不一样,它跟它的视图容器并不是在同一个视图层上,它的 UI 显示也可以不在一个独立的线程中完成,所以对 SurfaceView 的绘制并不会影响到主线程的运行。如果需要在另外的线程绘制界面或者渲染UI界面需要较长时间则可以选择使用SurfaceView。
使用SurfaceView常与SurfaceHolder 及surfaceHolder.callback一块使用 还可以实例化一个Runnable 在run方法中绘制View在绘画开始需要
Canvas mCanvas = mHolder.lockCanvas(); // 获得画布对象 。在绘画结束 时需要
mHolder.unlockCanvasAndPost(mCanvas); // 完成画画,把画布显示在屏幕。

private SurfaceHolder mSurfaceHolder;
private SurfaceView mSurfaceView;
mSurfaceView = (SurfaceView) view.findViewById(R.id.surfaceView);
        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.addCallback(new HoldCallback());

private class HoldCallback implements SurfaceHolder.Callback {

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            //当Surface尺寸等参数改变时触发
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            //此处耗时操作的开始
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder){ 
            //耗时操作结束释放资源等
        }
    }

MediaPlayer

MediaPlayer的API
谈起MediaPlayer不看安卓关于播放的图就说不过去
这里写图片描述
MediaPlayer关于播放器所有的操作按照这张图。能用代码解决的不废话。
说明:

  1. 每一个方法的调用必须在MediaPlayer特定的状态中prepareAsync()在{Idle, Prepared, Started, Paused, PlaybackCompleted, Error}就会出错;
  2. MediaPlayer在执行播放动作前必须指定加载视频的SurfaceHolder mMediaPlayer.setDisplay(mSurfaceHolder);否者就会只有声音而没有图像,同时也需要设置这个媒体播放器的音频流类型mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);且这个方法必须在prepareAsync(),或者prepare();方法前。
  3. 可能用到的方法getDuration();//获取视频时长、getCurrentPosition();//当前播放的时间seekTo(int msec) //选择时段播放
  4. 加载字幕mMediaPlayer.addTimedTextSource(path, MediaPlayer.MEDIA_MIMETYPE_TEXT_SUBRIP);
  5. 获取视频的缩略图Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(path,
    MediaStore.Video.Thumbnails.MINI_KIND);
  6. 从ContentResolver 中获取视频列表传入合适的URI即可,如:Media.EXTERNAL_CONTENT_URI 、Media.INTERNAL_CONTENT_URI
    public final Cursor query(Uri uri, String[] projection,
    String selection, String[] selectionArgs, String sortOrder) {
    return query(uri, projection, selection, selectionArgs, sortOrder, null);
    }
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <SurfaceView
        android:id="@+id/surfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <LinearLayout
        android:id="@+id/ll_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="#33000000"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:paddingBottom="10dp"
        android:paddingTop="10dp" >

        <LinearLayout
            android:id="@+id/img_play"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_marginLeft="5dp"
            android:gravity="center"
            android:visibility="gone" >

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clickable="false"
                android:src="@mipmap/vedio_play" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/img_pause"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_marginLeft="30dp"
            android:layout_marginStart="30dp"
            android:gravity="center"
            android:visibility="visible" >

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clickable="false"
                android:src="@mipmap/zanting" />
        </LinearLayout>

        <TextView
            android:id="@+id/tv_current_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="2dp"
            android:layout_marginRight="2dp"
            android:text="00:00"
            android:textColor="#ffffff"
            android:textSize="14sp" />

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" >

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

        <LinearLayout
            android:id="@+id/iv_resize"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="center_vertical"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:paddingRight="5dp" >

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:gravity="bottom"
                android:orientation="horizontal" >

                <TextView
                    android:id="@+id/tv_duration_time"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="2dp"
                    android:layout_marginRight="2dp"
                    android:text="00:00"
                    android:textColor="#acacac"
                    android:textSize="14sp" />
            </LinearLayout>

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="5dp"
                android:layout_marginRight="10dp"
                android:clickable="false"
                android:src="@mipmap/quanp" />
        </LinearLayout>
    </LinearLayout>
</RelativeLayout>

这里写图片描述

package me.itangqi.waveloadingview.view;

import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.SeekBar;
import android.widget.TextView;

import java.io.IOException;

import me.itangqi.waveloadingview.R;

public class MediaPlayerActivity extends AppCompatActivity {
    private String TAG = MediaPlayerActivity.class.getSimpleName();
    private SurfaceHolder mSurfaceHolder;
    private SurfaceView mSurfaceView;
    private MediaPlayer mMediaPlayer;
    private SeekBar mSeekBar;
    private static final  int MESSAGE_UPDATE_TIME = 0x01;
    private TextView mDurationTime ;
    private TextView mCurrentTime ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().hide();
        setContentView(R.layout.activity_media_player);
        initView();
    }

    private void initView() {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); // 屏幕常亮
        mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.addCallback(new HoldCallback());
        mSeekBar = (SeekBar) findViewById(R.id.seekbar);
        mDurationTime = (TextView) findViewById(R.id.tv_duration_time);
        mCurrentTime= (TextView) findViewById(R.id.tv_current_time);
        seekBarListener();
    }

    private class HoldCallback implements SurfaceHolder.Callback {

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            Log.i(TAG, "--surfaceChanged");
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            Log.i(TAG, "--surfaceCreated");
            String path = Environment.getExternalStorageDirectory().getPath()+"/yimaoshow/media/local/yimaosl.mp4";
            initMedia();
            if (mSurfaceHolder.getSurface().isValid()) {
                mMediaPlayer.reset();
                try {
                    // 设置音乐流
                    mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                    // 设置播入文件地址
                    mMediaPlayer.setDataSource(path);
                    mMediaPlayer.setDisplay(mSurfaceHolder);
                    mMediaPlayer.prepareAsync();

                } catch (IOException e) {

                }

            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            Log.i(TAG, "--surfaceDestroyed");
            if (mMediaPlayer != null) {
                if (mMediaPlayer.isPlaying()) {
                    mMediaPlayer.stop();
                    mMediaPlayer.release();
                    Log.d("VideoSurfaceView", "mMediaPlayer release");
                }
                mMediaPlayer = null;
            }
        }
    }

    private void initMedia() {
        if (mMediaPlayer == null) {

            mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

                @Override
                public void onCompletion(MediaPlayer mp) {

                }
            });

            mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {

                @Override
                public boolean onError(MediaPlayer mp, int what, int extra) {
                    Log.i(TAG, "视频播放中发生错误" + "what:"+what +"extra"+extra);
                    return false;
                }
            });

            mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

                @Override
                public void onPrepared(MediaPlayer mp) {
                    Log.i(TAG, "视频装载完毕");
                    if (mMediaPlayer != null) {
                        mMediaPlayer.start();
                        mSeekBar.setMax(mMediaPlayer.getDuration());
                        mDurationTime.setText(mMediaPlayer.getDuration()/1000+"");
                        updateTime();
                    }

                }

            });
        }
    }

    private void updateTime() {
        if (mMediaPlayer != null) {
            mSeekBar.setProgress(mMediaPlayer.getCurrentPosition());
            mHandler.sendEmptyMessageDelayed(MESSAGE_UPDATE_TIME, 1000);
            mCurrentTime.setText(mMediaPlayer.getCurrentPosition()/1000 +"");
        }
    }

    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MESSAGE_UPDATE_TIME:
                    updateTime();
                    break;
            }
        }
    };

    private void seekBarListener() {
        mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                mMediaPlayer.seekTo(seekBar.getProgress());
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

            }
        });

    }
}
发布了14 篇原创文章 · 获赞 1 · 访问量 8053

猜你喜欢

转载自blog.csdn.net/hua199237/article/details/52023247