4.1 广告功能
- 本功能需要后台开通移动广告;
- 广告核心类DWMediaAD提供能了获取广告信息的方法,广告详细信息通过DWMediaADListener监听器回调来获取;
- 广告分为前贴、暂停、片尾,需要分别调用方法来获取,提供了视频和图片广告。
……
DWMediaAD mDWMediaAD = new DWMediaAD(dwMediaADlistener, USERID, videoId);
mDWMediaAD.getFrontAD();
mDWMediaAD.getPauseAD();
mDWMediaAD.getEndAD();
……
// 广告监听器
private DWMediaADListener dwMediaADListener = new DWMediaADListener() {
//回调片头广告信息
@Override
public void onFrontAD(FrontADInfo info) {
}
//回调暂停广告信息
@Override
public void onPauseAD(PauseADInfo info) {
}
//回调片尾广告信息
@Override
public void onEndAD(EndADInfo info) {
}
@Override
public void onFrontADError(HuodeException e) {
}
@Override
public void onPauseADError(HuodeException e) {
}
@Override
public void onEndADError(HuodeException e) {
}
};
注:目前只提供获取广告信息的接口,广告界面需要用户自行实现
4.2 用户自定义参数播放统计功能
支持用户自定义参数实现播放的统计,可以通过调用player的setCustomId(String customId)方法来实现,其中customId为用户自己定义的参数值。
//设置CustomId
player.setCustomId("Huode");
注:需要在prepareAsync()方法前调用才可以生效。
4.3 视频打点功能
支持用户自定义视频打点功能的回调,可以通过调用player的setOnHotspotListener(OnHotspotListener onHotspotListener)方法,当视频有打点信息时,在该接口中回调打点信息。
//获得视频打点信息
player.setOnHotspotListener(new OnHotspotListener() {
/**
* @param hotspotMap key为时间(秒),value是打点描述
*/
@Override
public void onHotspots(TreeMap<Integer, String> hotspotMap) {
}
});
4.4 视频问答功能
支持用户自定义视频问答功能的回调,可以通过调用player的setOnQAMsgListener(OnQAMsgListener qaMsgListener)方法,当视频有问答信息时,在该接口中回调问答信息。
//获得视频问答信息
player.setOnQAMsgListener(new OnQAMsgListener() {
/**
* @param qaJsonArray,单条信息包含有question和answer
*/
@Override
public void onQAMessage(JSONArray qaJsonArray) {
}
});
问答信息回调的格式为JSONArray,单条问答信息的内容如下,请用户自行解析。
{
"answers": [
{
"content": "A、答案A",
"id": 1045,
"right": false
},
{
"content": "B、答案B",
"id": 1046,
"right": true
},
{
"content": "C、答案C",
"id": 1047,
"right": false
},
{
"content": "D、答案D",
"id": 1048,
"right": false
}
],
"backSecond": -1,
"keepPlay":true,
"content": "内容",
"explainInfo": "解释答案",
"id": 99,
"jump": false,
"showTime": 2
}
4.5 视频显示字幕功能
4.5.1 在线字幕
支持从服务器获取字幕资源并显示,可以通过调用player的setOnSubtitleMsgListener(OnSubtitleMsgListener onSubtitleMsgListener)方法,当有字幕资源时,在该接口中回调字幕信息。
//获得字幕信息
player.setOnSubtitleMsgListener(new OnSubtitleMsgListener() {
/**
* 第一种字幕,设置这些字幕样式需要在主线程操作
* @param subtitleName 字幕名称
* @param sort 字幕位置顺序
* @param url 字幕资源地址
* @param font 字体名称,需要在工程的assets(没有请自行创建)
* 文件夹下有对应的字体文件,自行实现字体显示逻辑
* @param size 字体大小
* @param color 字体颜色
* @param surroundColor 字体环绕色
* @param bottom 距离底部的边距占手机屏幕宽度的百分比
* @param code 字幕编码格式,如utf-8
*/
@Override
public void onSubtitleMsg(String subtitleName, int sort, String url, String font, int size, String color, String surroundColor, double bottom, String code) {
}
/**
* 第二种字幕,设置这些字幕样式需要在主线程操作
* @param subtitleName 字幕名称
* @param sort 字幕位置顺序
* @param url 字幕资源地址
* @param font 字体名称,需要在工程的assets(没有请自行创建)
* 文件夹下有对应的字体文件,自行实现字体显示逻辑
* @param size 字体大小
* @param color 字体颜色
* @param surroundColor 字体环绕色
* @param bottom 距离底部的边距占手机屏幕宽度的百分比
* @param code 字幕编码格式,如utf-8
*/
@Override
public void onSecSubtitleMsg(String subtitleName, int sort, String url, String font, int size, String color, String surroundColor, double bottom, String code) {
}
/**
* @param defaultSubtitle 0默认显示第一种字幕,1默认显示第二种字幕,2默认显示双语字幕
*/
@Override
public void onDefSubtitle(int defaultSubtitle) {
}
});
4.5.2 离线字幕
在下载视频时,如果视频存在字幕文件,可以同时下载字幕,通过downloader.setDownloadSubtitle(downloadSubtitlePath,subtitleName)设置下载字幕,只有同时设置了downloadSubtitlePath和subtitleName,才会下载字幕,downloadSubtitlePath的格式如 "/storage/emulated/0/HuodeDownload/",subtitleName的格式如"huode", 最终字幕一(如有)的保存路径是downloadSubtitlePath+subtitleName+"subtitle.srt",字幕二(如有)的保存路径是downloadSubtitlePath+subtitleName+"subtitle2.srt", 字幕设置(如有)的保存路径是downloadSubtitlePath+subtitleName+"subtitleSet.json"。
//设置下载字幕
downloader.setDownloadSubtitle(downloadSubtitlePath, subtitleName);
下载字幕回调。
//字幕回调
downloader.setOnDownloadSubtitleListener(new OnDownloadSubtitleListener() {
//字幕数量subtitleNum,0:无字幕 1:一种字幕 2:二种字幕
@Override
public void onSubtitleNum(int subtitleNum) {
}
//视频存在字幕一时才会回调,保存字幕成功,subtitlePath:字幕保存路径
@Override
public void onDownloadFirstSubtitleSuccess(String subtitlePath) {
}
//视频存在字幕一时才会回调,保存字幕失败,subtitlePath:字幕保存路径 subtitleUrl:字幕资源地址
@Override
public void onDownloadFirstSubtitleFail(String subtitlePath, String subtitleUrl) {
}
//视频存在字幕二时才会回调,保存字幕成功,subtitlePath:字幕保存路径
@Override
public void onDownloadSecondSubtitleSuccess(String subtitlePath) {
}
//视频存在字幕二时才会回调,保存字幕失败,subtitlePath:字幕保存路径 subtitleUrl:字幕资源地址
@Override
public void onDownloadSecondSubtitleFail(String subtitlePath, String subtitleUrl) {
}
//存在字幕设置时回调,保存字幕设置成功,subtitleSetPath:字幕设置文件的保存路径
@Override
public void onSaveSubtitleSetSuccess(String subtitleSetPath) {
}
//存在字幕设置时回调,保存字幕设置失败,subtitleSetInfo:字幕设置信息
@Override
public void onSaveSubtitleSetFail(String subtitleSetInfo) {
}
});
4.5.3 字幕自适应
支持从服务器设定当前字幕字体大小显示的方式,固定字号或跟随播放器大小变化的自适应模式。同时支持SDK本地设置字体模式。SDK声明了枚举SubtitleModel类,FIXED(固定)与SELF_ADAPTION(自适应)用于设定当前类型。
注意:
1.SDK本地设置的优先级要高于服务器获取。
2.Demo中,本地缓存视频的字幕模式跟随当前下载时的字幕模式。如有其他需求,可根据自己的业务加以调整。SubtitleView类中同样提供了setSubtitleModel方法。
player.setSubtitleModel(SubtitleModel.FIXED);
player.setSubtitleModel(SubtitleModel.SELF_ADAPTION);
4.6 访客信息收集功能
支持从服务器获取访客信息收集设置并显示,可以通过调用player的setOnVisitMsgListener(OnVisitMsgListener onVisitMsgListener)方法,得到访客信息收集设置。
//获得访客信息设置
player.setOnVisitMsgListener(new OnVisitMsgListener() {
/**
* @param appearTime 收集器出现的时间(S)
* @param imageURL 图片地址
* @param isJump 是否需要跳过 1跳过,0不跳过
* @param jumpURL 图片跳转的地址
* @param title 收集器名称
* @param visitorId 收集器ID
* @param visitorMessage //要收集的信息
*/
@Override
public void onVisitMsg(int appearTime, String imageURL, int isJump, String jumpURL, String title, String visitorId, JSONArray visitorMessage) {
}
});
4.7 倍速功能
倍速功能使用第三方库IjkMediaPlayer v0.8.4来实现。倍速播放功能需要使用DWIjkMediaPlayer类,该类继承自第三方库IjkMediaPlayer的IjkMediaPlayer类,该类的使用方法和DWMediaPlayer一样。
IjkMeidaPlayer的github地址如下:请参考链接:https://github.com/Bilibili/ijkplayer
设置倍速方法如下:
player.setSpeed();
ijkspeed文件夹为ijk所需要的so文件和jar,请放到自己的工程目录使用。
4.8 辅助调试工具
SDK提供HTTP通信日志调试功能。在使用SDK进行播放、上传、下载过程中,如果遇到与网络通信相关的问题,可通过设置HTTP日志的级别获取通信信息。使用示例如下:
// 设置HTTP通信日志级别
HttpUtil.LOG_LEVEL = HttpLogLevel.DETAIL;
默认日志级别为GENERAL(记录HTTP通信发生时间、响应状态码)。
4.9 问答统计功能
要统计问答的结果,只需在提交答案时调用下面这个方法:
/**
* @param vid 加密的视频ID
* @param qid 问题ID
* @param answer 用户选择的选项ID,以逗号分隔多个选项ID。如1345是单选;2067,3092,4789是多选。
* @param status 用户答题的结果。1=正确;0=错误。
*/
QaStatistics.reportQaResult(String vid, String qid, String answer, String status);
4.10 授权验证功能
从服务器获取授权验证信息,可以通过调用player的setOnAuthMsgListener(OnAuthMsgListener onAuthMsgListener)方法,在该接口中回调授权验证信息。
//获得授权验证信息
player.setOnAuthMsgListener(new OnAuthMsgListener() {
/**
* @param enable 视频是否可以完整播放 0:不允许完整播放 1:允许完整播放
* @param freetime 视频试看时间,单位:秒
* @param messaage 不允许播放,或者试看结束时播放器显示的提示内容
* @param marqueeInfo 跑马灯信息,具体使用方法请参考4.18章节
*/
@Override
public void onAuthMsg(int enable, int freetime, String messaage, MarqueeInfo marqueeInfo) {
}
});
4.11 视频压缩功能
可以选择高质量压缩、中质量压缩、低质量压缩,压缩质量越高,压缩出来的文件就相对较大。
/**
* 高质量压缩
* @param filePath 源文件路径
* @param compressOutPut 输出文件路径
* @param VideoCompress.CompressListener 压缩过程监听
*/
VideoCompress.compressVideoHigh(filePath, compressOutPut, new VideoCompress.CompressListener() {
@Override
public void onStart() {
}
@Override
public void onSuccess() {
}
@Override
public void onFail() {
}
@Override
public void onProgress(float percent) {
}
});
/**
* 中质量压缩
* @param filePath 源文件路径
* @param compressOutPut 输出文件路径
* @param VideoCompress.CompressListener 压缩过程监听
*/
VideoCompress.compressVideoMedium(filePath, compressOutPut, new VideoCompress.CompressListener() {
@Override
public void onStart() {
}
@Override
public void onSuccess() {
}
@Override
public void onFail() {
}
@Override
public void onProgress(float percent) {
}
});
/**
* 低质量压缩
* @param filePath 源文件路径
* @param compressOutPut 输出文件路径
* @param VideoCompress.CompressListener 压缩过程监听
*/
VideoCompress.compressVideoLow(filePath, compressOutPut, new VideoCompress.CompressListener() {
@Override
public void onStart() {
}
@Override
public void onSuccess() {
}
@Override
public void onFail() {
}
@Override
public void onProgress(float percent) {
}
});
4.12 课堂练习功能
支持用户自定义课堂练习功能的回调,可以通过调用player的setOnExercisesMsgListener(OnExercisesMsgListener onExercisesMsgListener)方法,当视频有课堂练习信息时,在该接口中回调课堂练习信息。
//获得视频课堂练习信息
player.setOnExercisesMsgListener(new OnExercisesMsgListener() {
@Override
public void onExercisesMessage(JSONArray exArray) {
}
});
课堂练习回调的格式为JSONArray,单条课堂练习的内容如下,请用户自行解析。
{
"id": 86,
"backSecond": 5,//回看时间
"isJump": 0,//是否允许跳过 1跳过 ,0不跳过
"isPlay": 0,//答错是否可以继续 0不能, 1 能
"questions": [
{
"answers": [
{
"content": "A、答案A",
"id": 608,
"right": true
},
{
"content": "B、答案B",
"id": 609,
"right": true
},
{
"content": "C、答案C",
"id": 610,
"right": true
},
{
"content": "D、答案D",
"id": 615,
"right": false
}
],
"backSecond": 3,//回看时间
"content": "题目",
"explainInfo": "试题详解",
"id": 414,
"type": 1
}
],
"showTime": 20,
"title": "课堂练习"
}
4.13 投屏功能
在播放时可以投射到电视或其他支持投屏的设备,分为非加密视频的投屏和加密视频的投屏。
4.13.1 非加密视频的投屏
//搜索发现设备
registryListener.setOnDeviceListChangedListener(new ProjectionDeviceListChangedListener() {
@Override
public void onDeviceAdded(ProjectionIDevice device) {
//发现设备
}
@Override
public void onDeviceRemoved(ProjectionIDevice device) {
//设备移除
}
});
//播放新的视频
projectionPlayControl.playNew(playUrl, new ProjectionControlCallback() {
@Override
public void success(ProjectionIResponse response) {
}
@Override
public void fail(ProjectionIResponse response) {
}
});
//暂停后恢复播放
projectionPlayControl.play(new ProjectionControlCallback() {
@Override
public void success(ProjectionIResponse response) {
}
@Override
public void fail(ProjectionIResponse response) {
}
});
//暂停播放
projectionPlayControl.pause(new ProjectionControlCallback() {
@Override
public void success(ProjectionIResponse response) {
}
@Override
public void fail(ProjectionIResponse response) {
}
});
4.13.2 加密视频的投屏
加密视频不可直接投屏,请打开手机的投屏功能,详情参考Demo。
4.14 防录屏
在播放视频时,调用setAntiRecordScreen()方法防录屏。
//开启防录屏,会使加密视频投屏功能不能正常使用
player.setAntiRecordScreen(activity);
4.15 视频水印
上传视频的时候,支持为视频配置水印。
//水印位置0,左上 1右上 2左下 3右下,默认3,非必填
videoInfo.setCorner(int corner);
//X轴偏移像素值,要求大于0,默认值5,超出视频大小按默认值,非必填
videoInfo.setOffsetx(int offsetx);
//Y轴偏移像素值,要求大于0,默认值5,超出视频大小按默认值,非必填
videoInfo.setOffsety(int offsety);
//字体类型:0,微软雅黑 1宋体 2黑体,默认0,非必填
videoInfo.setFontfamily(int fontfamily);
//字体大小,[0-100],默认12
videoInfo.setFontsize(int fontsize);
//16进制字体颜色,如#FFFFFF,不能写#号,默认灰色D3D3D3,非必填
videoInfo.setFontcolor(String fontcolor);
//透明度,[0-100],默认0,100为不透明,非必填
videoInfo.setFontalpha(int fontalpha);
//水印文字内容, 1-50个字符,数字、字母、汉字,不填写则文字水印不生效,填写错误,会导致上传失败
videoInfo.setText(String text);
4.16 切换到备用线路
调用player.setBackupPlay(true)方法切换到备用线路。
4.17 获取播放时长和暂停时长
//获取播放时长(单位是秒)
player.getPlayedTime();
//获取暂停时长(单位是秒)
player.getPausedTime();
//当切换到另外一个视频时,需要调用player.resetPlayedAndPausedTime(),将上一个视频的播放时长和暂停时长重置为0
player.resetPlayedAndPausedTime();
4.18 跑马灯
使用跑马灯。
<com.bokecc.sdk.mobile.play.MarqueeView
android:id="@+id/mv_video"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
获取跑马灯数据。
1.获取在线视频跑马灯数据
player.setOnAuthMsgListener(new OnAuthMsgListener() {
//marqueeInfo:跑马灯信息
@Override
public void onAuthMsg(int enable, int freetime, String messaage, MarqueeInfo marqueeInfo) {
//获得跑马灯类型,text:文字,image:图片
String type = marqueeInfo.getType();
//获得循环次数
int loop = marqueeInfo.getLoop();
//获得文字信息
MarqueeInfo.TextBean textBean = marqueeInfo.getTextBean();
//获得文字内容
String content = textBean.getContent();
//获得字体大小
int font_size = textBean.getFont_size();
//获得文字颜色
String color = textBean.getColor();
if (!TextUtils.isEmpty(color) && color.length() == 8) {
String textColor = "#" + color.substring(2, 8);
if (textColor.length() == 7) {
//textColor:文字颜色,格式如:#ffffff
mv_video.setTextColor(textColor);
}
}
//获得图片信息
MarqueeInfo.ImageBean imageBean = marqueeInfo.getImageBean();
//获得图片url
String image_url= imageBean.getImage_url();
//获得图片宽度
int width= imageBean.getWidth();
//获得图片高度
int width = imageBean.getHeight();
//获得动作节点
ArrayList<MarqueeAction> action = marqueeInfo.getAction();
}
});
2.获取离线视频跑马灯数据
跑马灯的相关数据会跟随视频下载,demo将该数据中保存在了本地数据库object-box中,用户可根据自身逻辑和场景,进行更改和保存。demo中由DownloadInfo.getMarqueeData()方法获取到序列化到本地的String类型的跑马灯数据 marqueeData,之后作为参数传入player的getMarqueeInfo()方法,该方法会返回MarqueeInfo对象,用于MarqueeView使用和展示。具体请参考demo中使用。
if (!TextUtils.isEmpty(marqueeData)) {
MarqueeInfo marqueeInfo=player.getMarqueeInfo(marqueeData);
setMarqueeView(marqueeInfo);
}
设置跑马灯类型。
//MarqueeView.TEXT:文字 MarqueeView.IMAGE:图片
mv_video.setType();
设置循环次数。
//loop:为-1时是无限循环,为其他正整数时是有限次循环
mv_video.setLoop(loop);
设置跑马灯动作节点,可定义多个节点。
//创建动作节点
MarqueeAction marqueeAction = new MarqueeAction();
//index:动作的执行顺序
marqueeAction.setIndex(index);
//duration:动作的执行时间(单位:ms)
marqueeAction.setDuration(duration);
//startXpos:动作起始点距离视频左上角原点水平距离,数据类型float,取值范围0~1,
//具体距离:视频宽度*startXpos
marqueeAction.setStartXpos(startXpos);
//startYpos:动作起始点距离视频左上角原点垂直距离,数据类型float,取值范围0~1
//具体距离:视频高度*startYpos
marqueeAction.setStartYpos(startYpos);
//startAlpha:起始点透明度,数据类型float,取值范围0~1
marqueeAction.setStartAlpha(startAlpha);
//endXpos:动作结束点距离视频左上角原点水平距离,数据类型float,取值范围0~1,
//具体距离:视频宽度*endXpos
marqueeAction.setEndXpos(endXpos);
//endYpos:动作结束点距离视频左上角原点垂直距离,数据类型float,取值范围0~1
//具体距离:视频高度*endYpos
marqueeAction.setEndYpos(endYpos);
//endAlpha:结束点透明度,数据类型float,取值范围0~1
marqueeAction.setEndAlpha(endAlpha);
//设置动作节点,marqueeActions:一组动作节点
mv_video.setMarqueeActions(marqueeActions);
设置文字内容。
//textContent:是文字内容
mv_video.setTextContent(textContent);
设置文字字体大小。
//textSize:文字字体大小(单位px)
mv_video.setTextFontSize(textSize);
设置文字颜色。
//textColor:文字颜色,如#ffffff
mv_video.setTextColor(textColor);
通过url设置跑马灯图片。
/**
* @param activity 上下文
* @param imageUrl 图片url
* @param imageWidth 图片宽度(单位px)
* @param imageHeight 图片高度(单位px)
*/
mv_video.setMarqueeImage(activity, imageUrl, imageWidth, imageHeight);
//设置跑马灯图片加载监听
mv_video.setOnMarqueeImgFailListener(new OnMarqueeImgFailListener() {
@Override
public void onLoadMarqueeImgFail() {
}
});
通过Bitmap设置跑马灯图片。
/**
* @param bitmap 图片bitmap
* @param imageWidth 图片宽度(单位px)
* @param imageHeight 图片高度(单位px)
*/
mv_video.setMarqueeImage(bitmap, imageWidth, imageHeight);
运行跑马灯。
mv_video.start();
4.19 小窗播放
Android 8.0及以上系统支持小窗播放,具体使用请参考Demo。
在AndroidManifest.xml文件中给播放Activity配置android:supportsPictureInPicture="true"和android:configChanges="smallestScreenSize|screenLayout|orientation"(避免Activity销毁重建)。
<activity
android:name=".play.MediaPlayActivity"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout"
android:screenOrientation="portrait"
android:supportsPictureInPicture="true" />
进入小窗播放,以下是部分代码示例,详细代码参考Demo:
private PictureInPictureParams.Builder builder;
private void useSmallWindowPlay() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (builder == null) {
builder = new PictureInPictureParams.Builder();
}
int width = rl_play_video.getWidth();
int height = rl_play_video.getHeight();
// 设置宽高比例值
if (width > 0 && height > 0) {
float whRate = MultiUtils.calFloat(2, width, height);
if (whRate > 0.42 && whRate < 2.39) {
Rational aspectRatio = new Rational(width, height);
builder.setAspectRatio(aspectRatio);
}
}
if (actions != null && actions.size() > 0) {
actions.clear();
}
if (player.isPlaying()) {
actions.add(pauseRemoteAction);
} else {
actions.add(playRemoteAction);
}
if (actions != null && actions.size() > 0) {
builder.setActions(actions);
}
// 进入小窗模式
enterPictureInPictureMode(builder.build());
}
}
4.20 视频截图
通过调用player.getVideoScreenShot(bitmap, videoScreenShotOutPath)获取当前播放视频的截图。
private void getVideoScreenShot() {
String videoScreenShotOutPath = MultiUtils.getVideoScreenShotOutPath();
if (!TextUtils.isEmpty(videoScreenShotOutPath)) {
Bitmap bitmap = tv_video.getBitmap();
//bitmap:视频画面的bitmap videoScreenShotOutPath:截图输出路径
boolean videoScreenShot = player.getVideoScreenShot(bitmap, videoScreenShotOutPath);
if (videoScreenShot) {
//通知系统相册更新
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.fromFile(new File(videoScreenShotOutPath))));
}
}
}
4.21 弹幕功能
发送弹幕。
/**
* @param videoId 视频ID
* @param danmuText 弹幕文字
* @param currentPosition 发送弹幕时的视频播放位置
* @param danmuColor 弹幕颜色(格式如:0xffffff)
* @param onSendDanmuListener 发送结果
*/
player.sendDanmu(videoId, danmuText, currentPosition, danmuColor, new OnSendDanmuListener() {
@Override
public void onSuccess() {
runOnUiThread(new Runnable() {
@Override
public void run() {
isCanSendDanmu = false;
sendDanmuInterval = 5;
addDanmu(danmuText, danmuColor, currentPosition, true);
}
});
}
@Override
public void onFail(final String msg) {
runOnUiThread(new Runnable() {
@Override
public void run() {
MultiUtils.showToast(activity, "发送弹幕失败:" + msg);
}
});
}
});
获取弹幕数据。
/**
* @param videoId 视频ID
* @param sec 段号
*每隔1分钟调用1次,段号递增
*/
player.getDanmuList(videoId, sec);
//查询弹幕结果
player.setOnDanmuListListener(new OnDanmuListListener() {
/**
* @param danmuInfos 弹幕信息
* danmuInfo组成字段:
* content:字幕内容 fc:字幕颜色,格式如:0xffffff
* pt:字幕相对于视频出现的时间
*/
@Override
public void onSuccess(final ArrayList<DanmuInfo> danmuInfos) {
runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
}
@Override
public void onFail(String msg) {
}
});
弹幕功能的演示请参考Demo。
4.22 设置用户标识
//setClientId()方法在setVideoPlayInfo()前调用,可以通过此方法设置用户标识,出问题时方便排查
player.setClientId("");
4.23 动感视频功能
支持在关键点震动提醒,详情参考Demo。
//添加震动权限
<uses-permission android:name="android.permission.VIBRATE"/>
Vibrator vibrator = vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
if (vibrator.hasVibrator() && isDynamicVideo){
//震动时长,单位毫秒
vibrator.vibrate(500);
}
//不用震动的时候,调用cancel()取消
if (vibrator != null) {
vibrator.cancel();
}
4.24 防拖拽
启用防拖拽功能,未看部分禁止拖动,将isForbidDragToUnPlayPart的值改为true,详情参考Demo。
//未看部分禁止拖动:isForbidDragToUnPlayPart为false时允许拖动到未看部分,为true时不允许拖动到未看部分
private boolean isForbidDragToUnPlayPart = true;
4.25 自定义Logo
在布局中使用CustomLogoView。
<com.bokecc.vod.view.CustomLogoView
android:id="@+id/clv_logo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" />
设置Logo,logo图片不宜太大,控制在100KB内。
/**
* @param img 图片地址
* @param xPosRate 相对于左上角的X轴位置偏移量与播放窗口宽度的比例
* @param yPosRate 相对于左上角的Y轴位置偏移量播放窗口高度的比例
* @param logoWidthRate Logo宽度相对于播放窗口宽度的比例
* @param logoHeightRate Logo高度相对于播放窗口高度的比例
*/
clv_logo.setCustomLogoInfo(img, xPosRate, yPosRate, logoWidthRate, logoHeightRate);
展示logo,调用clv_logo.show()。
clv_logo.show();
横竖屏切换时,刷新Logo。
//刷新logo视图
clv_logo.refreshView();
4.26 错误处理
错误信息有两种,一种是播放器触发的错误,另一种是获得场景视频自定义的错误。
4.26.1 监听播放器的错误事件
DWMediaPlayer重载了MediaPlayer的setOnErrorListener()方法,如果需要在应用中提示错误信息,可调用此方法设置OnErrorListener。具体实现方式如下:
player.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
//在这里进行错误处理
return true;
}
});
4.26.2 监听获得场景视频自定义的错误事件
player.setOnDreamWinErrorListener(new OnDreamWinErrorListener() {
@Override
public void onPlayError(HuodeException e) {
//在这里进行错误处理
}
});
4.27 错误码
4.27.1 HuodeException自定义的错误码
101:无播放节点
102:视频无播放节点
103:音频无播放节点
104:授权验证失败
105:视频无法播放,请检查视频状态
106:请求播放数据失败,检查网络连接,检查UserId和ApiKey是否正确
107:服务端响应失败
108:获取服务器信息失败
109:视频已删除
111:请求播放数据时出现未知错误
112:获取当前播放清晰度出现异常
113:播放离线视频时出现未知错误
201:下载地址不存在
202:视频下载节点不存在
203:下载失败,请检查视频状态
204:下载授权验证失败
205:请求下载数据失败
206:请求下载,服务端响应失败
207:下载请求的结果无效
208:获取下载清晰度的OnProcessDefinitionListener为空
209:设置下载结束点异常
210:请求下载地址响应码异常
211:被请求的下载文件无效或者本地设置的下载路径无效
212:下载初始化时出现IO异常
213:下载初始化时出现JSONException
214:下载初始化时出现NullPointerException
215:下载初始化时出现未知异常
216:恢复下载时出现IO异常
217:恢复下载时出现JSONException
218:恢复下载时出现NullPointerException
219:恢复下载时出现未知异常
220:获取下载清晰度时出现JSONException
221:下载设置的文件名为空
301:初始化上传信息失败
302:上传spark请求失败
303:上传时检查是否为续传时异常
304:检查上传时转化结果类型异常
305:检查上传时返回结果为空值
306:检查上传结果时失败
307:检查不到上传结果异常
308:上传请求异常,请检查网络连接
309:恢复上传时失败
310:恢复上传时出现未知错误
311:上传请求参数无效
312:上述时请求Spark时出现IOException
313:上传文件时出现IOException
314:上传结束当前线程时出现InterruptedException
315:上述时请求Spark时出现XmlPullParserException
316:水印文字颜色错误
317:水印文字内容错误
401:片头广告请求失败
402:片头广告Json解析失败
403:暂停广告请求失败
404:暂停广告Json解析失败
405:片头广告数据不存在
406:片头广告数据错误
407:暂停广告数据不存在
408:暂停广告数据错误
409:片尾广告请求失败
410: 片尾广告Json解析失败
411:片尾广告数据不存在
412:片尾广告数据错误
501:文件不存在
502:不是一个pcm文件
503:DRM加密版本错误
504:源文件不存在
505:加载数据失败
4.27.2 ijkplayer错误码
int MEDIA_INFO_UNKNOWN = 1;//未知信息
int MEDIA_INFO_STARTED_AS_NEXT = 2;//播放下一条
int MEDIA_INFO_VIDEO_RENDERING_START = 3;//视频开始整备中,准备渲染
int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700;//视频日志跟踪
int MEDIA_INFO_BUFFERING_START = 701;//开始缓冲中 开始缓冲
int MEDIA_INFO_BUFFERING_END = 702;//缓冲结束
int MEDIA_INFO_NETWORK_BANDWIDTH = 703;//网络带宽,网速方面
int MEDIA_INFO_NOT_SEEKABLE = 801;//不可设置播放位置,直播方面
int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901;//不支持字幕
int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902;//字幕超时
int MEDIA_INFO_VIDEO_INTERRUPT= -10000;//数据连接中断,一般是视频源有问题或者数据格式不支持,比如音频不是AAC之类的
int MEDIA_INFO_VIDEO_ROTATION_CHANGED = 10001;//视频方向改变,视频选择信息
int MEDIA_INFO_AUDIO_RENDERING_START = 10002;//音频开始整备中
int MEDIA_ERROR_SERVER_DIED = 100;//服务挂掉,视频中断,一般是视频源异常或者不支持的视频类型
int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200;//数据错误没有有效的回收
int MEDIA_ERROR_IO = -1004;//IO 错误
int MEDIA_ERROR_MALFORMED = -1007;比特流不符合相关的编码标准和文件规范
int MEDIA_ERROR_UNSUPPORTED = -1010;//数据不支持
int MEDIA_ERROR_TIMED_OUT = -110;//数据超时