package com.metis.base.fragment; import android.content.Context; import android.content.pm.ActivityInfo; import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.PowerManager; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import com.bokecc.sdk.mobile.drm.DRMServer; import com.bokecc.sdk.mobile.play.DWMediaPlayer; import com.bokecc.sdk.mobile.util.HttpUtil; import com.metis.base.R; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Created by Beak on 2015/9/24. */ public class CcPlayFragment extends Fragment implements SurfaceHolder.Callback, MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener, MediaPlayer.OnBufferingUpdateListener{ private static final String TAG = CcPlayFragment.class.getSimpleName(); private static CcPlayFragment sFragment = null; public static CcPlayFragment getInstance () { if (sFragment == null) { sFragment = new CcPlayFragment(); } return sFragment; } private boolean isSeeking = false; private Runnable mUpdateRunnable = new Runnable() { @Override public void run() { if (!isSeeking && mPlayer != null && mPlayer.isPlaying()) { final int currentPosition = mPlayer.getCurrentPosition(); final int duration = mPlayer.getDuration(); int progress = currentPosition * 100 / duration; doMuchPlayerUpdateProgress(currentPosition, duration, progress); mUpdateHandler.postDelayed(this, 1000); Log.v(TAG, "update progress " + currentPosition); } } }; private static Handler mUpdateHandler = new Handler(); private SurfaceView mCcPlaySurfaceView = null; private Surface mSurface = null; private Context mAppContext = null; private boolean isSufaceViewCreated = false, isStarted = false; private OnFullScreenCallback mFullScreenCallback = null; private PlayerProperty mProperty = null; private DWMediaPlayer mPlayer = null; private DRMServer mDrmServer = null; private AudioManager mAudioManager = null; private List<PlayerCallback> mCallbackList = new ArrayList<PlayerCallback>(); private int mBufferingPercent = 0; private boolean onPausedFirst = false; private AudioManager.OnAudioFocusChangeListener mAudioListener = new AudioManager.OnAudioFocusChangeListener() { @Override public void onAudioFocusChange(int focusChange) { if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { pausePlay(); } } }; @Override public void onAttach(Context context) { super.onAttach(context); mAppContext = context.getApplicationContext(); mProperty = PlayerProperty.getInstance(context); mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_cc_play, null, true); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mCcPlaySurfaceView = (SurfaceView)view.findViewById(R.id.cc_play_surface_view); mCcPlaySurfaceView.getHolder().addCallback(this); } @Override public void surfaceCreated(SurfaceHolder holder) { isSufaceViewCreated = true; mSurface = holder.getSurface(); Log.v(TAG, TAG + " surfaceCreated"); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.v(TAG, TAG + " surfaceChanged"); } @Override public void surfaceDestroyed(SurfaceHolder holder) { isSufaceViewCreated = false; mSurface = null; Log.v(TAG, TAG + " surfaceDestroyed"); } public void setFullScreen(boolean fullScreen) { View view = getActivity().getWindow().getDecorView(); if (fullScreen) { getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LOW_PROFILE); } else { getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); view.setSystemUiVisibility(0); } if (mFullScreenCallback != null) { mFullScreenCallback.onFullScreen(fullScreen); } } @Override public void onPause() { super.onPause(); if (!onPausedFirst) { onPausedFirst = true; return; } pausePlay(); } @Override public void onResume() { super.onResume(); //resumePlay(); } public boolean isFullScreen () { return getActivity().getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; } @Override public void onDestroy() { super.onDestroy(); mCcPlaySurfaceView.getHolder().removeCallback(this); if (isStarted) { stopPlay(); release(); } } @Override public void onDetach() { super.onDetach(); mAudioManager = null; } public void setSeeking (boolean seeking) { isSeeking = seeking; if (isSeeking) { mUpdateHandler.removeCallbacks(mUpdateRunnable); } else { mUpdateHandler.post(mUpdateRunnable); } } public int getDuration () { if (mPlayer == null) { return 0; } return mPlayer.getDuration(); } public void seekTo (int position) { if (mPlayer == null || !mPlayer.isPlaying() || position < 0 || position > mPlayer.getDuration()) { return; } mPlayer.seekTo(position); } @Override public void onPrepared(MediaPlayer mp) { mPlayer.start(); isStarted = true; int height = mPlayer.getVideoHeight(); int width = mPlayer.getVideoWidth(); Log.v(TAG, TAG + " height=" + height + " width=" + width); keepScreenOn(true); mUpdateHandler.post(mUpdateRunnable); doMuchPlayerPrepared(width, height); } @Override public void onCompletion(MediaPlayer mp) { Log.v(TAG, TAG + " onCompletion"); keepScreenOn(false); doMuchPlayerCompleted(); } @Override public void onBufferingUpdate(MediaPlayer mp, int percent) { if (mBufferingPercent != percent) { Log.v(TAG, "onBufferingUpdate " + percent); doMuchPlayerBuffering(percent); mBufferingPercent = percent; } } @Override public boolean onError(MediaPlayer mp, int what, int extra) { return false; } public void startRemotePlay (String videoId) { ensurePlayer(); //TODO Log.v(TAG, TAG + " user_id=" + mProperty.getUser_id() + " api_key=" + mProperty.getApi_key()); mPlayer.setVideoPlayInfo(videoId, mProperty.getUser_id(), mProperty.getApi_key(), mAppContext); Map<String, Integer> definitions = mPlayer.getDefinitions(); if (definitions != null) { mPlayer.setDefaultDefinition(definitions.get("definitionInfo")); } else { mPlayer.setDefaultDefinition(DWMediaPlayer.NORMAL_DEFINITION); } mPlayer.prepareAsync(); doMuchPlayerStarted(); } public void startRemotePlayWithUrl (String url) { ensurePlayer(); try { Log.v(TAG, TAG + " startRemotePlayWithUrl path=" + url); //mPlayer.setDataSource(path); mPlayer.setDataSource(getContext(), Uri.parse(url)); mPlayer.prepareAsync(); doMuchPlayerStarted(); } catch (IOException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); stopPlay(); release(); startRemotePlayWithUrl(url); } } public void startLocalPlay (String path) { ensurePlayer(); try { Log.v(TAG, TAG + " startLocalPlay path=" + path); //mPlayer.setDataSource(path); mPlayer.setDRMVideoPath(path, mAppContext); mPlayer.prepareAsync(); doMuchPlayerStarted(); } catch (IOException e) { e.printStackTrace(); } } private void ensurePlayer() { HttpUtil.LOG_LEVEL = HttpUtil.HttpLogLevel.DETAIL; if (mSurface == null) { throw new IllegalStateException("no surface was set to MediaPlayer, call setSurface before startPlay"); } startServerIfNeed(); if (mPlayer == null) { mPlayer = new DWMediaPlayer(); } mPlayer.setDRMServerPort(mDrmServer.getPort()); mPlayer.setOnPreparedListener(this); mPlayer.setOnCompletionListener(this); mPlayer.setOnBufferingUpdateListener(this); mPlayer.setSurface(mSurface); requestAudioFocus(); } public void stopPlay () { if (mPlayer == null) { return; } mPlayer.stop(); isStarted = false; doMuchPlayerStopped(); } public void pausePlay () { if (mPlayer != null && isStarted && mPlayer.isPlaying()) { mPlayer.pause(); keepScreenOn(false); releaseAudioFocus(); doMuchPlayerPaused(); } } public void resumePlay () { if (mPlayer != null && isStarted && !mPlayer.isPlaying()) { mPlayer.setSurface(mSurface); mPlayer.start(); keepScreenOn(true); requestAudioFocus(); doMuchPlayerResumed(); mUpdateHandler.post(mUpdateRunnable); } } public void release () { if (mPlayer != null) { stopServerIfNeed(); mPlayer.release(); mPlayer = null; //mSurface = null; releaseAudioFocus(); //mCallbackList.clear(); } } private void keepScreenOn (boolean screenOn) { mCcPlaySurfaceView.setKeepScreenOn(screenOn); /*if (screenOn) { mWakeLock.acquire(); } else { if (mWakeLock.isHeld()) { mWakeLock.release(); } }*/ } private void requestAudioFocus() { mAudioManager.requestAudioFocus(mAudioListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); } private void releaseAudioFocus () { mAudioManager.abandonAudioFocus(mAudioListener); } private void startServerIfNeed () { if (mDrmServer == null) { mDrmServer = new DRMServer(); mDrmServer.start(); } } private void stopServerIfNeed () { if (mDrmServer != null) { mDrmServer.stop(); mDrmServer = null; } } public void registerPlayerCallback (PlayerCallback callback) { if (mCallbackList.contains(callback)) { return; } mCallbackList.add(callback); } public void unregisterPlayerCallback (PlayerCallback callback) { if (!mCallbackList.contains(callback)) { return; } mCallbackList.remove(callback); } private void doMuchPlayerPrepared (int width, int height) { final int length = mCallbackList.size(); for (int i = 0; i < length; i++) { PlayerCallback callback = mCallbackList.get(i); callback.onPlayerPrepared(width, height); } } private void doMuchPlayerStarted () { final int length = mCallbackList.size(); for (int i = 0; i < length; i++) { PlayerCallback callback = mCallbackList.get(i); callback.onPlayerStarted(); } } private void doMuchPlayerPaused () { final int length = mCallbackList.size(); for (int i = 0; i < length; i++) { PlayerCallback callback = mCallbackList.get(i); callback.onPlayerPaused(); } } private void doMuchPlayerResumed () { final int length = mCallbackList.size(); for (int i = 0; i < length; i++) { PlayerCallback callback = mCallbackList.get(i); callback.onPlayerResumed(); } } private void doMuchPlayerStopped () { final int length = mCallbackList.size(); for (int i = 0; i < length; i++) { PlayerCallback callback = mCallbackList.get(i); callback.onPlayerStopped(); } } private void doMuchPlayerCompleted () { final int length = mCallbackList.size(); for (int i = 0; i < length; i++) { PlayerCallback callback = mCallbackList.get(i); callback.onPlayerCompleted(); } } private void doMuchPlayerUpdateProgress (int current, int duration, int progress) { final int length = mCallbackList.size(); for (int i = 0; i < length; i++) { PlayerCallback callback = mCallbackList.get(i); callback.onUpdateProgress(current, duration, progress); } } private void doMuchPlayerBuffering (int percent) { final int length = mCallbackList.size(); for (int i = 0; i < length; i++) { PlayerCallback callback = mCallbackList.get(i); callback.onBuffering(percent); } } public void setOnFullScreenCallback (OnFullScreenCallback callback) { mFullScreenCallback = callback; } public interface OnFullScreenCallback { public void onFullScreen (boolean fullScreen); } public interface PlayerCallback { public void onPlayerStarted (); public void onPlayerPrepared (int width, int height); public void onPlayerPaused (); public void onPlayerResumed (); public void onPlayerStopped (); public void onPlayerCompleted (); public void onUpdateProgress (int current, int duration, int progress); public void onBuffering (int percent); } }