bilibili DanmakuFlameMaster在播放器上的使用

使用b站的弹幕:
1 弹幕的配置和获取弹幕的布局view:
private IDanmakuView mDanmakuView ; // 弹幕控件
private DanmakuContext mContext ; // 弹幕上下文
private BaseDanmakuParser mParser ; // 数据对象


//弹幕之前的配置
// 设置最大显示行数
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 );

mDanmakuView = ( IDanmakuView ) findViewById ( R . id . vod_danmaku );//获取弹幕的view
mContext = DanmakuContext . create ();//创建弹幕上下文
mContext . setDanmakuStyle ( IDisplayer . DANMAKU_STYLE_STROKEN , 3 )
// 描边样式
// 是否合并重复弹幕setDuplicateMergingEnabled
. setDuplicateMergingEnabled ( false )
. setScrollSpeedFactor ( 1.2f )
// .setCacheStuffer(new SpannedCacheStuffer(),
// mCacheStufferAdapter)
// //.setCacheStuffer(new BackgroundCacheStuffer()) //
// 绘制背景使用BackgroundCacheStuffer

. setMaximumVisibleSizeInScreen ( 40 )
// 同屏最大显示数量(弹幕密度(只对滚动有效))
. setScaleTextSize ( 1.2f ). setMaximumLines ( maxLinesPair )
. preventOverlapping ( overlappingEnablePair )
. setScrollSpeedFactor ( 1.0f ); // 设置弹幕滚动速度系数,只对滚动弹幕有效



mDanmakuView//mDanmakuView表示的是布局中弹幕view
. setCallback ( new master . flame . danmaku . controller . DrawHandler . Callback () {
@Override
public void updateTimer ( DanmakuTimer timer ) {
// lzw 这里是更新时间后的回调
}

@Override
public void drawingFinished () {

}

@Override
public void danmakuShown ( BaseDanmaku danmaku ) {
Log . d ( "danmaku" , "danmakuShown(): text="
+ danmaku . text );
}

@Override
public void prepared () {
//因为要是点播弹幕,当播放器有历史记录,的时候,希望弹幕与播放时间同步,就在这里//操作
// 在这里是用这个,因为初始化的时候,start不起作用
// 坑,要是刚进去的时候,马上seek,不起作用,因此发现这里有个回调,在这里进行处理,补坑,这个是handler里面的回调
setStartDanmukuTime ( mVodDTO . getSeekPos ());//根据播放器的进度设置弹幕开始的//时候的进度
Log . d ( "lu" , "danmaku start callback "
+ mVodDTO . getSeekPos ());
} else {
mDanmakuView . start ();
}
}
});

private void setStartDanmukuTime ( long ms ) { // lzw
// 设置开始时间弹幕时间,在弹幕准备好了之后,不能用这个,应该用seek,这个要
//要是刚刚准备开始的时候,应该用这个设置时间
if ( ms > 0 ) {
mDanmakuView . start ( ms );
} else {
mDanmakuView . start ();
}
Log . d ( "lu" , "danmaku start time " + mDanmakuView . getCurrentTime ()
+ " ms " + ms );
}

private void seekToDanmuKuTime ( long ms ) { // lzw seek 弹幕时间 就是移动到什么时候,
//要是//启///动之后的弹幕,用这个
mDanmakuView . seekTo ( ms );
Log . d ( "lu" , "danmaku seek time " + mDanmakuView . getCurrentTime ()
+ " ms " + ms );
}
2弹幕的启动:
// 启动弹幕
private void startDanmaku ( String jsonArr ) { // lzw
// 这个是对弹幕的初始化,并且启动,具体实现,看弹幕里的Handler

// mParser = createParser(this.getResources().openRawResource(
// R.raw.comments));//这里是加载自己文件中的xml
mParser = createParser ( jsonArr );//解析 json,或者是xml

mDanmakuView . release (); // 先释放之前的资源,和还原时间
mDanmakuView . prepare ( mParser , mContext );
// lzw 显示,弹幕的时间,内存之类的,测试的时候用,true 为显示
// mDanmakuView.showFPS(true);// 画面的帧数值,帧数值越高, 画面会越流畅,
mDanmakuView . enableDanmakuDrawingCache ( true );
Log . d ( "lu" , "danmaku start" );
// lzw 设置弹幕开始时间,播放点播的时候,可能会有历史记录,注意,这里要用seek, 但是刚进去的时候,进度条是为0,
// 因此加个mVodDTO
// if (mFooterSeekBar != null) {
// seekToDanmuKuTime(mFooterSeekBar.getProgress());
// Log.d("lu", "danmaku seek "+mFooterSeekBar.getProgress());
// }
// if (mVodDTO != null && mVodDTO.getSeekPos() != 0) {//lzw
// 在这里是用这个,因为初始化的时候,进度条是为0的
// //lzw 坑,要是刚进去的时候,马上seek,不起作用
// seekToDanmuKuTime(mVodDTO.getSeekPos());
// Log.d("lu", "danmaku seek "+ mVodDTO.getSeekPos());
// }
}
3弹幕的加载数据:
/ 加载json串,就是把从服务器上获取的json加进去
private BaseDanmakuParser createParser ( String jsonArr ) {

if ( jsonArr == null ) {
return new BaseDanmakuParser () {

@Override
protected Danmakus parse () {
return new Danmakus ();
}
};
}

try {
BaseDanmakuParser parser = new AcFunDanmakuParser ();//加载的是json
JSONSource jsonSource = new JSONSource ( jsonArr );
IDataSource<?> dataSource = jsonSource ;
parser . load ( dataSource );

return parser ;
} catch ( JSONException e ) {
e . printStackTrace ();
}

return null ;

}

// 测试用的,加载自己的文件里的xml,这个也可以自己改成加载服务器上的xml
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 );//加载的xml

try {
loader . load ( stream );
} catch ( IllegalDataException e ) {
e . printStackTrace ();
}
BaseDanmakuParser parser = new BiliDanmukuParser ();
IDataSource<?> dataSource = loader . getDataSource ();
parser . load ( dataSource );
return parser ;

}
4弹幕的解析格式:
有两种解析方式。 一种是xml,一种是json
ILoader loader = DanmakuLoaderFactory.create(DanmakuLoaderFactory.TAG_BILI);//这个是xml的方式

DanmakuLoaderFactory.TAG_ACFUN//这个是josn

在调用的时候,会有个判断,是加载json还是xmL,(这个可以看源码)
if (TAG_BILI.equalsIgnoreCase(tag)) {
            return BiliDanmakuLoader.instance();
        } else if(TAG_ACFUN.equalsIgnoreCase(tag))
            return AcFunDanmakuLoader.instance();}

 BiliDanmakuLoader//这个是对xml进行解析

AcFunDanmakuLoader//这个是对json进行解析
如果是直接跟b站的内容格式是一样的话,就可以直接传入下载的地址,里面有对http,https,file的下载处理, 如果要是有自己的格式话。
那么就自己转成b站一样的格式,


内容格式xml:
// <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


json格式: 记住传入的json最开始的时候一定应该是个数组

 JSONObject obj = jsonObject;
                Log.d("lu","弹幕json"+"\n"+obj.toString());
                String c = obj.getString("c");
                String[] values = c.split(",");
                if (values.length > 0) {
                    int type = Integer.parseInt(values[2]); // 弹幕类型
                    if (type == 7)
                        // FIXME : hard code
                        // TODO : parse advance danmaku json
                        continue;
                    long time = (long) (Float.parseFloat(values[0]) * 1000); // 出现时间
                    int color = Integer.parseInt(values[1]) | 0xFF000000; // 颜色
                    float textSize = Float.parseFloat(values[3]); // 字体大小
                    BaseDanmaku item = mContext.mDanmakuFactory.createDanmaku(type, mContext);
                    if (item != null) {
                        item.time = time;
                        item.textSize = textSize * (mDispDensity - 0.6f);
                        item.textColor = color;
                        item.textShadowColor = color <= Color.BLACK ? Color.WHITE : Color.BLACK;
                        DanmakuUtils.fillText(item, obj.optString("m", "...."));
                        item.index = i;
                        item.setTimer(mTimer);
                        danmakus.addItem(item);
                    }
                }

弹幕json格式:
[{"c":"0,16777215,1,25,196050,1364468342","m":"。。。。。。。。。。。。。。。。。。。。。。"}]

表达的意思:
{"c": "播放时间,颜色,模式,字号,uid,发送时间", "m": "弹幕内容"}  
这里介绍下c里面各自参数:
1、播放时间单位是秒 如1.234
2、颜色是十进制
3、模式在BaseDanmaku里有声明,总结一下就是
1:滚动弹幕
4:底端弹幕
5:顶端弹幕



5 弹幕的添加:
从输入框输入文字,添加一个弹幕
danmaku . text = strText ; // 文字
danmaku . padding = 5 ; // 内距离
danmaku . priority = 0 ; // 可能会被各种过滤器过滤并隐藏显示
danmaku . time = mDanmakuView . getCurrentTime () + 5 ; // 时间,取当前弹幕时间,加上五毫秒
danmaku . textSize = 16f * ( mParser . getDisplayer (). getDensity () - 0.6f ); // 大小
danmaku . textColor = Color . WHITE ; // 字体颜色
danmaku . textShadowColor = Color . WHITE ; // 字体描边的颜色
// danmaku.underlineColor = Color.GREEN;//下滑线
danmaku . borderColor = Color . GREEN ; // 边框线
// danmaku.isLive;// 是否是直播
mDanmakuView . addDanmaku ( danmaku )

6弹幕的生命周期:
mDanmakuView . pause ();//弹幕暂停,加在activity的生命周期里和播放器的生命周期方法里
mDanmakuView . resume ();//弹幕复苏,加在activity的生命周期和播放器的生命周期方法里
mDanmakuView . release ();//弹幕释放
if ( mFooterSeekBar != null ) {
seekToDanmuKuTime ( mFooterSeekBar . getProgress ()); //mFooterSeekBar是播放器的进度条(相对于点播,要是直播就没有必要矫正)
// 每次复苏的时候,我都对时间进行一次矫正,但是有时候得注意进度条返回的时间是否是一致的
Log . d ( "lu" , "danmaku resume " + mFooterSeekBar . getProgress ());
}

7弹幕是否显示:
// lzw 是否显示弹幕
private void isShowDanmaku ( boolean show ) {
if ( show ) {
mDanmakuView . show ();

Log . d ( "lu" , "danmaku show" );
} else {

mDanmakuView . hide ();
Log . d ( "lu" , "danmaku hide" );
}
}
}

8可以设置一个定时器,定时发送
class AsyncAddTask extends TimerTask { // 定时发送的时候用

@Override
public void run () {
for ( int i = 0 ; i < 20 ; i++ ) {

SystemClock . sleep ( 20 );
}
}
}
总结:以上是在点播(视频)的使用,要是直播,其实原理也是差不多,就是建立一个WebSocket,时时更新数据,并且添加到弹幕里.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值