Android弹幕实现:基于B站弹幕开源系统

1,885 阅读18分钟
原文链接: blog.csdn.net


Android弹幕实现:基于B站弹幕开源系统(1)

如今的视频播放,流行在视频上飘弹幕。这里面做的相对比较成熟、稳定、使用量较多的弹幕系统,当推B站的弹幕系统,B站的弹幕系统已经作为开源项目在github上,其项目地址:github.com/Bilibili/Da…
以B站开源的弹幕项目为基础,现给出一个简单的例子,实现发送简单的文本弹幕。
第一步,首先要在 android的build.gradle文件中引入B站的项目:

  1. repositories {  
  2.         jcenter()  
  3. }  
  4.   
  5.   
  6. dependencies {  
  7.   
  8.     compile 'com.github.ctiao:DanmakuFlameMaster:0.7.3'  
  9.     compile 'com.github.ctiao:ndkbitmap-armv7a:0.7.3'  
  10.   
  11. }  
repositories {
    	jcenter()
}


dependencies {

	compile 'com.github.ctiao:DanmakuFlameMaster:0.7.3'
	compile 'com.github.ctiao:ndkbitmap-armv7a:0.7.3'

}

第二步,写一个布局文件,引入B站的弹幕view:

  1. <?xml version="1.0" encoding= "utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical">  
  6.   
  7.     <Button  
  8.         android:id="@+id/show"  
  9.         android:layout_width="wrap_content"  
  10.         android:layout_height="wrap_content"  
  11.         android:text="显示弹幕" />  
  12.   
  13.     <Button  
  14.         android:id="@+id/hide"  
  15.         android:layout_width="wrap_content"  
  16.         android:layout_height="wrap_content"  
  17.         android:text="隐藏弹幕" />  
  18.   
  19.     <Button  
  20.         android:id="@+id/sendText"  
  21.         android:layout_width="wrap_content"  
  22.         android:layout_height="wrap_content"  
  23.         android:text="发送文本弹幕" />  
  24.   
  25.     <Button  
  26.         android:id="@+id/pause"  
  27.         android:layout_width="wrap_content"  
  28.         android:layout_height="wrap_content"  
  29.         android:text="暂停弹幕" />  
  30.   
  31.     <Button  
  32.         android:id="@+id/resume"  
  33.         android:layout_width="wrap_content"  
  34.         android:layout_height="wrap_content"  
  35.         android:text="重启弹幕" />  
  36.   
  37.     <master.flame.danmaku.ui.widget.DanmakuView  
  38.         android:id="@+id/danmakuView"  
  39.         android:layout_width="match_parent"  
  40.         android:layout_height="match_parent" />  
  41.   
  42. </LinearLayout>  
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/show"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="显示弹幕" />

    <Button
        android:id="@+id/hide"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="隐藏弹幕" />

    <Button
        android:id="@+id/sendText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送文本弹幕" />

    <Button
        android:id="@+id/pause"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="暂停弹幕" />

    <Button
        android:id="@+id/resume"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="重启弹幕" />

    <master.flame.danmaku.ui.widget.DanmakuView
        android:id="@+id/danmakuView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

第三步,写上层Java代码(该处java代码改造自B站弹幕github上的demo代码):

  1. package zhangphil.danmaku;  
  2.   
  3. import android.app.Activity;  
  4. import android.graphics.Color;  
  5. import android.os.Bundle;  
  6. import android.util.Log;  
  7. import android.view.View;  
  8. import android.widget.Button;  
  9.   
  10. import java.util.HashMap;  
  11.   
  12. import master.flame.danmaku.danmaku.model.BaseDanmaku;  
  13. import master.flame.danmaku.danmaku.model.DanmakuTimer;  
  14. import master.flame.danmaku.danmaku.model.IDisplayer;  
  15. import master.flame.danmaku.danmaku.model.android.DanmakuContext;  
  16. import master.flame.danmaku.ui.widget.DanmakuView;  
  17.   
  18. public class MainActivity extends Activity {  
  19.   
  20.     private DanmakuView mDanmakuView;  
  21.     private DanmakuContext mContext;  
  22.   
  23.     private AcFunDanmakuParser mParser;  
  24.   
  25.     @Override  
  26.     protected void onCreate(Bundle savedInstanceState) {  
  27.         super.onCreate(savedInstanceState);  
  28.         setContentView(R.layout.activity_main);  
  29.   
  30.         mDanmakuView = (DanmakuView) findViewById(R.id.danmakuView);  
  31.   
  32.         Button show = (Button) findViewById(R.id.show);  
  33.         Button hide = (Button) findViewById(R.id.hide);  
  34.         Button sendText = (Button) findViewById(R.id.sendText);  
  35.         Button pause = (Button) findViewById(R.id.pause);  
  36.         Button resume = (Button) findViewById(R.id.resume);  
  37.   
  38.         show.setOnClickListener(new View.OnClickListener() {  
  39.             @Override  
  40.             public void onClick(View v) {  
  41.                 mDanmakuView.show();  
  42.             }  
  43.         });  
  44.   
  45.         hide.setOnClickListener(new View.OnClickListener() {  
  46.             @Override  
  47.             public void onClick(View v) {  
  48.                 mDanmakuView.hide();  
  49.             }  
  50.         });  
  51.   
  52.         sendText.setOnClickListener(new View.OnClickListener() {  
  53.             @Override  
  54.             public void onClick(View v) {  
  55.                 //每点击一次按钮发送一条弹幕  
  56.                 sendTextMessage();  
  57.             }  
  58.         });  
  59.   
  60.         pause.setOnClickListener(new View.OnClickListener() {  
  61.             @Override  
  62.             public void onClick(View v) {  
  63.                 mDanmakuView.pause();  
  64.             }  
  65.         });  
  66.   
  67.         resume.setOnClickListener(new View.OnClickListener() {  
  68.             @Override  
  69.             public void onClick(View v) {  
  70.                 mDanmakuView.resume();  
  71.             }  
  72.         });  
  73.   
  74.   
  75.         init();  
  76.     }  
  77.   
  78.     private void init() {  
  79.         mContext = DanmakuContext.create();  
  80.   
  81.         // 设置最大显示行数  
  82.         HashMap<Integer, Integer> maxLinesPair = new HashMap<>();  
  83.         maxLinesPair.put(BaseDanmaku.TYPE_SCROLL_RL, 8); // 滚动弹幕最大显示5行  
  84.   
  85.         // 设置是否禁止重叠  
  86.         HashMap<Integer, Boolean> overlappingEnablePair = new HashMap<>();  
  87.         overlappingEnablePair.put(BaseDanmaku.TYPE_SCROLL_RL, true);  
  88.         overlappingEnablePair.put(BaseDanmaku.TYPE_FIX_TOP, true);  
  89.   
  90.         mContext.setDanmakuStyle(IDisplayer.DANMAKU_STYLE_STROKEN, 10//描边的厚度  
  91.                 .setDuplicateMergingEnabled(false)  
  92.                 .setScrollSpeedFactor(1.2f) //弹幕的速度。注意!此值越小,速度越快!值越大,速度越慢。// by phil  
  93.                 .setScaleTextSize(1.2f)  //缩放的值  
  94.                 //.setCacheStuffer(new SpannedCacheStuffer(), mCacheStufferAdapter) // 图文混排使用SpannedCacheStuffer  
  95. //        .setCacheStuffer(new BackgroundCacheStuffer())  // 绘制背景使用BackgroundCacheStuffer  
  96.                 .setMaximumLines(maxLinesPair)  
  97.                 .preventOverlapping(overlappingEnablePair);  
  98.   
  99.         mParser = new AcFunDanmakuParser();  
  100.         mDanmakuView.prepare(mParser, mContext);  
  101.   
  102.         //mDanmakuView.showFPS(true);  
  103.         mDanmakuView.enableDanmakuDrawingCache(true);  
  104.   
  105.         if (mDanmakuView != null) {  
  106.             mDanmakuView.setCallback(new master.flame.danmaku.controller.DrawHandler.Callback() {  
  107.                 @Override  
  108.                 public void updateTimer(DanmakuTimer timer) {  
  109.                 }  
  110.   
  111.                 @Override  
  112.                 public void drawingFinished() {  
  113.   
  114.                 }  
  115.   
  116.                 @Override  
  117.                 public void danmakuShown(BaseDanmaku danmaku) {  
  118.                     Log.d("弹幕文本""danmakuShown text=" + danmaku.text);  
  119.                 }  
  120.   
  121.                 @Override  
  122.                 public void prepared() {  
  123.                     mDanmakuView.start();  
  124.                 }  
  125.             });  
  126.         }  
  127.     }  
  128.   
  129.     private void sendTextMessage() {  
  130.         addDanmaku(true);  
  131.     }  
  132.   
  133.     private void addDanmaku(boolean islive) {  
  134.         BaseDanmaku danmaku = mContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);  
  135.         if (danmaku == null || mDanmakuView == null) {  
  136.             return;  
  137.         }  
  138.   
  139.         danmaku.text = "zhangphil @ csdn :" + System.currentTimeMillis();  
  140.         danmaku.padding = 5;  
  141.         danmaku.priority = 0;  // 可能会被各种过滤器过滤并隐藏显示  
  142.         danmaku.isLive = islive;  
  143.         danmaku.setTime(mDanmakuView.getCurrentTime() + 1200);  
  144.         danmaku.textSize = 20f * (mParser.getDisplayer().getDensity() - 0.6f); //文本弹幕字体大小  
  145.         danmaku.textColor = getRandomColor(); //文本的颜色  
  146.         danmaku.textShadowColor = getRandomColor(); //文本弹幕描边的颜色  
  147.         //danmaku.underlineColor = Color.DKGRAY; //文本弹幕下划线的颜色  
  148.         danmaku.borderColor = getRandomColor(); //边框的颜色  
  149.   
  150.         mDanmakuView.addDanmaku(danmaku);  
  151.     }  
  152.   
  153.     @Override  
  154.     protected void onPause() {  
  155.         super.onPause();  
  156.         if (mDanmakuView != null && mDanmakuView.isPrepared()) {  
  157.             mDanmakuView.pause();  
  158.         }  
  159.     }  
  160.   
  161.     @Override  
  162.     protected void onResume() {  
  163.         super.onResume();  
  164.         if (mDanmakuView != null && mDanmakuView.isPrepared() && mDanmakuView.isPaused()) {  
  165.             mDanmakuView.resume();  
  166.         }  
  167.     }  
  168.   
  169.     @Override  
  170.     protected void onDestroy() {  
  171.         super.onDestroy();  
  172.         if (mDanmakuView != null) {  
  173.             // dont forget release!  
  174.             mDanmakuView.release();  
  175.             mDanmakuView = null;  
  176.         }  
  177.     }  
  178.   
  179.     /** 
  180.      * 从一系列颜色中随机选择一种颜色 
  181.      * 
  182.      * @return 
  183.      */  
  184.     private int getRandomColor() {  
  185.         int[] colors = {Color.RED, Color.YELLOW, Color.BLUE, Color.GREEN, Color.CYAN, Color.BLACK, Color.DKGRAY};  
  186.         int i = ((int) (Math.random() * 10)) % colors.length;  
  187.         return colors[i];  
  188.     }  
  189. }  
package zhangphil.danmaku;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import java.util.HashMap;

import master.flame.danmaku.danmaku.model.BaseDanmaku;
import master.flame.danmaku.danmaku.model.DanmakuTimer;
import master.flame.danmaku.danmaku.model.IDisplayer;
import master.flame.danmaku.danmaku.model.android.DanmakuContext;
import master.flame.danmaku.ui.widget.DanmakuView;

public class MainActivity extends Activity {

    private DanmakuView mDanmakuView;
    private DanmakuContext mContext;

    private AcFunDanmakuParser mParser;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mDanmakuView = (DanmakuView) findViewById(R.id.danmakuView);

        Button show = (Button) findViewById(R.id.show);
        Button hide = (Button) findViewById(R.id.hide);
        Button sendText = (Button) findViewById(R.id.sendText);
        Button pause = (Button) findViewById(R.id.pause);
        Button resume = (Button) findViewById(R.id.resume);

        show.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDanmakuView.show();
            }
        });

        hide.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDanmakuView.hide();
            }
        });

        sendText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //每点击一次按钮发送一条弹幕
                sendTextMessage();
            }
        });

        pause.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDanmakuView.pause();
            }
        });

        resume.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDanmakuView.resume();
            }
        });


        init();
    }

    private void init() {
        mContext = DanmakuContext.create();

        // 设置最大显示行数
        HashMap<Integer, Integer> maxLinesPair = new HashMap<>();
        maxLinesPair.put(BaseDanmaku.TYPE_SCROLL_RL, 8); // 滚动弹幕最大显示5行

        // 设置是否禁止重叠
        HashMap<Integer, Boolean> overlappingEnablePair = new HashMap<>();
        overlappingEnablePair.put(BaseDanmaku.TYPE_SCROLL_RL, true);
        overlappingEnablePair.put(BaseDanmaku.TYPE_FIX_TOP, true);

        mContext.setDanmakuStyle(IDisplayer.DANMAKU_STYLE_STROKEN, 10) //描边的厚度
                .setDuplicateMergingEnabled(false)
                .setScrollSpeedFactor(1.2f) //弹幕的速度。注意!此值越小,速度越快!值越大,速度越慢。// by phil
                .setScaleTextSize(1.2f)  //缩放的值
                //.setCacheStuffer(new SpannedCacheStuffer(), mCacheStufferAdapter) // 图文混排使用SpannedCacheStuffer
//        .setCacheStuffer(new BackgroundCacheStuffer())  // 绘制背景使用BackgroundCacheStuffer
                .setMaximumLines(maxLinesPair)
                .preventOverlapping(overlappingEnablePair);

        mParser = new AcFunDanmakuParser();
        mDanmakuView.prepare(mParser, mContext);

        //mDanmakuView.showFPS(true);
        mDanmakuView.enableDanmakuDrawingCache(true);

        if (mDanmakuView != null) {
            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) {
                    Log.d("弹幕文本", "danmakuShown text=" + danmaku.text);
                }

                @Override
                public void prepared() {
                    mDanmakuView.start();
                }
            });
        }
    }

    private void sendTextMessage() {
        addDanmaku(true);
    }

    private void addDanmaku(boolean islive) {
        BaseDanmaku danmaku = mContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);
        if (danmaku == null || mDanmakuView == null) {
            return;
        }

        danmaku.text = "zhangphil @ csdn :" + System.currentTimeMillis();
        danmaku.padding = 5;
        danmaku.priority = 0;  // 可能会被各种过滤器过滤并隐藏显示
        danmaku.isLive = islive;
        danmaku.setTime(mDanmakuView.getCurrentTime() + 1200);
        danmaku.textSize = 20f * (mParser.getDisplayer().getDensity() - 0.6f); //文本弹幕字体大小
        danmaku.textColor = getRandomColor(); //文本的颜色
        danmaku.textShadowColor = getRandomColor(); //文本弹幕描边的颜色
        //danmaku.underlineColor = Color.DKGRAY; //文本弹幕下划线的颜色
        danmaku.borderColor = getRandomColor(); //边框的颜色

        mDanmakuView.addDanmaku(danmaku);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mDanmakuView != null && mDanmakuView.isPrepared()) {
            mDanmakuView.pause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mDanmakuView != null && mDanmakuView.isPrepared() && mDanmakuView.isPaused()) {
            mDanmakuView.resume();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mDanmakuView != null) {
            // dont forget release!
            mDanmakuView.release();
            mDanmakuView = null;
        }
    }

    /**
     * 从一系列颜色中随机选择一种颜色
     *
     * @return
     */
    private int getRandomColor() {
        int[] colors = {Color.RED, Color.YELLOW, Color.BLUE, Color.GREEN, Color.CYAN, Color.BLACK, Color.DKGRAY};
        int i = ((int) (Math.random() * 10)) % colors.length;
        return colors[i];
    }
}

代码运行结果如图:

需要特别注意的是本例使用了一个叫做AcFunDanmakuParser的弹幕parser,这个解析器得自己写,自己基于json数据格式实现。该类写好基本就可以拿来稳定使用,现给出AcFunDanmakuParser的全部源代码:

  1. package zhangphil.danmaku;  
  2.   
  3. import org.json.JSONArray;  
  4. import org.json.JSONException;  
  5. import org.json.JSONObject;  
  6.   
  7. import master.flame.danmaku.danmaku.model.BaseDanmaku;  
  8. import master.flame.danmaku.danmaku.model.android.Danmakus;  
  9. import master.flame.danmaku.danmaku.parser.BaseDanmakuParser;  
  10. import master.flame.danmaku.danmaku.parser.android.JSONSource;  
  11. import master.flame.danmaku.danmaku.util.DanmakuUtils;  
  12.   
  13. /** 
  14.  * Created by phil on 2017/3/29. 
  15.  */  
  16.   
  17. public class AcFunDanmakuParser extends BaseDanmakuParser {  
  18.   
  19.     public AcFunDanmakuParser() {  
  20.   
  21.     }  
  22.   
  23.     public Danmakus parse() {  
  24.         if (this.mDataSource != null &&  this.mDataSource instanceof JSONSource) {  
  25.             JSONSource jsonSource = (JSONSource) this.mDataSource;  
  26.             return this.doParse(jsonSource.data());  
  27.         } else {  
  28.             return new Danmakus();  
  29.         }  
  30.     }  
  31.   
  32.     private Danmakus doParse(JSONArray danmakuListData) {  
  33.         Danmakus danmakus = new Danmakus();  
  34.         if (danmakuListData != null && danmakuListData.length() !=  0) {  
  35.             for (int i = 0; i < danmakuListData.length(); ++i) {  
  36.                 try {  
  37.                     JSONObject e = danmakuListData.getJSONObject(i);  
  38.                     if (e != null) {  
  39.                         danmakus = this._parse(e, danmakus);  
  40.                     }  
  41.                 } catch (JSONException var5) {  
  42.                     var5.printStackTrace();  
  43.                 }  
  44.             }  
  45.   
  46.             return danmakus;  
  47.         } else {  
  48.             return danmakus;  
  49.         }  
  50.     }  
  51.   
  52.     private Danmakus _parse(JSONObject jsonObject, Danmakus danmakus) {  
  53.         if (danmakus == null) {  
  54.             danmakus = new Danmakus();  
  55.         }  
  56.   
  57.         if (jsonObject != null && jsonObject.length() !=  0) {  
  58.             for (int i = 0; i < jsonObject.length(); ++i) {  
  59.                 try {  
  60.                     String c = jsonObject.getString("c");  
  61.                     String[] values = c.split(",");  
  62.                     if (values.length > 0) {  
  63.                         int type = Integer.parseInt(values[ 2]);  
  64.                         if (type !=  7) {  
  65.                             long time = ( long) (Float.parseFloat(values[0]) * 1000.0F);  
  66.                             int color = Integer.parseInt(values[ 1]) | -16777216;  
  67.                             float textSize = Float.parseFloat(values[ 3]);  
  68.                             BaseDanmaku item = this.mContext.mDanmakuFactory.createDanmaku(type,  this.mContext);  
  69.                             if (item !=  null) {  
  70.                                 item.setTime(time);  
  71.                                 item.textSize = textSize * (this.mDispDensity -  0.6F);  
  72.                                 item.textColor = color;  
  73.                                 item.textShadowColor = color <= -16777216 ? - 1 : -16777216;  
  74.                                 DanmakuUtils.fillText(item, jsonObject.optString("m" "...."));  
  75.                                 item.index = i;  
  76.                                 item.setTimer(this.mTimer);  
  77.                                 danmakus.addItem(item);  
  78.                             }  
  79.                         }  
  80.                     }  
  81.                 } catch (JSONException var13) {  
  82.   
  83.                 } catch (NumberFormatException var14) {  
  84.   
  85.                 }  
  86.             }  
  87.   
  88.             return danmakus;  
  89.         } else {  
  90.             return danmakus;  
  91.         }  
  92.     }  
  93. }  
package zhangphil.danmaku;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import master.flame.danmaku.danmaku.model.BaseDanmaku;
import master.flame.danmaku.danmaku.model.android.Danmakus;
import master.flame.danmaku.danmaku.parser.BaseDanmakuParser;
import master.flame.danmaku.danmaku.parser.android.JSONSource;
import master.flame.danmaku.danmaku.util.DanmakuUtils;

/**
 * Created by phil on 2017/3/29.
 */

public class AcFunDanmakuParser extends BaseDanmakuParser {

    public AcFunDanmakuParser() {

    }

    public Danmakus parse() {
        if (this.mDataSource != null && this.mDataSource instanceof JSONSource) {
            JSONSource jsonSource = (JSONSource) this.mDataSource;
            return this.doParse(jsonSource.data());
        } else {
            return new Danmakus();
        }
    }

    private Danmakus doParse(JSONArray danmakuListData) {
        Danmakus danmakus = new Danmakus();
        if (danmakuListData != null && danmakuListData.length() != 0) {
            for (int i = 0; i < danmakuListData.length(); ++i) {
                try {
                    JSONObject e = danmakuListData.getJSONObject(i);
                    if (e != null) {
                        danmakus = this._parse(e, danmakus);
                    }
                } catch (JSONException var5) {
                    var5.printStackTrace();
                }
            }

            return danmakus;
        } else {
            return danmakus;
        }
    }

    private Danmakus _parse(JSONObject jsonObject, Danmakus danmakus) {
        if (danmakus == null) {
            danmakus = new Danmakus();
        }

        if (jsonObject != null && jsonObject.length() != 0) {
            for (int i = 0; i < jsonObject.length(); ++i) {
                try {
                    String c = jsonObject.getString("c");
                    String[] values = c.split(",");
                    if (values.length > 0) {
                        int type = Integer.parseInt(values[2]);
                        if (type != 7) {
                            long time = (long) (Float.parseFloat(values[0]) * 1000.0F);
                            int color = Integer.parseInt(values[1]) | -16777216;
                            float textSize = Float.parseFloat(values[3]);
                            BaseDanmaku item = this.mContext.mDanmakuFactory.createDanmaku(type, this.mContext);
                            if (item != null) {
                                item.setTime(time);
                                item.textSize = textSize * (this.mDispDensity - 0.6F);
                                item.textColor = color;
                                item.textShadowColor = color <= -16777216 ? -1 : -16777216;
                                DanmakuUtils.fillText(item, jsonObject.optString("m", "...."));
                                item.index = i;
                                item.setTimer(this.mTimer);
                                danmakus.addItem(item);
                            }
                        }
                    }
                } catch (JSONException var13) {

                } catch (NumberFormatException var14) {

                }
            }

            return danmakus;
        } else {
            return danmakus;
        }
    }
}