package com.shuyu.gsyvideoplayer; import android.content.Context; import android.media.AudioManager; import android.net.Uri; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.text.TextUtils; import android.view.Surface; import com.danikula.videocache.HttpProxyCacheServer; import com.shuyu.gsyvideoplayer.listener.GSYMediaPlayerListener; import com.shuyu.gsyvideoplayer.model.GSYModel; import java.lang.ref.WeakReference; import java.util.Map; import tv.danmaku.ijk.media.exo.IjkExoMediaPlayer; import tv.danmaku.ijk.media.player.IMediaPlayer; /** * 视频管理,单例 * 目前使用的是IJK封装的谷歌EXOPlayer * Created by shuyu on 2016/11/11. */ public class GSYVideoManager implements IMediaPlayer.OnPreparedListener, IMediaPlayer.OnCompletionListener, IMediaPlayer.OnBufferingUpdateListener, IMediaPlayer.OnSeekCompleteListener, IMediaPlayer.OnErrorListener, IMediaPlayer.OnVideoSizeChangedListener, IMediaPlayer.OnInfoListener { public static String TAG = "GSYVideoManager"; private static GSYVideoManager videoManager; public static final int HANDLER_PREPARE = 0; public static final int HANDLER_SETDISPLAY = 1; public static final int HANDLER_RELEASE = 2; private IjkExoMediaPlayer mediaPlayer; private HandlerThread mMediaHandlerThread; private MediaHandler mMediaHandler; private Handler mainThreadHandler; private Context context; private WeakReference listener; private WeakReference lastListener; private HttpProxyCacheServer proxy; //视频代理 private int currentVideoWidth = 0; //当前播放的视频宽的高 private int currentVideoHeight = 0; //当前播放的视屏的高 private int lastState;//当前视频的最后状态 /** * 初始化,必须的 * * @param context */ public static void initVideo(Context context) { if (videoManager == null) { videoManager = new GSYVideoManager(context); } } public static GSYVideoManager instance() { return videoManager; } /** * 获取缓存代理服务 */ public static HttpProxyCacheServer getProxy(Context context) { HttpProxyCacheServer proxy = GSYVideoManager.instance().proxy; return proxy == null ? (proxy = GSYVideoManager.instance().newProxy(context)) : proxy; } /** * 创建缓存代理服务 */ private HttpProxyCacheServer newProxy(Context context) { return new HttpProxyCacheServer(context.getApplicationContext()); } public GSYMediaPlayerListener listener() { if (listener == null) return null; return listener.get(); } public GSYMediaPlayerListener lastListener() { if (lastListener == null) return null; return lastListener.get(); } public void setListener(GSYMediaPlayerListener listener) { if (listener == null) this.listener = null; else this.listener = new WeakReference<>(listener); } public void setLastListener(GSYMediaPlayerListener lastListener) { if (lastListener == null) this.lastListener = null; else this.lastListener = new WeakReference<>(lastListener); } public GSYVideoManager(Context context) { this.context = context; mediaPlayer = new IjkExoMediaPlayer(context); mMediaHandlerThread = new HandlerThread(TAG); mMediaHandlerThread.start(); mMediaHandler = new MediaHandler((mMediaHandlerThread.getLooper())); mainThreadHandler = new Handler(); } public class MediaHandler extends Handler { public MediaHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case HANDLER_PREPARE: try { currentVideoWidth = 0; currentVideoHeight = 0; mediaPlayer.release(); mediaPlayer = new IjkExoMediaPlayer(context); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setDataSource(context, Uri.parse(((GSYModel) msg.obj).getUrl()), ((GSYModel) msg.obj).getMapHeadData()); mediaPlayer.setOnPreparedListener(GSYVideoManager.this); mediaPlayer.setOnCompletionListener(GSYVideoManager.this); mediaPlayer.setOnBufferingUpdateListener(GSYVideoManager.this); mediaPlayer.setScreenOnWhilePlaying(true); mediaPlayer.setOnSeekCompleteListener(GSYVideoManager.this); mediaPlayer.setOnErrorListener(GSYVideoManager.this); mediaPlayer.setOnInfoListener(GSYVideoManager.this); mediaPlayer.setOnVideoSizeChangedListener(GSYVideoManager.this); mediaPlayer.prepareAsync(); } catch (Exception e) { e.printStackTrace(); } break; case HANDLER_SETDISPLAY: if (msg.obj == null) { mediaPlayer.setSurface(null); } else { Surface holder = (Surface) msg.obj; if (holder.isValid()) { mediaPlayer.setSurface(holder); if (mediaPlayer != null && mediaPlayer.getDuration() > 30 && mediaPlayer.getCurrentPosition() < mediaPlayer.getDuration()) { mediaPlayer.seekTo(mediaPlayer.getCurrentPosition() - 20); } } } break; case HANDLER_RELEASE: mediaPlayer.release(); break; } } } public void prepare(final String url, final Map mapHeadData, boolean loop) { if (TextUtils.isEmpty(url)) return; Message msg = new Message(); msg.what = HANDLER_PREPARE; GSYModel fb = new GSYModel(url, mapHeadData, loop); msg.obj = fb; mMediaHandler.sendMessage(msg); } public void releaseMediaPlayer() { Message msg = new Message(); msg.what = HANDLER_RELEASE; mMediaHandler.sendMessage(msg); } public void setDisplay(Surface holder) { Message msg = new Message(); msg.what = HANDLER_SETDISPLAY; msg.obj = holder; mMediaHandler.sendMessage(msg); } @Override public void onPrepared(IMediaPlayer mp) { mainThreadHandler.post(new Runnable() { @Override public void run() { if (listener != null) { listener().onPrepared(); } } }); } @Override public void onCompletion(IMediaPlayer mp) { mainThreadHandler.post(new Runnable() { @Override public void run() { if (listener != null) { listener().onAutoCompletion(); } } }); } @Override public void onBufferingUpdate(IMediaPlayer mp, final int percent) { mainThreadHandler.post(new Runnable() { @Override public void run() { if (listener != null) { listener().onBufferingUpdate(percent); } } }); } @Override public void onSeekComplete(IMediaPlayer mp) { mainThreadHandler.post(new Runnable() { @Override public void run() { if (listener != null) { listener().onSeekComplete(); } } }); } @Override public boolean onError(IMediaPlayer mp, final int what, final int extra) { mainThreadHandler.post(new Runnable() { @Override public void run() { if (listener != null) { listener().onError(what, extra); } } }); return true; } @Override public boolean onInfo(IMediaPlayer mp, final int what, final int extra) { mainThreadHandler.post(new Runnable() { @Override public void run() { if (listener != null) { listener().onInfo(what, extra); } } }); return false; } @Override public void onVideoSizeChanged(IMediaPlayer mp, int width, int height, int sar_num, int sar_den) { currentVideoWidth = mp.getVideoWidth(); currentVideoHeight = mp.getVideoHeight(); mainThreadHandler.post(new Runnable() { @Override public void run() { if (listener != null) { listener().onVideoSizeChanged(); } } }); } public IjkExoMediaPlayer getMediaPlayer() { return mediaPlayer; } public int getCurrentVideoWidth() { return currentVideoWidth; } public int getCurrentVideoHeight() { return currentVideoHeight; } public int getLastState() { return lastState; } public void setLastState(int lastState) { this.lastState = lastState; } public void setCurrentVideoHeight(int currentVideoHeight) { this.currentVideoHeight = currentVideoHeight; } public void setCurrentVideoWidth(int currentVideoWidth) { this.currentVideoWidth = currentVideoWidth; } }