Android基于surfaceview与mediaplayer的视频播放器(android-studio)

Android Studio实战:SurfaceView与MediaPlayer打造视频播放器
该博客介绍了如何使用SurfaceView和MediaPlayer在Android Studio中实现一个视频播放器。内容包括视频的双击横屏、单击控制栏显示隐藏、手势控制播放进度及屏幕亮度和音量调节。同时,解决了重力感应切换横竖屏及手机固定屏幕时重力切换失效的问题,适合初学者学习。

最近闲来无事写了一个较为完整的视频播放器,但由于有了新的项目,就把这个搁浅了,就差一个横竖屏切换的时候切换不同的控制栏了,以及横屏的自动锁定了。


surfaceview的测量,视频缩略图




实现了双击横屏 单击控制栏的显示与隐藏,手势控制播放进度,屏幕亮度和音量的调节




重力切换横竖屏与点击切换横竖屏也解决了,手机固定屏幕重力切换失效也搞定了


由于并没有高度封装,很适合初学者,大神勿喷罗





package com.wyt.hcy.wyt_microclassroomapp;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.ThumbnailUtils;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.MediaController;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import Utils.ProjectUtils;
import wseemann.media.FFmpegMediaMetadataRetriever;

/**
 * created by  hcy 2016.8.4
 * <p>
 * bug: 只有声音没有图片
 * cause:
 * 1.在用SurfaceView播放视频时,如果处理不当,会出现有声音无图像的问题,主要的原因是,
 * 在调用MediaPlayer开始播放视频时,SurfaceView却还未创建成功,
 * 解决办法是判断SurfaceView创建成功后再调用MediaPlayer的播放,
 * 通过surfaceHolder的addCallBack()方法来监听surfaceCreated。
 * 2.注意测量的时间 应该在prepare之后
 * 应为在视频初始化时获得视频的高宽都为0 ,
 * 这个必须要注意,必须播放后延时 修改view 大小
 * bug:手动切换与自动切换横竖屏的冲突:手动点击横竖屏切换,手机再横竖屏就没法驱使
 * bug:屏幕切换时能够流畅的播放
 * bug:双击全屏
 * bug:横屏的锁屏机制
 * bug:手势操作:调节音量、亮度、快进、快退
 * bug:检测系统屏幕旋转的开关
 * bug:横竖屏切换不同风格的控制栏
 * bug:缓存进度与下载进度
 * bug:
 */

public class VideoPlayerActivity extends AppCompatActivity implements SurfaceHolder.Callback, MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener, MediaPlayer.OnInfoListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnSeekCompleteListener, MediaPlayer.OnVideoSizeChangedListener, MediaController.MediaPlayerControl, View.OnTouchListener, View.OnClickListener {
    private static final String TAG = "VideoPlayerActivity";
    private Display display;
    private SurfaceHolder surfaceHolder;//监控在底层表面上发生的事情
    private SurfaceView surfaceView;
    private MediaPlayer mediaPlayer;
    private int videoWidth;
    private int videoHeight;
    private MyHandler mHandler;
    private static final int MEASURE_VIDEO_SIZE = 1;//测量视频的大小
    private static final int CONTROLLER_AUTO_HIDE_TIME = 5000;//5s自动隐藏控制条
    private static final int PLAY_TIME = 0;
    private ImageView iv_play;
    private SeekBar seekbar;
    private TextView tv_start, tv_end;
    private ImageView iv_full;
    private ImageView imageView_main_show;//func:点击该按钮 ,按钮消失 ,视频播放
    private Timer timer;
    private SurfaceHolder currentSurfaceHolder;
    private boolean sennorFlag = true;
    private boolean stretch_flag = true;
    private int screenHeight;
    private int screenWidth;
    private SensorManager sm;
    private SensorManager sm2;
    private OrientationSensorListener listener;
    private OrientationSensorListener2 listener2;
    private Sensor sensor;
    private Sensor sensor2;
    private FrameLayout fl_controller;
    private String filepath;
    private ImageView iv_suolue;//缩略图
    private int currentPosition;//当前的播放位置
    private RelativeLayout rl_show;
    private ImageView iv_flag;
    private TextView tv_pro;
    /**
     * 手势控制
     */
    private GestureDetector gestureDetector;

    private ImageView iv_lock;


    public interface GestureOperationHelper {


        void SingleTap();
    }

    private GestureOperationHelper gestureOperationHelper;

    private static enum GestureOperationType {

        NONE,//无手势操作类型

        VOLUME,//音量

        BRIGHTNESS,//亮度

        FASTFORWARDORBACKWARD,//快进  快退

    }

    private GestureOperationType mGestureOperationType = GestureOperationType.NONE;

    private AudioManager manager;

    private ImageView iv_voice;


    /**
     * 为了结局点击surfaceview与控制器出现与隐藏的联动bug
     * func:等上一个Runnable执行完才会执行下一个Runnable
     */

    private Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            if (fl_controller.getVisibility() == View.VISIBLE) {
                fl_controller.setVisibility(View.GONE);
                // isTimeUp = true;
                if (imageView_main_show.getVisibility() == View.VISIBLE && imageView_main_show.isSelected()) {
                    imageView_main_show.setVisibility(View.GONE);
                }
            }
        }
    };

    /**
     * 控制模块的显示或者隐藏
     */
    private void showOrHideController() {
        if (rl_show.getVisibility() == View.VISIBLE) {
            rl_show.setVisibility(View.GONE);
            mHandler.removeMessages(11);
        }


        if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
            //横屏的时候显现锁屏按钮

            iv_lock.setVisibility(View.VISIBLE);

        } else {
            iv_lock.setVisibility(View.GONE);
        }

        if (fl_controller.getVisibility() == View.VISIBLE) {


            fl_controller.setVisibility(View.GONE);

            iv_lock.setVisibility(View.GONE);
            if (imageView_main_show.getVisibility() == View.VISIBLE && imageView_main_show.isSelected()) {
                imageView_main_show.setVisibility(View.GONE);
            }
        } else {
            fl_controller.setVisibility(View.VISIBLE);
            mHandler.removeCallbacks(mRunnable);
            mHandler.postDelayed(mRunnable, CONTROLLER_AUTO_HIDE_TIME);


            if (mediaPlayer != null && mediaPlayer.isPlaying() && imageView_main_show.isSelected()) {

                imageView_main_show.setSelected(true);
                imageView_main_show.setVisibility(View.VISIBLE);
                Log.i("<<<???", imageView_main_show.isSelected() + "");
            }
        }


    }

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

        mHandler = new MyHandler(this);
        manager = (AudioManager) getSystemService(AUDIO_SERVICE);
        Log.i("TTTTT", "onCreate");
        initSurfaceView();
        initController();
        initGestureController();

    }

    /**
     * 初始化手势控制
     */

    private void initGestureController() {
        gestureOperationHelper = new GestureOperationHelper() {
            @Override
            public void SingleTap() {

            }
        };

        gestureDetector = new GestureDetector(VideoPlayerActivity.this, new GestureDetector.SimpleOnGestureListener() {


            //双击
            @Override
            public boolean onDoubleTap(MotionEvent e) {
                //双击横竖屏切换
                if (stretch_flag) {
                    //切换成横屏
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    stretch_flag = false;
                } else {
                    //切换成竖屏
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    stretch_flag = true;
                }
                return true;
            }

            @Override
            public void onShowPress(MotionEvent e) {
                super.onShowPress(e);
                showOrHideController();
            }

            /**
             * ,一次单独的轻击抬起操作,也就是轻击一下屏幕
             * @param e
             * @return
             */

            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                mHandler.postDelayed(mSwitchTitleRunnable, 200);
                return true;
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

                if (Math.abs(distanceX) > Math.abs(distanceY)) {
                    //如果X轴的绝对值大于Y轴的绝对值  说明此时在快进或者快退
                    Log.i("KKKKKK", "快进");
                    mGestureOperationType = GestureOperationType.FASTFORWARDORBACKWARD;
                } else {
                    if (e1.getX() < surfaceView.getWidth() / 2) {
                        //说名在屏幕的左侧,左侧调节亮度
                        Log.i("KKKKKK", "亮度");
                        mGestureOperationType = GestureOperationType.BRIGHTNESS;
                    } else {
                        //右侧调节音量
                        Log.i("KKKKKK", "音量");
                        mGestureOperationType = GestureOperationType.VOLUME;

                    }
                }


                return DealWithScrollGestureOperation(e1, e2, distanceX, distanceY);
            }
        });


    }


    private boolean DealWithScrollGestureOperation(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

        if (fl_controller.getVisibility() == View.VISIBLE) {
            fl_controller.setVisibility(View.GONE);
            imageView_main_show.setVisibility(View.GONE);
            iv_lock.setVisibility(View.GONE);
            mHandler.removeCallbacks(mRunnable);
        }

        rl_show.setVisibility(View.VISIBLE);
        if (mGestureOperationType == GestureOperationType.FASTFORWARDORBACKWARD) {
            //快进,快退操作的处理

            if (mediaPlayer == null || !mediaPlayer.isPlaying()) {
                //不执行
                return false;

            }

            if (iv_voice.getVisibility() == View.VISIBLE) {
                iv_voice.setVisibility(View.GONE);
            }

            /**
             * 向右边滑动disX为负数 向左边滑动disX为正数
             * func:无论快进还是快退都是一分钟
             *
             */

            int pos = mediaPlayer.getCurrentPosition();
            int total = mediaPlayer.getDuration();


            if (distanceX < 0) {
                //右话
                iv_flag.setImageResource(R.mipmap.fast);

                pos = pos + 1 * 10 * 1000;

            } else if (distanceX > 0) {
                //左话
                iv_flag.setImageResource(R.mipmap.rewind);
                pos = pos - 1 * 10 * 1000;
            }


            mHandler.removeMessages(11);
            mHandler.sendEmptyMessageDelayed(11, 5000);

            int progress = (int) ((pos / (float) total) * 100);

            // Log.i("GGGGG:",progress+" ");

            seekbar.setProgress(progress);

            if (pos < 0) {
                pos = 0;
            } else if (pos > total) {
                pos = total;
            }

            mediaPlayer.seekTo(pos);


            int currentPosition = mediaPlayer.getCurrentPosition();
            String start = null;

            if (currentPosition > 0) {
                start = formatTime(currentPosition);

            } else {
                start = "00:00";

            }

            String str = new StringBuffer().append(start).append("/").append(tv_end.getText().toString()).toString();
            tv_pro.setText(str);


        } else if (mGestureOperationType == GestureOperationType.VOLUME) {


            iv_flag.setImageResource(R.mipmap.huatong);

            iv_voice.setVisibility(View.VISIBLE);

            if (imageView_main_show.getVisibility() == View.VISIBLE) {
                imageView_main_show.setVisibility(View.GONE);
            }


            int maxVolume = manager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);

            int currentVolume = manager.getStreamVolume(AudioManager.STREAM_MUSIC);

            Log.i("音量:当前", currentVolume + "");

            Log.i("音量:最大", maxVolume + "");


            /*
             * 发现音量最小0 最大15
             */

            /**
             * 上滑是正数,下滑是负数
             */
            float percent = (distanceY / (float) surfaceView.getMeasuredHeight());
            float volumeOffsetAccurate = maxVolume * percent * 0.5f;

            int volumeOffset = (int) volumeOffsetAccurate;

            if (volumeOffset == 0 && Math.abs(volumeOffsetAccurate) > 0.2f) {
                if (distanceY > 0) {
                    volumeOffset = 1;
                } else if (distanceY < 0) {
                    volumeOffset = -1;
                }
            }

            currentVolume += volumeOffset;
            if (currentVolume < 0) {
                currentVolume = 0;
            } else if (currentVolume >= maxVolume) {
                currentVolume = maxVolume;
            }


            if (currentVolume == 0) {
                iv_voice.setImageResource(R.mipmap.vc_0);
            } else if (currentVolume <= 2) {
                iv_voice.setImageResource(R.mipmap.vc_1);
            } else if (currentVolume <= 4) {
                iv_voice.setImageResource(R.mipmap.vc_2);
            } else if (currentVolume <= 6) {
                iv_voice.setImageResource(R.mipmap.vc_3);
            } else if (currentVolume <= 8) {
                iv_voice.setImageResource(R.mipmap.vc_4);
            } else if (currentVolume <= 11) {
                iv_voice.setImageResource(R.mipmap.vc_5);
            } else if (currentVolume <= 14) {
                iv_voice.setImageResource(R.mipmap.vc_6);
            } else if (currentVolume == 15) {
                iv_voice.setImageResource(R.mipmap.vc_7);
            }
            tv_pro.setText(currentVolume * 100 / maxVolume + "%");
            mHandler.removeMessages(11);

            mHandler.sendEmptyMessageDelayed(11, 5000);

            manager.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume, 0);


        } else if (mGestureOperationType == GestureOperationType.BRIGHTNESS) {

            iv_flag.setImageResource(R.mipmap.video_brightness_bg);


            if (iv_voice.getVisibility() == View.VISIBLE) {
                iv_voice.setVisibility(View.GONE);
            }
            float percent = distanceY / (float) surfaceView.getMeasuredHeight();
            float currentBrightness = getBrightnessPercent(VideoPlayerActivity.this);
            float brightnessOffset = percent * 5;

            currentBrightness += brightnessOffset;
            if (currentBrightness < 0) {
                currentBrightness = 0;
            } else if (currentBrightness > 1) {
                currentBrightness = 1;
            }

            int progress = (int) (currentBrightness * 100);
            Log.i("FFFFF", progress + "");
            tv_pro.setText(progress + "%");
            setBrightness(VideoPlayerActivity.this, currentBrightness);

            mHandler.removeMessages(11);
            mHandler.sendEmptyMessageDelayed(11, 5000);
        }

        return true;
    }

    /**
     * 设置屏幕亮度
     */

    private void setBrightness(Activity activity, float percent) {


        if (activity == null) {
            return;
        }

        if (percent < 0.01f) {
            percent = 0.01f;
        } else if (percent > 1.0f) {
            percent = 1.0f;
        }

        WindowManager.LayoutParams params = activity.getWindow().getAttributes();

        params.screenBrightness = percent;
        activity.getWindow().setAttributes(params);

    }


    /**
     * 获得当前屏幕亮度
     *
     * @param activity
     * @return
     */
    private float getBrightnessPercent(Activity activity) {
        WindowManager.LayoutParams params = activity.getWindow().getAttributes();

        return params.screenBrightness;
    }

    private Runnable mSwitchTitleRunnable = new Runnable() {
        @Override
        public void run() {
            gestureOperationHelper.SingleTap();
        }
    };


    @Override
    protected void onStart() {
        super.onStart();
        Log.i("TTTTT", "onStart");
    }

    private void initSensor() {
        //初始化重力感应器,func:重力感应屏幕切换
        sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        //获得重力传感器
        sensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        listener = new OrientationSensorListener(mHandler);
        sm.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_UI);
        sm2 = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        sensor2 = sm2.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        listener2 = new OrientationSensorListener2();
        sm2.registerListener(listener2, sensor2, SensorManager.SENSOR_DELAY_UI);
    }

    private void initMediaPlayer() {
        /**
         * 获取屏幕宽高
         */
        display = getWindowManager().getDefaultDisplay();
        screenWidth = display.getWidth();
        screenHeight = display.getHeight();
        mediaPlayer = null;
        mediaPlayer = new MediaPlayer();
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);//边播放边缓冲
        mediaPlayer.setDisplay(currentSurfaceHolder);//指定mediaplayer用于播放
    /*    *
         * 监听视频播放结束*/

        mediaPlayer.setOnCompletionListener(this);
      /*  *
         * 播放视频出错的监听*/

        mediaPlayer.setOnErrorListener(this);
   /*     *
         *  注册一个回调函数,在有警告或错误信息时调用*/

        mediaPlayer.setOnInfoListener(this);
   /*     *
         *   注册一个回调函数,在视频预处理完成后调用。*/

        mediaPlayer.setOnPreparedListener(this);
       /* *
         * 注册一个回调函数,在seek操作完成后调用。*/

        mediaPlayer.setOnSeekCompleteListener(this);
      /*  *
         * 注册一个回调函数,在视频大小已知或更新后调用。*/

        mediaPlayer.setOnVideoSizeChangedListener(this);
        /**
         * 视频路径
         */
        filepath = ProjectUtils.getDiskCacheDir(this, "video") + "/test2.mp4";
        try {
            mediaPlayer.setDataSource(filepath);
            mediaPlayer.setLooping(false);//不重复
            mediaPlayer.prepareAsync();
        } catch (IOException e) {
            Log.i(TAG, "setDataSource-IOException:" + e.getMessage());
            //  finish();
        } catch (IllegalArgumentException e) {
            Log.i(TAG, "setDataSource-IllegalArgumentException:" + e.getMessage());
            // finish();
        } catch (IllegalStateException e) {
            Log.i(TAG, "setDataSource-IllegalStateException:" + e.getMessage());
            //  finish();
        }

        //初始化重力传感器
        initSensor();


    }

    /**
     * 控制条
     */
    private void initController() {
        fl_controller = (FrameLayout) findViewById(R.id.fl_controller);
        iv_play = (ImageView) findViewById(R.id.iv_play);
        iv_play.setSelected(false);
        seekbar = (SeekBar) findViewById(R.id.seekbar);
        tv_start = (TextView) findViewById(R.id.tv_start);
        tv_end = (TextView) findViewById(R.id.tv_end);
        iv_full = (ImageView) findViewById(R.id.iv_full);
        seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                //   mHandler.postDelayed()
                if (fromUser && mediaPlayer != null) {
                    currentPosition = progress * mediaPlayer.getDuration() / 100;


                    mediaPlayer.seekTo(currentPosition);
                }
            }


            /**
             * 正在拖动进度条 并且手指没有离开屏幕
             * @param seekBar
             */

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                //取消延时器
                mHandler.removeCallbacks(mRunnable);

            }

            /**
             * 手指拖动完毕  手机离开屏幕的时候触发
             * @param seekBar
             */

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                //让延时器启动
                mHandler.postDelayed(mRunnable, CONTROLLER_AUTO_HIDE_TIME);
            }
        });


        //播放&暂停
        iv_play.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 隐藏缩略图
                 */
                if (iv_suolue != null && iv_suolue.getVisibility() == View.VISIBLE) {
                    iv_suolue.setVisibility(View.GONE);
                }


                if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                    //正在播放 此时该暂停
                    try {

                        iv_play.setSelected(false);
                        mediaPlayer.pause();
                        //此时应该显示大暂停按钮
                        imageView_main_show.setSelected(false);
                        imageView_main_show.setVisibility(View.VISIBLE);
                    } catch (IllegalArgumentException e) {
                        Log.i(TAG, "iv_play播放暂停-IllegalArgumentException:" + e.getMessage());
                        finish();
                    } catch (IllegalStateException e) {
                        Log.i(TAG, "iv_play播放暂停-IllegalStateException:" + e.getMessage());
                        finish();
                    }

                } else if (mediaPlayer != null) {
                    try {
                        iv_play.setSelected(true);

                        mediaPlayer.start();
                        imageView_main_show.setSelected(true);
                        mHandler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                imageView_main_show.setVisibility(View.GONE);
                            }
                        }, 500);
                    } catch (IllegalArgumentException e) {
                        Log.i(TAG, "iv_play开始播放-IllegalArgumentException:" + e.getMessage());
                        finish();
                    } catch (IllegalStateException e) {
                        Log.i(TAG, "iv_play开始播放-IllegalStateException:" + e.getMessage());
                        finish();
                    }
                }
            }
        });

        /**
         * 全屏 或者 退出全屏 播放
         */
        iv_full.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("HHHH", "切换横屏)))" + stretch_flag);

                //  stretch_flag = sp1.getBoolean("stretch_flag", true);
                if (stretch_flag) {
                    //切换成横屏
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    stretch_flag = false;
                } else {
                    //切换成竖屏
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    stretch_flag = true;
                }


            }
        });


    }

    @Override
    public void start() {
        mediaPlayer.start();
    }

    @Override
    public void pause() {
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.pause();
        }
    }

    @Override
    public int getDuration() {
        return mediaPlayer.getDuration();
    }

    @Override
    public int getCurrentPosition() {
        return mediaPlayer.getCurrentPosition();
    }

    @Override
    public void seekTo(int pos) {
        mediaPlayer.seekTo(pos);
    }

    @Override
    public boolean isPlaying() {
        return mediaPlayer.isPlaying();
    }

    @Override
    public int getBufferPercentage() {
        return 0;
    }

    @Override
    public boolean canPause() {
        return true;
    }

    @Override
    public boolean canSeekBackward() {
        return true;
    }

    @Override
    public boolean canSeekForward() {
        return true;
    }

    @Override
    public int getAudioSessionId() {
        return 0;
    }

    /**
     * surfaceView的Touch监听
     *
     * @param v
     * @param event
     * @return
     */
    @Override
    public boolean onTouch(View v, MotionEvent event) {

        gestureDetector.onTouchEvent(event);
        return true;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.imageView_main_play:
                if (iv_suolue != null && iv_suolue.getVisibility() == View.VISIBLE) {
                    iv_suolue.setVisibility(View.GONE);
                }

                Log.i(TAG, "imageView_main_play::播放" + imageView_main_show.isSelected());
                //  if (mediaPlayer != null  && imageView_main_show.isSelected()&& mediaPlayer.isPlaying()) {
                //说明此时正在播放,播放按钮处于播放状态
                try {


                    if (mediaPlayer != null && imageView_main_show.isSelected() && mediaPlayer.isPlaying()) {
                        mediaPlayer.pause();
                        //此时控制条的播放组件应该是显示暂停状态
                        if (iv_play != null) {
                            iv_play.setSelected(false);
                            // iv_play.setImageResource(R.drawable.fvl_selector_play);
                        }
                        imageView_main_show.setSelected(false);


                    } else if (mediaPlayer != null && !imageView_main_show.isSelected()) {
                        imageView_main_show.setSelected(true);
                        mediaPlayer.start();
                        //此时控制条的播放组件应该是显示播放状态
                        if (iv_play != null) {
                            iv_play.setSelected(true);
                        }
                        imageView_main_show.setVisibility(View.GONE);
                    }


                } catch (IllegalArgumentException e) {
                    Log.i(TAG, "imageView_main_play-IllegalArgumentException:" + e.getMessage());
                    finish();
                } catch (IllegalStateException e) {
                    Log.i(TAG, "imageView_main_play-IllegalStateException:" + e.getMessage());

                }
                break;
        }
    }


    private class MyHandler extends Handler {

        private WeakReference<Activity> weakReference;

        public MyHandler(Activity activity) {
            weakReference = new WeakReference<Activity>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Activity activity = weakReference.get();
            if (activity != null) {

                switch (msg.what) {
                    case MEASURE_VIDEO_SIZE:
                        /**
                         * 测量的视频大小
                         */

                        /**
                         * 设置播放大小,如果视频的大小>显示器  设置显示器  反之 视频,取小的设置比率
                         */
                        videoWidth = mediaPlayer.getVideoWidth();
                        Log.i(TAG, "视频的宽度:" + videoWidth);
                        Log.i(TAG, "视频的宽度:::" + screenWidth);
                        videoHeight = mediaPlayer.getVideoHeight();
                        Log.i(TAG, "视频的高度:" + videoHeight);
                        Log.i(TAG, "视频的高度:::" + screenHeight);

                        // screenHeight = display.getHeight();

                        if (videoWidth > display.getWidth() || videoHeight > screenHeight) {
                            //视频的大小>显示器的大小
                            float heightRatio = (float) videoHeight / (float) screenHeight;//高度比率
                            float widthRatio = (float) videoWidth / (float) screenWidth;//宽度比率
                            if (heightRatio > widthRatio) {
                                videoHeight = (int) Math.ceil((float) videoHeight / heightRatio);
                                videoWidth = (int) Math.ceil((float) videoWidth / heightRatio);
                            } else {
                                videoHeight = (int) Math.ceil((float) videoHeight / widthRatio);
                                videoWidth = (int) Math.ceil((float) videoWidth / widthRatio);
                            }
                        }


                        surfaceView.setLayoutParams(new RelativeLayout.LayoutParams(videoWidth, videoHeight));


                        if (iv_suolue.getVisibility() == View.VISIBLE) {
                            iv_suolue.setVisibility(View.GONE);
                            new GetVideoBitmapAsyncTask(iv_suolue, surfaceView).execute(filepath);
                        }
                        break;
                    case PLAY_TIME:
                        if (mediaPlayer != null) {
                            try {
                                int currentPosition = mediaPlayer.getCurrentPosition();
                                if (currentPosition > 0) {
                                    int progress = (int) ((currentPosition / (float) mediaPlayer
                                            .getDuration()) * 100);
                                    Log.i("PRogress::", progress + "");
                                    seekbar.setProgress(progress);
                                    tv_start.setText(formatTime(currentPosition));
                                } else {
                                    tv_start.setText("00:00");
                                    seekbar.setProgress(0);
                                }
                            } catch (IllegalStateException ex) {
                                mediaPlayer.release();
                            }

                        }
                        break;
                    case 10001:
                        int orientation = msg.arg1;

                        if (orientation > 45 && orientation < 135) {

                        } else if (orientation > 135 && orientation < 225) {

                        } else if (orientation > 225 && orientation < 315) {

                            Log.i(TAG, "切换成横屏");

                            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                            sennorFlag = false;
                            stretch_flag = false;
                        } else if ((orientation > 315 && orientation < 360) || (orientation > 0 && orientation < 45)) {

                            Log.i(TAG, "切换成竖屏");
                            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                            sennorFlag = true;
                            stretch_flag = true;
                        }
                        break;
                    case 11:
                        rl_show.setVisibility(View.GONE);

                        if (imageView_main_show.isSelected() == false && imageView_main_show.getVisibility() == View.GONE) {
                            imageView_main_show.setVisibility(View.VISIBLE);
                        }
                        break;


                }

            }
        }
    }


    private void initSurfaceView() {
        surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
        iv_voice = (ImageView) findViewById(R.id.iv_voice);
        tv_pro = (TextView) findViewById(R.id.tv_pro);
        iv_suolue = (ImageView) findViewById(R.id.iv_suolue);
        rl_show = (RelativeLayout) findViewById(R.id.rl_show);
        iv_flag = (ImageView) findViewById(R.id.iv_flag);


        iv_lock = (ImageView) findViewById(R.id.iv_lock);//锁屏


        imageView_main_show = (ImageView) findViewById(R.id.imageView_main_play);
        imageView_main_show.setOnClickListener(this);
        imageView_main_show.setSelected(false);//初始状态  是处于暂停的状态
        surfaceHolder = surfaceView.getHolder();

        /**
         * 确保底层的表面是一个推送缓冲区表面,用于视频播放和摄像头的浏览
         */
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceView.setOnTouchListener(this);
        surfaceHolder.addCallback(this);

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Log.i(TAG, "surfaceCreated");
        currentSurfaceHolder = holder;
        initMediaPlayer();
    }

    /**
     * 当SurfaceView 的底层表面的宽度、高度或者其他参数发生变化时  调用
     *
     * @param holder
     * @param format
     * @param width
     * @param height
     */

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

    /*当销毁 SurfaceView的底层表面时,调用
     */

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.i(TAG, "surfaceDestroyed:");
    }

    @Override
    public void onCompletion(MediaPlayer mp) {
        Log.i(TAG, "onCompletion:");
        if (iv_play != null) {

            iv_play.setSelected(false);
        }


        if (imageView_main_show != null) {
            imageView_main_show.setSelected(false);
            imageView_main_show.setVisibility(View.VISIBLE);
        }


    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        Log.i(TAG, "onError:");
        //  initMediaPlayer();

        switch (what) {
            case -1004:
                Log.d(TAG, "MEDIA_ERROR_IO");
                break;
            case -1007:
                Log.d(TAG, "MEDIA_ERROR_MALFORMED");
                break;
            case 200:
                Log.d(TAG, "MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK");
                break;
            case 100:
                Log.d(TAG, "MEDIA_ERROR_SERVER_DIED");
                break;
            case -110:
                Log.d(TAG, "MEDIA_ERROR_TIMED_OUT");
                break;
            case 1:
                Log.d(TAG, "MEDIA_ERROR_UNKNOWN");
                break;
            case -1010:
                Log.d(TAG, "MEDIA_ERROR_UNSUPPORTED");
                break;
        }
        switch (extra) {
            case 800:
                Log.d(TAG, "MEDIA_INFO_BAD_INTERLEAVING");
                break;
            case 702:
                Log.d(TAG, "MEDIA_INFO_BUFFERING_END");
                break;
            case 701:
                Log.d(TAG, "MEDIA_INFO_METADATA_UPDATE");
                break;
            case 802:
                Log.d(TAG, "MEDIA_INFO_METADATA_UPDATE");
                break;
            case 801:
                Log.d(TAG, "MEDIA_INFO_NOT_SEEKABLE");
                break;
            case 1:
                Log.d(TAG, "MEDIA_INFO_UNKNOWN");
                break;
            case 3:
                Log.d(TAG, "MEDIA_INFO_VIDEO_RENDERING_START");
                break;
            case 700:
                Log.d(TAG, "MEDIA_INFO_VIDEO_TRACK_LAGGING");
                break;
        }
        /**
         * false:表明错误没有被处理 调用 onCompletion  此时mediaplayer处于错误状态
         */
        return false;
    }

    /**
     * 当出现关于播放媒体的特定信息或者需要发出警告的时候,将调用onInfo
     *
     * @param mp
     * @param what
     * @param extra
     * @return
     */

    @Override
    public boolean onInfo(MediaPlayer mp, int what, int extra) {
        Log.i(TAG, "onInfo:");
        if (what == MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING) {
            //当文件中的音频和视频数据不正确的交错的时候会触发
            Log.i(TAG, "onInfo:MEDIA_INFO_BAD_INTERLEAVING:" + extra);
        } else if (what == MediaPlayer.MEDIA_INFO_NOT_SEEKABLE) {
            //当媒体不能正确的定位
            Log.i(TAG, "onInfo:MEDIA_INFO_NOT_SEEKABLE:" + extra);
        } else if (what == MediaPlayer.MEDIA_INFO_UNKNOWN) {
            //媒体信息尚未指定或者未知
            Log.i(TAG, "onInfo:MEDIA_INFO_UNKNOWN:" + extra);
        } else if (what == MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING) {
            //无法播放视频或者音频太复杂或者码率过高
            Log.i(TAG, "onInfo:MEDIA_INFO_VIDEO_TRACK_LAGGING:" + extra);
        } else if (what == MediaPlayer.MEDIA_INFO_METADATA_UPDATE) {
            //当新的元数据可用时
            Log.i(TAG, "onInfo:MEDIA_INFO_METADATA_UPDATE:" + extra);
        }
        return false;
    }

    @Override
    public void onPrepared(MediaPlayer mp) {

        try {

             /*当不是全屏的时候才需要测量,才需要比较*/

            if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
                //因为配置文件中并未设置横竖屏

                mHandler.sendEmptyMessageDelayed(MEASURE_VIDEO_SIZE, 1000);

            } else if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {

                mHandler.sendEmptyMessageDelayed(MEASURE_VIDEO_SIZE, 1000);

            } else {

                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
                surfaceView.setLayoutParams(params);

            }
            //Log.i("屏幕方向:::", isLandScape + "");


            /**
             * 获取缩略图
             */


            tv_end.setText(formatTime(mediaPlayer.getDuration()));


            //初始化计时器

            timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    mHandler.sendEmptyMessage(PLAY_TIME);
                }
            }, 0, 1000);


        } catch (IllegalStateException e) {
            Log.i(TAG, "prepare-IllegalStateException:" + e.getMessage());
            finish();
        }


    }

    private String formatTime(long time) {
        SimpleDateFormat formatter = new SimpleDateFormat("mm:ss");
        return formatter.format(new Date(time));
    }


    @Override
    public void onSeekComplete(MediaPlayer mp) {
        Log.i(TAG, "onSeekComplete:");
    }

    /**
     * 当视频的大小发生变化的时候调用一次  当指定的数据源和读取视频的元数据后将至少调用它一次
     *
     * @param mp
     * @param width
     * @param height
     */
    @Override
    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
        Log.i(TAG, "onVideoSizeChanged:");
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return false;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i("TTTTT", "onDestroy");
    }

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

        Log.i("TTTTT", "onPause");
    }


    //重力感应监听


    public class OrientationSensorListener implements SensorEventListener {
        private static final int _DATA_X = 0;
        private static final int _DATA_Y = 1;
        private static final int _DATA_Z = 2;
        public static final int ORIENTATION_UNKNOWN = -1;
        private MyHandler myHandler;
        private boolean isSupportGravity = false;

        public OrientationSensorListener(MyHandler myHandler) {
            this.myHandler = myHandler;


        }

        public void onAccuracyChanged(Sensor arg0, int arg1) {
            // TODO Auto-generated method stub

        }

        public void onSensorChanged(SensorEvent event) {

            /**
             * 检测手机自动旋转屏幕的功能是否打开
             */
            isSupportGravity = isscreenAutoRotate();

            if (!isSupportGravity) {
                return;
            }

            if (sennorFlag != stretch_flag)  //只有两个不相同才开始监听行为
            {
                float[] values = event.values;
                int orientation = ORIENTATION_UNKNOWN;
                float X = -values[_DATA_X];
                float Y = -values[_DATA_Y];
                float Z = -values[_DATA_Z];
                float magnitude = X * X + Y * Y;
                // Don't trust the angle if the magnitude is small compared to the y value
                if (magnitude * 4 >= Z * Z) {
                    //屏幕旋转时
                    float OneEightyOverPi = 57.29577957855f;
                    float angle = (float) Math.atan2(-Y, X) * OneEightyOverPi;
                    orientation = 90 - (int) Math.round(angle);
                    // normalize to 0 - 359 range
                    while (orientation >= 360) {
                        orientation -= 360;
                    }
                    while (orientation < 0) {
                        orientation += 360;
                    }
                }
                if (myHandler != null) {
                    myHandler.obtainMessage(10001, orientation, 0).sendToTarget();
                }

            }
        }
    }


    public class OrientationSensorListener2 implements SensorEventListener {
        //初始化重力感应器的坐标轴
        private static final int sensor_X = 0;
        private static final int sensor_Y = 1;
        private static final int sensor_Z = 2;
        private static final int ORIENTATION_UNKNOW = -1;


        private boolean isSupportGravity = false;

        public OrientationSensorListener2() {


        }

        @Override
        public void onSensorChanged(SensorEvent event) {

            /**
             * 检测手机自动旋转屏幕的功能是否打开
             */

            isSupportGravity = isscreenAutoRotate();

            if (!isSupportGravity) {
                return;
            }

            float[] values = event.values;

            int orientation = ORIENTATION_UNKNOW;
            float X = -values[sensor_X];
            float Y = -values[sensor_Y];
            float Z = -values[sensor_Z];

            /**
             * 重力传感器监听手机的摆放状态的算法
             */
            float magnitude = X * X + Y * Y;
            // Don't trust the angle if the magnitude is small compared to the y value
            if (magnitude * 4 >= Z * Z) {
                //屏幕旋转时
                float OneEightyOverPi = 57.29577957855f;
                float angle = (float) Math.atan2(-Y, X) * OneEightyOverPi;
                orientation = 90 - (int) Math.round(angle);
                // normalize to 0 - 359 range
                while (orientation >= 360) {
                    orientation -= 360;
                }
                while (orientation < 0) {
                    orientation += 360;
                }
            }

            if (orientation > 225 && orientation < 315) {  //横屏
                sennorFlag = false;
            } else if ((orientation > 315 && orientation < 360) || (orientation > 0 && orientation < 45)) {  //竖屏
                sennorFlag = true;
            }

            if (stretch_flag == sennorFlag) {  //点击变成横屏  屏幕 也转横屏 激活
                Log.i(TAG, "激活");
                sm.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_UI);
            }
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {

        }
    }


    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        Log.i("TTTTT", "onConfigurationChanged");
        if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
            //如果是横屏
            Log.i("WWWWWW", "横屏");
            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            surfaceView.setLayoutParams(params);

            if (iv_suolue.getVisibility() == View.VISIBLE && !iv_play.isSelected() && !imageView_main_show.isSelected()) {
                iv_suolue.setVisibility(View.GONE);
                new GetVideoBitmapAsyncTask(iv_suolue, surfaceView).execute(filepath);
            }

        } else if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {

            mHandler.sendEmptyMessage(MEASURE_VIDEO_SIZE);
            Log.i("WWWWWW", "竖屏");
        } else if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {

            mHandler.sendEmptyMessage(MEASURE_VIDEO_SIZE);
            Log.i("WWWWWW", "无屏");
        }

    }


    /**
     * 获取屏幕的缩略图
     */

    private class GetVideoBitmapAsyncTask extends AsyncTask<String, Void, Bitmap> {

        private ImageView iv;
        private SurfaceView sv;

        public GetVideoBitmapAsyncTask(ImageView iv, SurfaceView sv) {
            this.iv = iv;
            this.sv = sv;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            /**
             * 第三方库获得视频里的缩略图
             */
            FFmpegMediaMetadataRetriever fmmr = new FFmpegMediaMetadataRetriever();
            try {
                fmmr.setDataSource(params[0]);
                Bitmap bitmap = fmmr.getFrameAtTime();
                if (bitmap != null) {
                    Bitmap b2 = fmmr
                            .getFrameAtTime(
                                    4000000,
                                    FFmpegMediaMetadataRetriever.OPTION_CLOSEST_SYNC);
                    if (b2 != null) {
                        bitmap = b2;
                    }
                    if (bitmap.getWidth() > 640) {// 如果图片宽度规格超过640px,则进行压缩
                        bitmap = ThumbnailUtils.extractThumbnail(bitmap,
                                640, 480,
                                ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
                    }

                    return bitmap;
                }
            } catch (IllegalArgumentException ex) {
                ex.printStackTrace();
            } finally {
                fmmr.release();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            if (bitmap != null && !iv_play.isSelected() && !imageView_main_show.isSelected()) {
                /**
                 * 缩略图的大小应该和surfaceview的大小一样,无论竖屏还是横屏
                 */
                ViewGroup.LayoutParams layoutParams = iv.getLayoutParams();
                ViewGroup.LayoutParams layoutParams1 = sv.getLayoutParams();
                layoutParams.width = layoutParams1.width;
                layoutParams.height = layoutParams1.height;
                iv.setLayoutParams(layoutParams);
                iv.setImageBitmap(bitmap);
                iv.setVisibility(View.VISIBLE);
            }
        }
    }


    /**
     * 检测手机自动旋转的是否打开
     *
     * @return
     */

    private boolean isscreenAutoRotate() {
        int gravity = 0;
        try {
            gravity = Settings.System.getInt(getContentResolver(), Settings.System.ACCELEROMETER_ROTATION);
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
            Log.i(TAG, "检测手机是否打开屏幕旋转出错");
        }
        return gravity == 1;
    }
}


评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值