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

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


surfaceview的测量,视频缩略图


Android基于surfaceview与mediaplayer的视频播放器(android-studio)_第1张图片


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


Android基于surfaceview与mediaplayer的视频播放器(android-studio)_第2张图片


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


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





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
 * 

* 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("<< 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 weakReference; public MyHandler(Activity activity) { weakReference = new WeakReference(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 { 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; } }


Android基于surfaceview与mediaplayer的视频播放器(android-studio)_第3张图片 Android基于surfaceview与mediaplayer的视频播放器(android-studio)_第4张图片

你可能感兴趣的:(Android)