最近在GitHub上看到一款基于IjkPlayer的视频播放控件,觉得不错,所以就体验了一下。
它的功能挺强大的,主要有一下几点:
支持 边播边缓存,使用了AndroidVideoCache。
支持 其他协议和编码concat、rtsp、hls、rtmp、crypto、mpeg等。
支持 DEMO演示获取视频第一帧等实现。
支持 简单滤镜(马赛克、黑白、色彩过滤、高斯、模糊、模糊等等20多种)。
支持 GL效果动画,(xyz轴旋转,放大)。
支持 视频帧截图功能,视频生成gif功能
支持 视频播放效果(水印、画面多重播放等)
支持 列表播放;列表连续播放;重力旋转与手动旋转;视频本身rotation旋转属性。
支持 全屏切换动画效果;小窗口播放,可拖动。
支持 快播和慢播;网络视频加载速度。
支持 调整显示比例:默认、16:9、4:3、填充。
支持 播放时旋转画面角度(0,90,180,270);镜像旋转。
支持 暂停前后台切换不黑屏;调整不同清晰度的支持;无缝切换支持。
支持 Https;IJKPlayer、EXOPlayer、系统播放器切换。
支持 锁定/解锁全屏点击功能;进度条小窗口预览(测试)。
支持 全屏与非全屏两套布局切换;弹幕功能。
支持 没有任何操作控件的纯播放支持。
支持 Demo带有RecyclerView列表滑动自动播放。
支持 多窗体下(包括桌面)的小窗口播放。
我选取了带有弹幕的视频播放例子感受了一下
1.引入:
A、直接引入
//完整版引入
compile 'com.shuyu:GSYVideoPlayer:3.0.0'
B、添加java和你想要的so支持:
compile 'com.shuyu:gsyVideoPlayer-java:3.0.0'
//根据你的需求
compile 'com.shuyu:gsyVideoPlayer-armv5:3.0.0'
compile 'com.shuyu:gsyVideoPlayer-armv7a:3.0.0'
compile 'com.shuyu:gsyVideoPlayer-arm64:3.0.0'
compile 'com.shuyu:gsyVideoPlayer-x64:3.0.0'
compile 'com.shuyu:gsyVideoPlayer-x86:3.0.0'
我选择的是第一种。
另外由于还要用到弹幕,还需要引入bilibili的弹幕引擎:
//bilibili 弹幕引擎
compile 'com.github.ctiao:DanmakuFlameMaster:0.9.16'
compile 'com.github.ctiao:ndkbitmap-armv7a:0.9.16'
2.添加播放弹幕视频额外代码:
需要添加解析弹幕的解析器:
public class BiliDanmukuParser extends BaseDanmakuParser {
static {
System.setProperty("org.xml.sax.driver", "org.xmlpull.v1.sax2.Driver");
}
protected float mDispScaleX;
protected float mDispScaleY;
@Override
public Danmakus parse() {
if (mDataSource != null) {
AndroidFileSource source = (AndroidFileSource) mDataSource;
try {
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
XmlContentHandler contentHandler = new XmlContentHandler();
xmlReader.setContentHandler(contentHandler);
xmlReader.parse(new InputSource(source.data()));
return contentHandler.getResult();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
public class XmlContentHandler extends DefaultHandler {
private static final String TRUE_STRING = "true";
public Danmakus result = new Danmakus();
public BaseDanmaku item = null;
public boolean completed = false;
public int index = 0;
public Danmakus getResult() {
return result;
}
@Override
public void startDocument() throws SAXException {
}
@Override
public void endDocument() throws SAXException {
completed = true;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
String tagName = localName.length() != 0 ? localName : qName;
tagName = tagName.toLowerCase(Locale.getDefault()).trim();
if (tagName.equals("d")) {
// <d p="23.826000213623,1,25,16777215,1422201084,0,057075e9,757076900">我从未见过如此厚颜无耻之猴</d>
// 0:时间(弹幕出现时间)
// 1:类型(1从右至左滚动弹幕|6从左至右滚动弹幕|5顶端固定弹幕|4底端固定弹幕|7高级弹幕|8脚本弹幕)
// 2:字号
// 3:颜色
// 4:时间戳 ?
// 5:弹幕池id
// 6:用户hash
// 7:弹幕id
String pValue = attributes.getValue("p");
// parse p value to danmaku
String[] values = pValue.split(",");
if (values.length > 0) {
long time = (long) (Float.parseFloat(values[0]) * 1000); // 出现时间
int type = Integer.parseInt(values[1]); // 弹幕类型
float textSize = Float.parseFloat(values[2]); // 字体大小
int color = (int) ((0x00000000ff000000 | Long.parseLong(values[3])) & 0x00000000ffffffff); // 颜色
// int poolType = Integer.parseInt(values[5]); // 弹幕池类型(忽略
item = mContext.mDanmakuFactory.createDanmaku(type, mContext);
if (item != null) {
item.setTime(time);
item.textSize = textSize * (mDispDensity - 0.6f);
item.textColor = color;
item.textShadowColor = color <= Color.BLACK ? Color.WHITE : Color.BLACK;
}
}
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (item != null && item.text != null) {
if (item.duration != null) {
String tagName = localName.length() != 0 ? localName : qName;
if (tagName.equalsIgnoreCase("d")) {
item.setTimer(mTimer);
item.flags = mContext.mGlobalFlagValues;
Object lock = result.obtainSynchronizer();
synchronized (lock) {
result.addItem(item);
}
}
}
item = null;
}
}
@Override
public void characters(char[] ch, int start, int length) {
if (item != null) {
DanmakuUtils.fillText(item, decodeXmlString(new String(ch, start, length)));
item.index = index++;
// initial specail danmaku data
String text = String.valueOf(item.text).trim();
if (item.getType() == BaseDanmaku.TYPE_SPECIAL && text.startsWith("[")
&& text.endsWith("]")) {
//text = text.substring(1, text.length() - 1);
String[] textArr = null;//text.split(",", -1);
try {
JSONArray jsonArray = new JSONArray(text);
textArr = new String[jsonArray.length()];
for (int i = 0; i < textArr.length; i++) {
textArr[i] = jsonArray.getString(i);
}
} catch (JSONException e) {
e.printStackTrace();
}
if (textArr == null || textArr.length < 5 || TextUtils.isEmpty(textArr[4])) {
item = null;
return;
}
item.text = textArr[4];
float beginX = Float.parseFloat(textArr[0]);
float beginY = Float.parseFloat(textArr[1]);
float endX = beginX;
float endY = beginY;
String[] alphaArr = textArr[2].split("-");
int beginAlpha = (int) (AlphaValue.MAX * Float.parseFloat(alphaArr[0]));
int endAlpha = beginAlpha;
if (alphaArr.length > 1) {
endAlpha = (int) (AlphaValue.MAX * Float.parseFloat(alphaArr[1]));
}
long alphaDuraion = (long) (Float.parseFloat(textArr[3]) * 1000);
long translationDuration = alphaDuraion;
long translationStartDelay = 0;
float rotateY = 0, rotateZ = 0;
if (textArr.length >= 7) {
rotateZ = Float.parseFloat(textArr[5]);
rotateY = Float.parseFloat(textArr[6]);
}
if (textArr.length >= 11) {
endX = Float.parseFloat(textArr[7]);
endY = Float.parseFloat(textArr[8]);
if (!"".equals(textArr[9])) {
translationDuration = Integer.parseInt(textArr[9]);
}
if (!"".equals(textArr[10])) {
translationStartDelay = (long) (Float.parseFloat(textArr[10]));
}
}
if (isPercentageNumber(beginX)) {
beginX *= DanmakuFactory.BILI_PLAYER_WIDTH;
}
if (isPercentageNumber(beginY)) {
beginY *= DanmakuFactory.BILI_PLAYER_HEIGHT;
}
if (isPercentageNumber(endX)) {
endX *= DanmakuFactory.BILI_PLAYER_WIDTH;
}
if (isPercentageNumber(endY)) {
endY *= DanmakuFactory.BILI_PLAYER_HEIGHT;
}
item.duration = new Duration(alphaDuraion);
item.rotationZ = rotateZ;
item.rotationY = rotateY;
mContext.mDanmakuFactory.fillTranslationData(item, beginX,
beginY, endX, endY, translationDuration, translationStartDelay, mDispScaleX, mDispScaleY);
mContext.mDanmakuFactory.fillAlphaData(item, beginAlpha, endAlpha, alphaDuraion);
if (textArr.length >= 12) {
// 是否有描边
if (!TextUtils.isEmpty(textArr[11]) && TRUE_STRING.equals(textArr[11])) {
item.textShadowColor = Color.TRANSPARENT;
}
}
if (textArr.length >= 13) {
//TODO 字体 textArr[12]
}
if (textArr.length >= 14) {
//TODO 是否有动画缓冲(easing)
}
if (textArr.length >= 15) {
// 路径数据
if (!"".equals(textArr[14])) {
String motionPathString = textArr[14].substring(1);
String[] pointStrArray = motionPathString.split("L");
if (pointStrArray != null && pointStrArray.length > 0) {
float[][] points = new float[pointStrArray.length][2];
for (int i = 0; i < pointStrArray.length; i++) {
String[] pointArray = pointStrArray[i].split(",");
points[i][0] = Float.parseFloat(pointArray[0]);
points[i][1] = Float.parseFloat(pointArray[1]);
}
mContext.mDanmakuFactory.fillLinePathData(item, points, mDispScaleX,
mDispScaleY);
}
}
}
}
}
}
private String decodeXmlString(String title) {
if (title.contains("&")) {
title = title.replace("&", "&");
}
if (title.contains(""")) {
title = title.replace(""", "\"");
}
if (title.contains(">")) {
title = title.replace(">", ">");
}
if (title.contains("<")) {
title = title.replace("<", "<");
}
return title;
}
}
private boolean isPercentageNumber(float number) {
return number >= 0f && number <= 1f;
}
@Override
public BaseDanmakuParser setDisplayer(IDisplayer disp) {
super.setDisplayer(disp);
mDispScaleX = mDispWidth / DanmakuFactory.BILI_PLAYER_WIDTH;
mDispScaleY = mDispHeight / DanmakuFactory.BILI_PLAYER_HEIGHT;
return this;
}
}
以及适配器:
public class DanamakuAdapter extends BaseCacheStuffer.Proxy {
private Drawable mDrawable;
private IDanmakuView mDanmakuView;
public DanamakuAdapter(IDanmakuView mDanmakuView) {
super();
this.mDanmakuView = mDanmakuView;
}
@Override
public void prepareDrawing(final BaseDanmaku danmaku, boolean fromWorkerThread) {
if (danmaku.text instanceof Spanned) { // 根据你的条件检查是否需要需要更新弹幕
// FIXME 这里只是简单启个线程来加载远程url图片,请使用你自己的异步线程池,最好加上你的缓存池
new Thread() {
@Override
public void run() {
String url = "http://www.bilibili.com/favicon.ico";
InputStream inputStream = null;
Drawable drawable = mDrawable;
if (drawable == null) {
try {
URLConnection urlConnection = new URL(url).openConnection();
inputStream = urlConnection.getInputStream();
drawable = BitmapDrawable.createFromStream(inputStream, "bitmap");
mDrawable = drawable;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(inputStream);
}
}
if (drawable != null) {
drawable.setBounds(0, 0, 100, 100);
SpannableStringBuilder spannable = createSpannable(drawable);
danmaku.text = spannable;
if (mDanmakuView != null) {
mDanmakuView.invalidateDanmaku(danmaku, false);
}
return;
}
}
}.start();
}
}
@Override
public void releaseResource(BaseDanmaku danmaku) {
// TODO 重要:清理含有ImageSpan的text中的一些占用内存的资源 例如drawable
}
private SpannableStringBuilder createSpannable(Drawable drawable) {
String text = "bitmap";
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text);
ImageSpan span = new ImageSpan(drawable);//ImageSpan.ALIGN_BOTTOM);
spannableStringBuilder.setSpan(span, 0, text.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
spannableStringBuilder.append("图文混排");
spannableStringBuilder.setSpan(new BackgroundColorSpan(Color.parseColor("#8A2233B1")), 0, spannableStringBuilder.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
return spannableStringBuilder;
}
}
还有就是配置弹幕使用的播放器:
public class DanmakuVideoPlayer extends StandardGSYVideoPlayer {
private BaseDanmakuParser mParser;//解析器对象
private IDanmakuView mDanmakuView;//弹幕view
private DanmakuContext mDanmakuContext;
private TextView mSendDanmaku, mToogleDanmaku;
private long mDanmakuStartSeekPosition = -1;
private boolean mDanmaKuShow = true;
public DanmakuVideoPlayer(Context context, Boolean fullFlag) {
super(context, fullFlag);
}
public DanmakuVideoPlayer(Context context) {
super(context);
}
public DanmakuVideoPlayer(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public int getLayoutId() {
return R.layout.danmaku_layout;
}
@Override
protected void init(Context context) {
super.init(context);
mDanmakuView = (DanmakuView) findViewById(R.id.danmaku_view);
mSendDanmaku = (TextView) findViewById(R.id.send_danmaku);
mToogleDanmaku = (TextView) findViewById(R.id.toogle_danmaku);
//初始化弹幕显示
initDanmaku();
mSendDanmaku.setOnClickListener(this);
mToogleDanmaku.setOnClickListener(this);
}
@Override
public void onPrepared() {
super.onPrepared();
onPrepareDanmaku(this);
}
@Override
public void onVideoPause() {
super.onVideoPause();
if (mDanmakuView != null && mDanmakuView.isPrepared()) {
mDanmakuView.pause();
}
}
@Override
public void onVideoResume() {
super.onVideoResume();
if (mDanmakuView != null && mDanmakuView.isPrepared() && mDanmakuView.isPaused()) {
mDanmakuView.resume();
}
}
@Override
public void onCompletion() {
releaseDanmaku(this);
}
@Override
public void onSeekComplete() {
super.onSeekComplete();
int time = mProgressBar.getProgress() * getDuration() / 100;
//如果已经初始化过的,直接seek到对于位置
if (mHadPlay && getDanmakuView() != null && getDanmakuView().isPrepared()) {
resolveDanmakuSeek(this, time);
} else if (mHadPlay && getDanmakuView() != null && !getDanmakuView().isPrepared()) {
//如果没有初始化过的,记录位置等待
setDanmakuStartSeekPosition(time);
}
}
@Override
public void onClick(View v) {
super.onClick(v);
switch (v.getId()) {
case R.id.send_danmaku:
addDanmaku(true);
break;
case R.id.toogle_danmaku:
mDanmaKuShow = !mDanmaKuShow;
resolveDanmakuShow();
break;
}
}
/**
* 处理播放器在全屏切换时,弹幕显示的逻辑
* 需要格外注意的是,因为全屏和小屏,是切换了播放器,所以需要同步之间的弹幕状态
*/
@Override
public GSYBaseVideoPlayer startWindowFullscreen(Context context, boolean actionBar, boolean statusBar) {
GSYBaseVideoPlayer gsyBaseVideoPlayer = super.startWindowFullscreen(context, actionBar, statusBar);
if (gsyBaseVideoPlayer != null) {
DanmakuVideoPlayer gsyVideoPlayer = (DanmakuVideoPlayer) gsyBaseVideoPlayer;
//对弹幕设置偏移记录
gsyVideoPlayer.setDanmakuStartSeekPosition(getCurrentPositionWhenPlaying());
gsyVideoPlayer.setDanmaKuShow(getDanmaKuShow());
onPrepareDanmaku(gsyVideoPlayer);
}
return gsyBaseVideoPlayer;
}
/**
* 处理播放器在退出全屏时,弹幕显示的逻辑
* 需要格外注意的是,因为全屏和小屏,是切换了播放器,所以需要同步之间的弹幕状态
*/
@Override
protected void resolveNormalVideoShow(View oldF, ViewGroup vp, GSYVideoPlayer gsyVideoPlayer) {
super.resolveNormalVideoShow(oldF, vp, gsyVideoPlayer);
if (gsyVideoPlayer != null) {
DanmakuVideoPlayer gsyDanmaVideoPlayer = (DanmakuVideoPlayer) gsyVideoPlayer;
setDanmaKuShow(gsyDanmaVideoPlayer.getDanmaKuShow());
if (gsyDanmaVideoPlayer.getDanmakuView() != null &&
gsyDanmaVideoPlayer.getDanmakuView().isPrepared()) {
resolveDanmakuSeek(this, gsyDanmaVideoPlayer.getCurrentPositionWhenPlaying());
resolveDanmakuShow();
releaseDanmaku(gsyDanmaVideoPlayer);
}
}
}
private void initDanmaku() {
// 设置最大显示行数
HashMap<Integer, Integer> maxLinesPair = new HashMap<Integer, Integer>();
maxLinesPair.put(BaseDanmaku.TYPE_SCROLL_RL, 5); // 滚动弹幕最大显示5行
// 设置是否禁止重叠
HashMap<Integer, Boolean> overlappingEnablePair = new HashMap<Integer, Boolean>();
overlappingEnablePair.put(BaseDanmaku.TYPE_SCROLL_RL, true);
overlappingEnablePair.put(BaseDanmaku.TYPE_FIX_TOP, true);
DanamakuAdapter danamakuAdapter = new DanamakuAdapter(mDanmakuView);
mDanmakuContext = DanmakuContext.create();
mDanmakuContext.setDanmakuStyle(IDisplayer.DANMAKU_STYLE_STROKEN, 3).setDuplicateMergingEnabled(false).setScrollSpeedFactor(1.2f).setScaleTextSize(1.2f)
.setCacheStuffer(new SpannedCacheStuffer(), danamakuAdapter) // 图文混排使用SpannedCacheStuffer
.setMaximumLines(maxLinesPair)
.preventOverlapping(overlappingEnablePair);
if (mDanmakuView != null) {
//todo 替换成你的数据流
mParser = createParser(this.getResources().openRawResource(R.raw.comments));
mDanmakuView.setCallback(new master.flame.danmaku.controller.DrawHandler.Callback() {
@Override
public void updateTimer(DanmakuTimer timer) {
}
@Override
public void drawingFinished() {
}
@Override
public void danmakuShown(BaseDanmaku danmaku) {
}
@Override
public void prepared() {
if (getDanmakuView() != null) {
getDanmakuView().start();
if (getDanmakuStartSeekPosition() != -1) {
resolveDanmakuSeek(DanmakuVideoPlayer.this, getDanmakuStartSeekPosition());
setDanmakuStartSeekPosition(-1);
}
resolveDanmakuShow();
}
}
});
mDanmakuView.enableDanmakuDrawingCache(true);
}
}
/**
* 弹幕的显示与关闭
*/
private void resolveDanmakuShow() {
post(new Runnable() {
@Override
public void run() {
if (mDanmaKuShow) {
if (!getDanmakuView().isShown())
getDanmakuView().show();
mToogleDanmaku.setText("弹幕关");
} else {
if (getDanmakuView().isShown()) {
getDanmakuView().hide();
}
mToogleDanmaku.setText("弹幕开");
}
}
});
}
/**
* 开始播放弹幕
*/
private void onPrepareDanmaku(DanmakuVideoPlayer gsyVideoPlayer) {
if (gsyVideoPlayer.getDanmakuView() != null && !gsyVideoPlayer.getDanmakuView().isPrepared()) {
gsyVideoPlayer.getDanmakuView().prepare(gsyVideoPlayer.getParser(),
gsyVideoPlayer.getDanmakuContext());
}
}
/**
* 弹幕偏移
*/
private void resolveDanmakuSeek(DanmakuVideoPlayer gsyVideoPlayer, long time) {
if (GSYVideoManager.instance().getMediaPlayer() != null && mHadPlay
&& gsyVideoPlayer.getDanmakuView() != null && gsyVideoPlayer.getDanmakuView().isPrepared()) {
gsyVideoPlayer.getDanmakuView().seekTo(time);
}
}
/**
* 创建解析器对象,解析输入流
*
* @param stream
* @return
*/
private BaseDanmakuParser createParser(InputStream stream) {
if (stream == null) {
return new BaseDanmakuParser() {
@Override
protected Danmakus parse() {
return new Danmakus();
}
};
}
ILoader loader = DanmakuLoaderFactory.create(DanmakuLoaderFactory.TAG_BILI);
try {
loader.load(stream);
} catch (IllegalDataException e) {
e.printStackTrace();
}
BaseDanmakuParser parser = new BiliDanmukuParser();
IDataSource<?> dataSource = loader.getDataSource();
parser.load(dataSource);
return parser;
}
/**
* 释放弹幕控件
*/
private void releaseDanmaku(DanmakuVideoPlayer danmakuVideoPlayer) {
if (danmakuVideoPlayer != null && danmakuVideoPlayer.getDanmakuView() != null) {
Debuger.printfError("release Danmaku!");
danmakuVideoPlayer.getDanmakuView().release();
}
}
public BaseDanmakuParser getParser() {
return mParser;
}
public DanmakuContext getDanmakuContext() {
return mDanmakuContext;
}
public IDanmakuView getDanmakuView() {
return mDanmakuView;
}
public long getDanmakuStartSeekPosition() {
return mDanmakuStartSeekPosition;
}
public void setDanmakuStartSeekPosition(long danmakuStartSeekPosition) {
this.mDanmakuStartSeekPosition = danmakuStartSeekPosition;
}
public void setDanmaKuShow(boolean danmaKuShow) {
mDanmaKuShow = danmaKuShow;
}
public boolean getDanmaKuShow() {
return mDanmaKuShow;
}
/**
* 模拟添加弹幕数据
*/
private void addDanmaku(boolean islive) {
BaseDanmaku danmaku = mDanmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);
if (danmaku == null || mDanmakuView == null) {
return;
}
danmaku.text = "这是一条弹幕 " + getCurrentPositionWhenPlaying();
danmaku.padding = 5;
danmaku.priority = 8; // 可能会被各种过滤器过滤并隐藏显示,所以提高等级
danmaku.isLive = islive;
danmaku.setTime(mDanmakuView.getCurrentTime() + 500);
danmaku.textSize = 25f * (mParser.getDisplayer().getDensity() - 0.6f);
danmaku.textColor = Color.RED;
danmaku.textShadowColor = Color.WHITE;
danmaku.borderColor = Color.GREEN;
mDanmakuView.addDanmaku(danmaku);
}
}
3.控制视频播放代码:
主要是在activity的oncreate方法中:
//使用自定义的全屏切换图片,!!!注意xml布局中也需要设置为一样的
//必须在setUp之前设置
danmakuVideoPlayer.setShrinkImageRes(R.drawable.custom_shrink);
danmakuVideoPlayer.setEnlargeImageRes(R.drawable.custom_enlarge);
String url = "https://res.exexm.com/cw_145225549855002";
danmakuVideoPlayer.setUp(url, true, null, "测试视频");
//增加封面
ImageView imageView = new ImageView(this);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageResource(R.mipmap.xxx1);
danmakuVideoPlayer.setThumbImageView(imageView);
resolveNormalVideoUI();
//外部辅助的旋转,帮助全屏
orientationUtils = new OrientationUtils(this, danmakuVideoPlayer);
//初始化不打开外部的旋转
orientationUtils.setEnable(false);
danmakuVideoPlayer.setIsTouchWiget(true);
//关闭自动旋转
danmakuVideoPlayer.setRotateViewAuto(false);
danmakuVideoPlayer.setLockLand(false);
danmakuVideoPlayer.setShowFullAnimation(false);
danmakuVideoPlayer.setNeedLockFull(true);
//detailPlayer.setOpenPreView(true);
danmakuVideoPlayer.getFullscreenButton().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//直接横屏
orientationUtils.resolveByClick();
//第一个true是否需要隐藏actionbar,第二个true是否需要隐藏statusbar
danmakuVideoPlayer.startWindowFullscreen(GsyActivity.this, true, true);
}
});
danmakuVideoPlayer.setStandardVideoAllCallBack(new SampleListener() {
@Override
public void onPrepared(String url, Object... objects) {
super.onPrepared(url, objects);
//开始播放了才能旋转和全屏
orientationUtils.setEnable(true);
isPlay = true;
}
@Override
public void onAutoComplete(String url, Object... objects) {
super.onAutoComplete(url, objects);
}
@Override
public void onClickStartError(String url, Object... objects) {
super.onClickStartError(url, objects);
}
@Override
public void onQuitFullscreen(String url, Object... objects) {
super.onQuitFullscreen(url, objects);
if (orientationUtils != null) {
orientationUtils.backToProtVideo();
}
}
});
danmakuVideoPlayer.setLockClickListener(new LockClickListener() {
@Override
public void onClick(View view, boolean lock) {
if (orientationUtils != null) {
//配合下方的onConfigurationChanged
orientationUtils.setEnable(!lock);
}
}
});