代码如下所示
public class IjkVideoPlayer extends AbstractVideoPlayer {
protected IjkMediaPlayer mMediaPlayer;
private int mBufferedPercent;
private Context mAppContext;
public IjkVideoPlayer(Context context) {
if (context instanceof Application){
mAppContext = context;
} else {
mAppContext = context.getApplicationContext();
}
}
@Override
public void initPlayer() {
mMediaPlayer = new IjkMediaPlayer();
//native日志
IjkMediaPlayer.native_setLogLevel(VideoLogUtils.isIsLog()
? IjkMediaPlayer.IJK_LOG_INFO : IjkMediaPlayer.IJK_LOG_SILENT);
setOptions();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
initListener();
}
@Override
public void setOptions() {
}
/**
* ijk视频播放器监听listener
*/
private void initListener() {
// 设置监听,可以查看ijk中的IMediaPlayer源码监听事件
// 设置视频错误监听器
mMediaPlayer.setOnErrorListener(onErrorListener);
// 设置视频播放完成监听事件
mMediaPlayer.setOnCompletionListener(onCompletionListener);
// 设置视频信息监听器
mMediaPlayer.setOnInfoListener(onInfoListener);
// 设置视频缓冲更新监听事件
mMediaPlayer.setOnBufferingUpdateListener(onBufferingUpdateListener);
// 设置准备视频播放监听事件
mMediaPlayer.setOnPreparedListener(onPreparedListener);
// 设置视频大小更改监听器
mMediaPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener);
// 设置视频seek完成监听事件
mMediaPlayer.setOnSeekCompleteListener(onSeekCompleteListener);
// 设置时间文本监听器
mMediaPlayer.setOnTimedTextListener(onTimedTextListener);
mMediaPlayer.setOnNativeInvokeListener(new IjkMediaPlayer.OnNativeInvokeListener() {
@Override
public boolean onNativeInvoke(int i, Bundle bundle) {
return true;
}
});
}
/**
* 设置播放地址
*
* @param path 播放地址
* @param headers 播放地址请求头
*/
@Override
public void setDataSource(String path, Map<String, String> headers) {
// 设置dataSource
if(path==null || path.length()==0){
if (mPlayerEventListener!=null){
mPlayerEventListener.onInfo(PlayerConstant.MEDIA_INFO_URL_NULL, 0);
}
return;
}
try {
//解析path
Uri uri = Uri.parse(path);
if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme())) {
RawDataSourceProvider rawDataSourceProvider = RawDataSourceProvider.create(mAppContext, uri);
mMediaPlayer.setDataSource(rawDataSourceProvider);
} else {
//处理UA问题
if (headers != null) {
String userAgent = headers.get("User-Agent");
if (!TextUtils.isEmpty(userAgent)) {
mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "user_agent", userAgent);
}
}
mMediaPlayer.setDataSource(mAppContext, uri, headers);
}
} catch (Exception e) {
mPlayerEventListener.onError();
}
}
/**
* 用于播放raw和asset里面的视频文件
*/
@Override
public void setDataSource(AssetFileDescriptor fd) {
try {
mMediaPlayer.setDataSource(new RawDataSourceProvider(fd));
} catch (Exception e) {
mPlayerEventListener.onError();
}
}
/**
* 设置渲染视频的View,主要用于TextureView
* @param surface surface
*/
@Override
public void setSurface(Surface surface) {
mMediaPlayer.setSurface(surface);
}
/**
* 准备开始播放(异步)
*/
@Override
public void prepareAsync() {
try {
mMediaPlayer.prepareAsync();
} catch (IllegalStateException e) {
mPlayerEventListener.onError();
}
}
/**
* 暂停
*/
@Override
public void pause() {
try {
mMediaPlayer.pause();
} catch (IllegalStateException e) {
mPlayerEventListener.onError();
}
}
/**
* 播放
*/
@Override
public void start() {
try {
mMediaPlayer.start();
} catch (IllegalStateException e) {
mPlayerEventListener.onError();
}
}
/**
* 停止
*/
@Override
public void stop() {
try {
mMediaPlayer.stop();
} catch (IllegalStateException e) {
mPlayerEventListener.onError();
}
}
/**
* 重置播放器
*/
@Override
public void reset() {
mMediaPlayer.reset();
mMediaPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener);
setOptions();
}
/**
* 是否正在播放
*/
@Override
public boolean isPlaying() {
return mMediaPlayer.isPlaying();
}
/**
* 调整进度
*/
@Override
public void seekTo(long time) {
try {
mMediaPlayer.seekTo((int) time);
} catch (IllegalStateException e) {
mPlayerEventListener.onError();
}
}
/**
* 释放播放器
*/
@Override
public void release() {
mMediaPlayer.setOnErrorListener(null);
mMediaPlayer.setOnCompletionListener(null);
mMediaPlayer.setOnInfoListener(null);
mMediaPlayer.setOnBufferingUpdateListener(null);
mMediaPlayer.setOnPreparedListener(null);
mMediaPlayer.setOnVideoSizeChangedListener(null);
new Thread() {
@Override
public void run() {
try {
mMediaPlayer.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
/**
* 获取当前播放的位置
*/
@Override
public long getCurrentPosition() {
return mMediaPlayer.getCurrentPosition();
}
/**
* 获取视频总时长
*/
@Override
public long getDuration() {
return mMediaPlayer.getDuration();
}
/**
* 获取缓冲百分比
*/
@Override
public int getBufferedPercentage() {
return mBufferedPercent;
}
/**
* 设置渲染视频的View,主要用于SurfaceView
*/
@Override
public void setDisplay(SurfaceHolder holder) {
mMediaPlayer.setDisplay(holder);
}
/**
* 设置音量
*/
@Override
public void setVolume(float v1, float v2) {
mMediaPlayer.setVolume(v1, v2);
}
/**
* 设置是否循环播放
*/
@Override
public void setLooping(boolean isLooping) {
mMediaPlayer.setLooping(isLooping);
}
/**
* 设置播放速度
*/
@Override
public void setSpeed(float speed) {
mMediaPlayer.setSpeed(speed);
}
/**
* 获取播放速度
*/
@Override
public float getSpeed() {
return mMediaPlayer.getSpeed(0);
}
/**
* 获取当前缓冲的网速
*/
@Override
public long getTcpSpeed() {
return mMediaPlayer.getTcpSpeed();
}
/**
* 设置视频错误监听器
* int MEDIA_INFO_VIDEO_RENDERING_START = 3;//视频准备渲染
* int MEDIA_INFO_BUFFERING_START = 701;//开始缓冲
* int MEDIA_INFO_BUFFERING_END = 702;//缓冲结束
* int MEDIA_INFO_VIDEO_ROTATION_CHANGED = 10001;//视频选择信息
* int MEDIA_ERROR_SERVER_DIED = 100;//视频中断,一般是视频源异常或者不支持的视频类型。
* int MEDIA_ERROR_IJK_PLAYER = -10000,//一般是视频源有问题或者数据格式不支持,比如音频不是AAC之类的
* int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200;//数据错误没有有效的回收
*/
private IMediaPlayer.OnErrorListener onErrorListener = new IMediaPlayer.OnErrorListener() {
@Override
public boolean onError(IMediaPlayer iMediaPlayer, int framework_err, int impl_err) {
mPlayerEventListener.onError();
VideoLogUtils.d("IjkVideoPlayer----listener---------onError ——> STATE_ERROR ———— what:" + framework_err + ", extra: " + impl_err);
return true;
}
};
/**
* 设置视频播放完成监听事件
*/
private IMediaPlayer.OnCompletionListener onCompletionListener = new IMediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(IMediaPlayer iMediaPlayer) {
mPlayerEventListener.onCompletion();
VideoLogUtils.d("IjkVideoPlayer----listener---------onCompletion ——> STATE_COMPLETED");
}
};
/**
* 设置视频信息监听器
*/
private IMediaPlayer.OnInfoListener onInfoListener = new IMediaPlayer.OnInfoListener() {
@Override
public boolean onInfo(IMediaPlayer iMediaPlayer, int what, int extra) {
mPlayerEventListener.onInfo(what, extra);
VideoLogUtils.d("IjkVideoPlayer----listener---------onInfo ——> ———— what:" + what + ", extra: " + extra);
return true;
}
};
/**
* 设置视频缓冲更新监听事件
*/
private IMediaPlayer.OnBufferingUpdateListener onBufferingUpdateListener = new IMediaPlayer.OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(IMediaPlayer iMediaPlayer, int percent) {
mBufferedPercent = percent;
}
};
/**
* 设置准备视频播放监听事件
*/
private IMediaPlayer.OnPreparedListener onPreparedListener = new IMediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(IMediaPlayer iMediaPlayer) {
mPlayerEventListener.onPrepared();
VideoLogUtils.d("IjkVideoPlayer----listener---------onPrepared ——> STATE_PREPARED");
}
};
/**
* 设置视频大小更改监听器
*/
private IMediaPlayer.OnVideoSizeChangedListener onVideoSizeChangedListener = new IMediaPlayer.OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(IMediaPlayer iMediaPlayer, int width, int height,
int sar_num, int sar_den) {
int videoWidth = iMediaPlayer.getVideoWidth();
int videoHeight = iMediaPlayer.getVideoHeight();
if (videoWidth != 0 && videoHeight != 0) {
mPlayerEventListener.onVideoSizeChanged(videoWidth, videoHeight);
}
VideoLogUtils.d("IjkVideoPlayer----listener---------onVideoSizeChanged ——> WIDTH:" + width + ", HEIGHT:" + height);
}
};
/**
* 设置时间文本监听器
*/
private IMediaPlayer.OnTimedTextListener onTimedTextListener = new IMediaPlayer.OnTimedTextListener() {
@Override
public void onTimedText(IMediaPlayer iMediaPlayer, IjkTimedText ijkTimedText) {
}
};
/**
* 设置视频seek完成监听事件
*/
private IMediaPlayer.OnSeekCompleteListener onSeekCompleteListener = new IMediaPlayer.OnSeekCompleteListener() {
@Override
public void onSeekComplete(IMediaPlayer iMediaPlayer) {
}
};
}
先来看一下创建不同内核播放器的代码,只需要开发者传入一个类型参数,即可创建不同类的实例对象。代码如下所示
/**
* 获取PlayerFactory具体实现类,获取内核
* 创建对象的时候只需要传递类型type,而不需要对应的工厂,即可创建具体的产品对象
* TYPE_IJK IjkPlayer,基于IjkPlayer封装播放器
* TYPE_NATIVE MediaPlayer,基于原生自带的播放器控件
* TYPE_EXO 基于谷歌视频播放器
* TYPE_RTC 基于RTC视频播放器
* @param type 类型
* @return
*/
public static AbstractVideoPlayer getVideoPlayer(Context context,@PlayerConstant.PlayerType int type){
if (type == PlayerConstant.PlayerType.TYPE_EXO){
return ExoPlayerFactory.create().createPlayer(context);
} else if (type == PlayerConstant.PlayerType.TYPE_IJK){
return IjkPlayerFactory.create().createPlayer(context);
} else if (type == PlayerConstant.PlayerType.TYPE_NATIVE){
return MediaPlayerFactory.create().createPlayer(context);
} else if (type == PlayerConstant.PlayerType.TYPE_RTC){
return IjkPlayerFactory.create().createPlayer(context);
} else {
return IjkPlayerFactory.create().createPlayer(context);
}
}
使用工厂模式创建不同对象的动机是什么,为何要这样使用?
首先定义一个工厂抽象类,然后不同的内核播放器分别创建其具体的工厂实现具体类
如何使用,分为三步,具体操作如下所示
抽象工厂类,代码如下所示
public abstract class PlayerFactory<T extends AbstractVideoPlayer> {
public abstract T createPlayer(Context context);
}
具体实现工厂类,代码如下所示
public class ExoPlayerFactory extends PlayerFactory<ExoMediaPlayer> {
public static ExoPlayerFactory create() {
return new ExoPlayerFactory();
}
@Override
public ExoMediaPlayer createPlayer(Context context) {
return new ExoMediaPlayer(context);
}
}
这种创建对象最大优点