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