package fm.jiecao.jcvideoplayer_lib; import android.content.Context; import android.content.pm.ActivityInfo; 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.os.Handler; import android.provider.Settings; import android.support.v7.app.ActionBar; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.Window; import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.SeekBar; import android.widget.TextView; import android.widget.Toast; import java.lang.reflect.Constructor; import java.util.Map; import java.util.Timer; import java.util.TimerTask; /** * Created by Nathen on 16/7/30. */ public abstract class JCVideoPlayer extends FrameLayout implements View.OnClickListener, SeekBar.OnSeekBarChangeListener, View.OnTouchListener { public static final String TAG = "JieCaoVideoPlayer"; public static boolean ACTION_BAR_EXIST = true; public static boolean TOOL_BAR_EXIST = true; public static int FULLSCREEN_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_SENSOR; public static int NORMAL_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; public static boolean SAVE_PROGRESS = true; public static boolean WIFI_TIP_DIALOG_SHOWED = false; public static final int FULLSCREEN_ID = 33797; public static final int TINY_ID = 33798; public static final int THRESHOLD = 80; public static final int FULL_SCREEN_NORMAL_DELAY = 300; public static long CLICK_QUIT_FULLSCREEN_TIME = 0; public static final int SCREEN_LAYOUT_NORMAL = 0; public static final int SCREEN_LAYOUT_LIST = 1; public static final int SCREEN_WINDOW_FULLSCREEN = 2; public static final int SCREEN_WINDOW_TINY = 3; public static final int CURRENT_STATE_NORMAL = 0; public static final int CURRENT_STATE_PREPARING = 1; public static final int CURRENT_STATE_PLAYING = 2; public static final int CURRENT_STATE_PLAYING_BUFFERING_START = 3; public static final int CURRENT_STATE_PAUSE = 5; public static final int CURRENT_STATE_AUTO_COMPLETE = 6; public static final int CURRENT_STATE_ERROR = 7; public static int BACKUP_PLAYING_BUFFERING_STATE = -1; public int currentState = -1; public int currentScreen = -1; public boolean loop = false; public Map<String, String> headData; public String url = ""; public Object[] objects = null; public int seekToInAdvance = 0; public ImageView startButton; public SeekBar progressBar; public ImageView fullscreenButton; public TextView currentTimeTextView, totalTimeTextView; public ViewGroup textureViewContainer; public ViewGroup topContainer, bottomContainer; protected static JCUserAction JC_USER_EVENT; protected static Timer UPDATE_PROGRESS_TIMER; protected int mScreenWidth; protected int mScreenHeight; protected AudioManager mAudioManager; protected Handler mHandler; protected ProgressTimerTask mProgressTimerTask; protected boolean mTouchingProgressBar; protected float mDownX; protected float mDownY; protected boolean mChangeVolume; protected boolean mChangePosition; protected boolean mChangeBrightness; protected int mGestureDownPosition; protected int mGestureDownVolume; protected float mGestureDownBrightness; protected int mSeekTimePosition; public JCVideoPlayer(Context context) { super(context); init(context); } public JCVideoPlayer(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public void init(Context context) { View.inflate(context, getLayoutId(), this); startButton = (ImageView) findViewById(R.id.start); fullscreenButton = (ImageView) findViewById(R.id.fullscreen); progressBar = (SeekBar) findViewById(R.id.bottom_seek_progress); currentTimeTextView = (TextView) findViewById(R.id.current); totalTimeTextView = (TextView) findViewById(R.id.total); bottomContainer = (ViewGroup) findViewById(R.id.layout_bottom); textureViewContainer = (ViewGroup) findViewById(R.id.surface_container); topContainer = (ViewGroup) findViewById(R.id.layout_top); startButton.setOnClickListener(this); fullscreenButton.setOnClickListener(this); progressBar.setOnSeekBarChangeListener(this); bottomContainer.setOnClickListener(this); textureViewContainer.setOnClickListener(this); textureViewContainer.setOnTouchListener(this); mScreenWidth = getContext().getResources().getDisplayMetrics().widthPixels; mScreenHeight = getContext().getResources().getDisplayMetrics().heightPixels; mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); mHandler = new Handler(); } public void setUp(String url, int screen, Object... objects) { if (!TextUtils.isEmpty(this.url) && TextUtils.equals(this.url, url)) { return; } this.url = url; this.objects = objects; this.currentScreen = screen; this.headData = null; setUiWitStateAndScreen(CURRENT_STATE_NORMAL); } @Override public void onClick(View v) { int i = v.getId(); if (i == R.id.start) { Log.i(TAG, "onClick start [" + this.hashCode() + "] "); if (TextUtils.isEmpty(url)) { Toast.makeText(getContext(), getResources().getString(R.string.no_url), Toast.LENGTH_SHORT).show(); return; } if (currentState == CURRENT_STATE_NORMAL || currentState == CURRENT_STATE_ERROR) { if (!url.startsWith("file") && !JCUtils.isWifiConnected(getContext()) && !WIFI_TIP_DIALOG_SHOWED) { showWifiDialog(); return; } prepareMediaPlayer(); onEvent(currentState != CURRENT_STATE_ERROR ? JCUserAction.ON_CLICK_START_ICON : JCUserAction.ON_CLICK_START_ERROR); } else if (currentState == CURRENT_STATE_PLAYING) { onEvent(JCUserAction.ON_CLICK_PAUSE); Log.d(TAG, "pauseVideo [" + this.hashCode() + "] "); JCMediaManager.instance().mediaPlayer.pause(); setUiWitStateAndScreen(CURRENT_STATE_PAUSE); } else if (currentState == CURRENT_STATE_PAUSE) { onEvent(JCUserAction.ON_CLICK_RESUME); JCMediaManager.instance().mediaPlayer.start(); setUiWitStateAndScreen(CURRENT_STATE_PLAYING); } else if (currentState == CURRENT_STATE_AUTO_COMPLETE) { onEvent(JCUserAction.ON_CLICK_START_AUTO_COMPLETE); prepareMediaPlayer(); } } else if (i == R.id.fullscreen) { Log.i(TAG, "onClick fullscreen [" + this.hashCode() + "] "); if (currentState == CURRENT_STATE_AUTO_COMPLETE) return; if (currentScreen == SCREEN_WINDOW_FULLSCREEN) { //quit fullscreen backPress(); } else { Log.d(TAG, "toFullscreenActivity [" + this.hashCode() + "] "); onEvent(JCUserAction.ON_ENTER_FULLSCREEN); startWindowFullscreen(); } } else if (i == R.id.surface_container && currentState == CURRENT_STATE_ERROR) { Log.i(TAG, "onClick surfaceContainer State=Error [" + this.hashCode() + "] "); prepareMediaPlayer(); } } public void prepareMediaPlayer() { JCVideoPlayerManager.completeAll(); Log.d(TAG, "prepareMediaPlayer [" + this.hashCode() + "] "); initTextureView(); addTextureView(); AudioManager mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); mAudioManager.requestAudioFocus(onAudioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); JCUtils.scanForActivity(getContext()).getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); JCMediaManager.CURRENT_PLAYING_URL = url; JCMediaManager.CURRENT_PLING_LOOP = loop; JCMediaManager.MAP_HEADER_DATA = headData; setUiWitStateAndScreen(CURRENT_STATE_PREPARING); JCVideoPlayerManager.setFirstFloor(this); } @Override public boolean onTouch(View v, MotionEvent event) { float x = event.getX(); float y = event.getY(); int id = v.getId(); if (id == R.id.surface_container) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.i(TAG, "onTouch surfaceContainer actionDown [" + this.hashCode() + "] "); mTouchingProgressBar = true; mDownX = x; mDownY = y; mChangeVolume = false; mChangePosition = false; mChangeBrightness = false; break; case MotionEvent.ACTION_MOVE: Log.i(TAG, "onTouch surfaceContainer actionMove [" + this.hashCode() + "] "); float deltaX = x - mDownX; float deltaY = y - mDownY; float absDeltaX = Math.abs(deltaX); float absDeltaY = Math.abs(deltaY); if (currentScreen == SCREEN_WINDOW_FULLSCREEN) { if (!mChangePosition && !mChangeVolume && !mChangeBrightness) { if (absDeltaX > THRESHOLD || absDeltaY > THRESHOLD) { cancelProgressTimer(); if (absDeltaX >= THRESHOLD) { // 全屏模式下的CURRENT_STATE_ERROR状态下,不响应进度拖动事件. // 否则会因为mediaplayer的状态非法导致App Crash if (currentState != CURRENT_STATE_ERROR) { mChangePosition = true; mGestureDownPosition = getCurrentPositionWhenPlaying(); } } else { //如果y轴滑动距离超过设置的处理范围,那么进行滑动事件处理 if (mDownX < mScreenWidth * 0.5f) {//左侧改变亮度 mChangeBrightness = true; WindowManager.LayoutParams lp = JCUtils.getAppCompActivity(getContext()).getWindow().getAttributes(); if (lp.screenBrightness < 0) { try { mGestureDownBrightness = Settings.System.getInt(getContext().getContentResolver(), Settings.System.SCREEN_BRIGHTNESS); Log.i(TAG, "current system brightness: " + mGestureDownBrightness); } catch (Settings.SettingNotFoundException e) { e.printStackTrace(); } } else { mGestureDownBrightness = lp.screenBrightness * 255; Log.i(TAG, "current activity brightness: " + mGestureDownBrightness); } } else {//右侧改变声音 mChangeVolume = true; mGestureDownVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); } } } } } if (mChangePosition) { int totalTimeDuration = getDuration(); mSeekTimePosition = (int) (mGestureDownPosition + deltaX * totalTimeDuration / mScreenWidth); if (mSeekTimePosition > totalTimeDuration) mSeekTimePosition = totalTimeDuration; String seekTime = JCUtils.stringForTime(mSeekTimePosition); String totalTime = JCUtils.stringForTime(totalTimeDuration); showProgressDialog(deltaX, seekTime, mSeekTimePosition, totalTime, totalTimeDuration); } if (mChangeVolume) { deltaY = -deltaY; int max = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); int deltaV = (int) (max * deltaY * 3 / mScreenHeight); mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mGestureDownVolume + deltaV, 0); //dialog中显示百分比 int volumePercent = (int) (mGestureDownVolume * 100 / max + deltaY * 3 * 100 / mScreenHeight); showVolumeDialog(-deltaY, volumePercent); } if (mChangeBrightness) { deltaY = -deltaY; int deltaV = (int) (255 * deltaY * 3 / mScreenHeight); WindowManager.LayoutParams params = JCUtils.getAppCompActivity(getContext()).getWindow().getAttributes(); if (((mGestureDownBrightness + deltaV) / 255) >= 1) {//这和声音有区别,必须自己过滤一下负值 params.screenBrightness = 1; } else if (((mGestureDownBrightness + deltaV) / 255) <= 0) { params.screenBrightness = 0.01f; } else { params.screenBrightness = (mGestureDownBrightness + deltaV) / 255; } JCUtils.getAppCompActivity(getContext()).getWindow().setAttributes(params); //dialog中显示百分比 int brightnessPercent = (int) (mGestureDownBrightness * 100 / 255 + deltaY * 3 * 100 / mScreenHeight); showBrightnessDialog(brightnessPercent); // mDownY = y; } break; case MotionEvent.ACTION_UP: Log.i(TAG, "onTouch surfaceContainer actionUp [" + this.hashCode() + "] "); mTouchingProgressBar = false; dismissProgressDialog(); dismissVolumeDialog(); dismissBrightnessDialog(); if (mChangePosition) { onEvent(JCUserAction.ON_TOUCH_SCREEN_SEEK_POSITION); JCMediaManager.instance().mediaPlayer.seekTo(mSeekTimePosition); int duration = getDuration(); int progress = mSeekTimePosition * 100 / (duration == 0 ? 1 : duration); progressBar.setProgress(progress); } if (mChangeVolume) { onEvent(JCUserAction.ON_TOUCH_SCREEN_SEEK_VOLUME); } startProgressTimer(); break; } } return false; } public int widthRatio = 0; public int heightRatio = 0; @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (currentScreen == SCREEN_WINDOW_FULLSCREEN || currentScreen == SCREEN_WINDOW_TINY) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); return; } if (widthRatio != 0 && heightRatio != 0) { int specWidth = MeasureSpec.getSize(widthMeasureSpec); int specHeight = (int) ((specWidth * (float) heightRatio) / widthRatio); setMeasuredDimension(specWidth, specHeight); int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(specWidth, MeasureSpec.EXACTLY); int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(specHeight, MeasureSpec.EXACTLY); getChildAt(0).measure(childWidthMeasureSpec, childHeightMeasureSpec); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } public void initTextureView() { removeTextureView(); JCMediaManager.textureView = new JCResizeTextureView(getContext()); JCMediaManager.textureView.setSurfaceTextureListener(JCMediaManager.instance()); } public void addTextureView() { Log.d(TAG, "addTextureView [" + this.hashCode() + "] "); FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER); textureViewContainer.addView(JCMediaManager.textureView, layoutParams); } public void removeTextureView() { JCMediaManager.savedSurfaceTexture = null; if (JCMediaManager.textureView != null && JCMediaManager.textureView.getParent() != null) { ((ViewGroup) JCMediaManager.textureView.getParent()).removeView(JCMediaManager.textureView); } } public void setUiWitStateAndScreen(int state) { currentState = state; switch (currentState) { case CURRENT_STATE_NORMAL: cancelProgressTimer(); if (isCurrentJcvd()) {//这个if是无法取代的,否则进入全屏的时候会releaseMediaPlayer JCMediaManager.instance().releaseMediaPlayer(); } break; case CURRENT_STATE_PREPARING: resetProgressAndTime(); break; case CURRENT_STATE_PLAYING: case CURRENT_STATE_PAUSE: case CURRENT_STATE_PLAYING_BUFFERING_START: startProgressTimer(); break; case CURRENT_STATE_ERROR: cancelProgressTimer(); break; case CURRENT_STATE_AUTO_COMPLETE: cancelProgressTimer(); progressBar.setProgress(100); currentTimeTextView.setText(totalTimeTextView.getText()); break; } } public void startProgressTimer() { cancelProgressTimer(); UPDATE_PROGRESS_TIMER = new Timer(); mProgressTimerTask = new ProgressTimerTask(); UPDATE_PROGRESS_TIMER.schedule(mProgressTimerTask, 0, 300); } public void cancelProgressTimer() { if (UPDATE_PROGRESS_TIMER != null) { UPDATE_PROGRESS_TIMER.cancel(); } if (mProgressTimerTask != null) { mProgressTimerTask.cancel(); } } public void onPrepared() { Log.i(TAG, "onPrepared " + " [" + this.hashCode() + "] "); if (currentState != CURRENT_STATE_PREPARING) return; if (seekToInAdvance != 0) { JCMediaManager.instance().mediaPlayer.seekTo(seekToInAdvance); seekToInAdvance = 0; } else { int position = JCUtils.getSavedProgress(getContext(), url); if (position != 0) { JCMediaManager.instance().mediaPlayer.seekTo(position); } } startProgressTimer(); setUiWitStateAndScreen(CURRENT_STATE_PLAYING); } public void clearFullscreenLayout() { ViewGroup vp = (ViewGroup) (JCUtils.scanForActivity(getContext()))//.getWindow().getDecorView(); .findViewById(Window.ID_ANDROID_CONTENT); View oldF = vp.findViewById(FULLSCREEN_ID); View oldT = vp.findViewById(TINY_ID); if (oldF != null) { vp.removeView(oldF); } if (oldT != null) { vp.removeView(oldT); } showSupportActionBar(getContext()); } public void onAutoCompletion() { //加上这句,避免循环播放video的时候,内存不断飙升。 Runtime.getRuntime().gc(); Log.i(TAG, "onAutoCompletion " + " [" + this.hashCode() + "] "); onEvent(JCUserAction.ON_AUTO_COMPLETE); dismissVolumeDialog(); dismissProgressDialog(); dismissBrightnessDialog(); cancelProgressTimer(); setUiWitStateAndScreen(CURRENT_STATE_AUTO_COMPLETE); if (currentScreen == SCREEN_WINDOW_FULLSCREEN) { backPress(); } JCUtils.saveProgress(getContext(), url, 0); } public void onCompletion() { Log.i(TAG, "onCompletion " + " [" + this.hashCode() + "] "); //save position if (currentState == CURRENT_STATE_PLAYING || currentState == CURRENT_STATE_PAUSE) { int position = getCurrentPositionWhenPlaying(); // int duration = getDuration(); JCUtils.saveProgress(getContext(), url, position); } cancelProgressTimer(); setUiWitStateAndScreen(CURRENT_STATE_NORMAL); // 清理缓存变量 textureViewContainer.removeView(JCMediaManager.textureView); JCMediaManager.instance().currentVideoWidth = 0; JCMediaManager.instance().currentVideoHeight = 0; AudioManager mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); mAudioManager.abandonAudioFocus(onAudioFocusChangeListener); JCUtils.scanForActivity(getContext()).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); clearFullscreenLayout(); JCUtils.getAppCompActivity(getContext()).setRequestedOrientation(NORMAL_ORIENTATION); JCMediaManager.textureView = null; JCMediaManager.savedSurfaceTexture = null; } //退出全屏和小窗的方法 public void playOnThisJcvd() { Log.i(TAG, "playOnThisJcvd " + " [" + this.hashCode() + "] "); //1.清空全屏和小窗的jcvd currentState = JCVideoPlayerManager.getSecondFloor().currentState; clearFloatScreen(); //2.在本jcvd上播放 setUiWitStateAndScreen(currentState); addTextureView(); } public void clearFloatScreen() { JCUtils.getAppCompActivity(getContext()).setRequestedOrientation(NORMAL_ORIENTATION); showSupportActionBar(getContext()); JCVideoPlayer currJcvd = JCVideoPlayerManager.getCurrentJcvd(); currJcvd.textureViewContainer.removeView(JCMediaManager.textureView); ViewGroup vp = (ViewGroup) (JCUtils.scanForActivity(getContext()))//.getWindow().getDecorView(); .findViewById(Window.ID_ANDROID_CONTENT); vp.removeView(currJcvd); JCVideoPlayerManager.setSecondFloor(null); } public static long lastAutoFullscreenTime = 0; //重力感应的时候调用的函数, public void autoFullscreen(float x) { if (isCurrentJcvd() && currentState == CURRENT_STATE_PLAYING && currentScreen != SCREEN_WINDOW_FULLSCREEN && currentScreen != SCREEN_WINDOW_TINY) { if (x > 0) { JCUtils.getAppCompActivity(getContext()).setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } else { JCUtils.getAppCompActivity(getContext()).setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); } startWindowFullscreen(); } } public void autoQuitFullscreen() { if ((System.currentTimeMillis() - lastAutoFullscreenTime) > 2000 && isCurrentJcvd() && currentState == CURRENT_STATE_PLAYING && currentScreen == SCREEN_WINDOW_FULLSCREEN) { lastAutoFullscreenTime = System.currentTimeMillis(); backPress(); } } public void onSeekComplete() { } public void onError(int what, int extra) { Log.e(TAG, "onError " + what + " - " + extra + " [" + this.hashCode() + "] "); if (what != 38 && what != -38) { setUiWitStateAndScreen(CURRENT_STATE_ERROR); if (isCurrentJcvd()) { JCMediaManager.instance().releaseMediaPlayer(); } } } public void onInfo(int what, int extra) { Log.d(TAG, "onInfo what - " + what + " extra - " + extra); if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) { if (currentState == CURRENT_STATE_PLAYING_BUFFERING_START) return; BACKUP_PLAYING_BUFFERING_STATE = currentState; setUiWitStateAndScreen(CURRENT_STATE_PLAYING_BUFFERING_START);//没这个case Log.d(TAG, "MEDIA_INFO_BUFFERING_START"); } else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) { if (BACKUP_PLAYING_BUFFERING_STATE != -1) { setUiWitStateAndScreen(BACKUP_PLAYING_BUFFERING_STATE); BACKUP_PLAYING_BUFFERING_STATE = -1; } Log.d(TAG, "MEDIA_INFO_BUFFERING_END"); } } public void onVideoSizeChanged() { Log.i(TAG, "onVideoSizeChanged " + " [" + this.hashCode() + "] "); if (JCMediaManager.textureView != null) { JCMediaManager.textureView.setVideoSize(JCMediaManager.instance().getVideoSize()); } } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { Log.i(TAG, "bottomProgress onStartTrackingTouch [" + this.hashCode() + "] "); cancelProgressTimer(); ViewParent vpdown = getParent(); while (vpdown != null) { vpdown.requestDisallowInterceptTouchEvent(true); vpdown = vpdown.getParent(); } } @Override public void onStopTrackingTouch(SeekBar seekBar) { Log.i(TAG, "bottomProgress onStopTrackingTouch [" + this.hashCode() + "] "); onEvent(JCUserAction.ON_SEEK_POSITION); startProgressTimer(); ViewParent vpup = getParent(); while (vpup != null) { vpup.requestDisallowInterceptTouchEvent(false); vpup = vpup.getParent(); } if (currentState != CURRENT_STATE_PLAYING && currentState != CURRENT_STATE_PAUSE) return; int time = seekBar.getProgress() * getDuration() / 100; JCMediaManager.instance().mediaPlayer.seekTo(time); Log.i(TAG, "seekTo " + time + " [" + this.hashCode() + "] "); } public static boolean backPress() { Log.i(TAG, "backPress"); if ((System.currentTimeMillis() - CLICK_QUIT_FULLSCREEN_TIME) < FULL_SCREEN_NORMAL_DELAY) return false; if (JCVideoPlayerManager.getSecondFloor() != null) { CLICK_QUIT_FULLSCREEN_TIME = System.currentTimeMillis(); JCVideoPlayer jcVideoPlayer = JCVideoPlayerManager.getSecondFloor(); jcVideoPlayer.onEvent(jcVideoPlayer.currentScreen == JCVideoPlayerStandard.SCREEN_WINDOW_FULLSCREEN ? JCUserAction.ON_QUIT_FULLSCREEN : JCUserAction.ON_QUIT_TINYSCREEN); JCVideoPlayerManager.getFirstFloor().playOnThisJcvd(); return true; } else if (JCVideoPlayerManager.getFirstFloor() != null && (JCVideoPlayerManager.getFirstFloor().currentScreen == SCREEN_WINDOW_FULLSCREEN || JCVideoPlayerManager.getFirstFloor().currentScreen == SCREEN_WINDOW_TINY)) {//以前我总想把这两个判断写到一起,这分明是两个独立是逻辑 CLICK_QUIT_FULLSCREEN_TIME = System.currentTimeMillis(); //直接退出全屏和小窗 JCVideoPlayerManager.getCurrentJcvd().currentState = CURRENT_STATE_NORMAL; JCVideoPlayerManager.getFirstFloor().clearFloatScreen(); JCMediaManager.instance().releaseMediaPlayer(); JCVideoPlayerManager.setFirstFloor(null); return true; } return false; } public void startWindowFullscreen() { Log.i(TAG, "startWindowFullscreen " + " [" + this.hashCode() + "] "); hideSupportActionBar(getContext()); JCUtils.getAppCompActivity(getContext()).setRequestedOrientation(FULLSCREEN_ORIENTATION); ViewGroup vp = (ViewGroup) (JCUtils.scanForActivity(getContext()))//.getWindow().getDecorView(); .findViewById(Window.ID_ANDROID_CONTENT); View old = vp.findViewById(FULLSCREEN_ID); if (old != null) { vp.removeView(old); } // ((ViewGroup)JCMediaManager.textureView.getParent()).removeView(JCMediaManager.textureView); textureViewContainer.removeView(JCMediaManager.textureView); try { Constructor<JCVideoPlayer> constructor = (Constructor<JCVideoPlayer>) JCVideoPlayer.this.getClass().getConstructor(Context.class); JCVideoPlayer jcVideoPlayer = constructor.newInstance(getContext()); jcVideoPlayer.setId(FULLSCREEN_ID); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); vp.addView(jcVideoPlayer, lp); jcVideoPlayer.setUp(url, JCVideoPlayerStandard.SCREEN_WINDOW_FULLSCREEN, objects); jcVideoPlayer.setUiWitStateAndScreen(currentState); jcVideoPlayer.addTextureView(); JCVideoPlayerManager.setSecondFloor(jcVideoPlayer); // final Animation ra = AnimationUtils.loadAnimation(getContext(), R.anim.start_fullscreen); // jcVideoPlayer.setAnimation(ra); CLICK_QUIT_FULLSCREEN_TIME = System.currentTimeMillis(); } catch (Exception e) { e.printStackTrace(); } } public void startWindowTiny() { Log.i(TAG, "startWindowTiny " + " [" + this.hashCode() + "] "); onEvent(JCUserAction.ON_ENTER_TINYSCREEN); if (currentState == CURRENT_STATE_NORMAL || currentState == CURRENT_STATE_ERROR) return; ViewGroup vp = (ViewGroup) (JCUtils.scanForActivity(getContext()))//.getWindow().getDecorView(); .findViewById(Window.ID_ANDROID_CONTENT); View old = vp.findViewById(TINY_ID); if (old != null) { vp.removeView(old); } textureViewContainer.removeView(JCMediaManager.textureView); try { Constructor<JCVideoPlayer> constructor = (Constructor<JCVideoPlayer>) JCVideoPlayer.this.getClass().getConstructor(Context.class); JCVideoPlayer jcVideoPlayer = constructor.newInstance(getContext()); jcVideoPlayer.setId(TINY_ID); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(400, 400); lp.gravity = Gravity.RIGHT | Gravity.BOTTOM; vp.addView(jcVideoPlayer, lp); jcVideoPlayer.setUp(url, JCVideoPlayerStandard.SCREEN_WINDOW_TINY, objects); jcVideoPlayer.setUiWitStateAndScreen(currentState); jcVideoPlayer.addTextureView(); JCVideoPlayerManager.setSecondFloor(jcVideoPlayer); } catch (InstantiationException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } public class ProgressTimerTask extends TimerTask { @Override public void run() { if (currentState == CURRENT_STATE_PLAYING || currentState == CURRENT_STATE_PAUSE || currentState == CURRENT_STATE_PLAYING_BUFFERING_START) { // Log.v(TAG, "onProgressUpdate " + position + "/" + duration + " [" + this.hashCode() + "] "); mHandler.post(new Runnable() { @Override public void run() { setProgressAndText(); } }); } } } public int getCurrentPositionWhenPlaying() { int position = 0; if (JCMediaManager.instance().mediaPlayer == null) return position;//这行代码不应该在这,如果代码和逻辑万无一失的话,心头之恨呐 if (currentState == CURRENT_STATE_PLAYING || currentState == CURRENT_STATE_PAUSE || currentState == CURRENT_STATE_PLAYING_BUFFERING_START) { try { position = JCMediaManager.instance().mediaPlayer.getCurrentPosition(); } catch (IllegalStateException e) { e.printStackTrace(); return position; } } return position; } public int getDuration() { int duration = 0; if (JCMediaManager.instance().mediaPlayer == null) return duration; try { duration = JCMediaManager.instance().mediaPlayer.getDuration(); } catch (IllegalStateException e) { e.printStackTrace(); return duration; } return duration; } public void setProgressAndText() { int position = getCurrentPositionWhenPlaying(); int duration = getDuration(); int progress = position * 100 / (duration == 0 ? 1 : duration); if (!mTouchingProgressBar) { if (progress != 0) progressBar.setProgress(progress); } if (position != 0) currentTimeTextView.setText(JCUtils.stringForTime(position)); totalTimeTextView.setText(JCUtils.stringForTime(duration)); } public void setBufferProgress(int bufferProgress) { if (bufferProgress != 0) progressBar.setSecondaryProgress(bufferProgress); } public void resetProgressAndTime() { progressBar.setProgress(0); progressBar.setSecondaryProgress(0); currentTimeTextView.setText(JCUtils.stringForTime(0)); totalTimeTextView.setText(JCUtils.stringForTime(0)); } public static AudioManager.OnAudioFocusChangeListener onAudioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() { @Override public void onAudioFocusChange(int focusChange) { switch (focusChange) { case AudioManager.AUDIOFOCUS_GAIN: break; case AudioManager.AUDIOFOCUS_LOSS: releaseAllVideos(); Log.d(TAG, "AUDIOFOCUS_LOSS [" + this.hashCode() + "]"); break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: try { if (JCMediaManager.instance().mediaPlayer != null && JCMediaManager.instance().mediaPlayer.isPlaying()) { JCMediaManager.instance().mediaPlayer.pause(); } } catch (IllegalStateException e) { e.printStackTrace(); } Log.d(TAG, "AUDIOFOCUS_LOSS_TRANSIENT [" + this.hashCode() + "]"); break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: break; } } }; public void release() { if (url.equals(JCMediaManager.CURRENT_PLAYING_URL) && (System.currentTimeMillis() - CLICK_QUIT_FULLSCREEN_TIME) > FULL_SCREEN_NORMAL_DELAY) { //在非全屏的情况下只能backPress() if (JCVideoPlayerManager.getSecondFloor() != null && JCVideoPlayerManager.getSecondFloor().currentScreen == SCREEN_WINDOW_FULLSCREEN) {//点击全屏 } else if (JCVideoPlayerManager.getSecondFloor() == null && JCVideoPlayerManager.getFirstFloor() != null && JCVideoPlayerManager.getFirstFloor().currentScreen == SCREEN_WINDOW_FULLSCREEN) {//直接全屏 } else { Log.d(TAG, "release [" + this.hashCode() + "]"); releaseAllVideos(); } } } //isCurrentJcvd and isCurrenPlayUrl should be two logic methods,isCurrentJcvd is for different jcvd with same //url when fullscreen or tiny screen. isCurrenPlayUrl is to find where is myself when back from tiny screen. //Sometimes they are overlap. public boolean isCurrentJcvd() {//虽然看这个函数很不爽,但是干不掉 return JCVideoPlayerManager.getCurrentJcvd() != null && JCVideoPlayerManager.getCurrentJcvd() == this; } // public boolean isCurrenPlayingUrl() { // return url.equals(JCMediaManager.CURRENT_PLAYING_URL); // } public static void releaseAllVideos() { if ((System.currentTimeMillis() - CLICK_QUIT_FULLSCREEN_TIME) > FULL_SCREEN_NORMAL_DELAY) { Log.d(TAG, "releaseAllVideos"); JCVideoPlayerManager.completeAll(); JCMediaManager.instance().releaseMediaPlayer(); } } public static void setJcUserAction(JCUserAction jcUserEvent) { JC_USER_EVENT = jcUserEvent; } public void onEvent(int type) { if (JC_USER_EVENT != null && isCurrentJcvd()) { JC_USER_EVENT.onEvent(type, url, currentScreen, objects); } } public static void startFullscreen(Context context, Class _class, String url, Object... objects) { hideSupportActionBar(context); JCUtils.getAppCompActivity(context).setRequestedOrientation(FULLSCREEN_ORIENTATION); ViewGroup vp = (ViewGroup) (JCUtils.scanForActivity(context))//.getWindow().getDecorView(); .findViewById(Window.ID_ANDROID_CONTENT); View old = vp.findViewById(JCVideoPlayer.FULLSCREEN_ID); if (old != null) { vp.removeView(old); } try { Constructor<JCVideoPlayer> constructor = _class.getConstructor(Context.class); final JCVideoPlayer jcVideoPlayer = constructor.newInstance(context); jcVideoPlayer.setId(JCVideoPlayer.FULLSCREEN_ID); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); vp.addView(jcVideoPlayer, lp); // final Animation ra = AnimationUtils.loadAnimation(context, R.anim.start_fullscreen); // jcVideoPlayer.setAnimation(ra); jcVideoPlayer.setUp(url, JCVideoPlayerStandard.SCREEN_WINDOW_FULLSCREEN, objects); CLICK_QUIT_FULLSCREEN_TIME = System.currentTimeMillis(); jcVideoPlayer.startButton.performClick(); } catch (InstantiationException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } public static void hideSupportActionBar(Context context) { if (ACTION_BAR_EXIST) { ActionBar ab = JCUtils.getAppCompActivity(context).getSupportActionBar(); if (ab != null) { ab.setShowHideAnimationEnabled(false); ab.hide(); } } if (TOOL_BAR_EXIST) { JCUtils.getAppCompActivity(context).getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } } public static void showSupportActionBar(Context context) { if (ACTION_BAR_EXIST) { ActionBar ab = JCUtils.getAppCompActivity(context).getSupportActionBar(); if (ab != null) { ab.setShowHideAnimationEnabled(false); ab.show(); } } if (TOOL_BAR_EXIST) { JCUtils.getAppCompActivity(context).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); } } public static class JCAutoFullscreenListener implements SensorEventListener { @Override public void onSensorChanged(SensorEvent event) {//可以得到传感器实时测量出来的变化值 final float x = event.values[SensorManager.DATA_X]; float y = event.values[SensorManager.DATA_Y]; float z = event.values[SensorManager.DATA_Z]; //过滤掉用力过猛会有一个反向的大数值 if (((x > -15 && x < -10) || (x < 15 && x > 10)) && Math.abs(y) < 1.5) { if ((System.currentTimeMillis() - lastAutoFullscreenTime) > 2000) { if (JCVideoPlayerManager.getCurrentJcvd() != null) { JCVideoPlayerManager.getCurrentJcvd().autoFullscreen(x); } lastAutoFullscreenTime = System.currentTimeMillis(); } } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } } public static void clearSavedProgress(Context context, String url) { JCUtils.clearSavedProgress(context, url); } public void showWifiDialog() { } public void showProgressDialog(float deltaX, String seekTime, int seekTimePosition, String totalTime, int totalTimeDuration) { } public void dismissProgressDialog() { } public void showVolumeDialog(float deltaY, int volumePercent) { } public void dismissVolumeDialog() { } public void showBrightnessDialog(int brightnessPercent) { } public void dismissBrightnessDialog() { } public abstract int getLayoutId(); }