lmw
2024-09-25 92778728b83ce1a34ba21bcdb061afdeca16cce5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package com.sinata.xqmuse.utils.cache;
 
import com.danikula.videocache.HttpProxyCacheServer;
import com.sinata.xqmuse.utils.Const;
import com.sinata.xqmuse.utils.event.InfoEvent;
 
import org.greenrobot.eventbus.EventBus;
 
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
 
import xyz.doikki.videoplayer.util.L;
 
/**
 * 原理:主动去请求VideoCache生成的代理地址,触发VideoCache缓存机制
 * 缓存到 PreloadManager.PRELOAD_LENGTH 的数据之后停止请求,完成预加载
 * 播放器去播放VideoCache生成的代理地址的时候,VideoCache会直接返回缓存数据,
 * 从而提升播放速度
 */
public class PreloadTask implements Runnable {
 
    /**
     * 原始地址
     */
    public String mRawUrl;
 
    /**
     * 列表中的位置
     */
    public int mPosition;
 
    /**
     * VideoCache服务器
     */
    public HttpProxyCacheServer mCacheServer;
 
    /**
     * 是否被取消
     */
    private boolean mIsCanceled;
 
    /**
     * 是否正在预加载
     */
    private boolean mIsExecuted;
 
    private final static List<String> blackList = new ArrayList<>();
 
    @Override
    public void run() {
        if (!mIsCanceled) {
            start();
        }
        mIsExecuted = false;
        mIsCanceled = false;
    }
 
    /**
     * 开始预加载
     */
    private void start() {
        // 如果在小黑屋里不加载
        if (blackList.contains(mRawUrl)){
            EventBus.getDefault().post(new InfoEvent(Const.EventCode.PRELOADED,mRawUrl));
            return;
        }
        L.i("预加载开始:" + mPosition);
        HttpURLConnection connection = null;
        try {
            //获取HttpProxyCacheServer的代理地址
            String proxyUrl = mCacheServer.getProxyUrl(mRawUrl);
            URL url = new URL(proxyUrl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(5_000);
            connection.setReadTimeout(5_000);
            InputStream in = new BufferedInputStream(connection.getInputStream());
            int length;
            int read = -1;
            byte[] bytes = new byte[8 * 1024];
            while ((length = in.read(bytes)) != -1) {
                read += length;
                //预加载完成或者取消预加载
                if (mIsCanceled || read >= PreloadManager.PRELOAD_LENGTH) {
                    if (mIsCanceled) {
                        EventBus.getDefault().post(new InfoEvent(Const.EventCode.PRELOADED,mRawUrl));
                        L.i("预加载取消:" + mPosition + " 读取数据:" + read + " Byte");
                    } else {
                        EventBus.getDefault().post(new InfoEvent(Const.EventCode.PRELOADED,mRawUrl));
                        L.i("预加载成功:" + mPosition + " 读取数据:" + read + " Byte");
                    }
                    break;
                }
            }
        } catch (Exception e) {
            L.i("预加载异常:" + mPosition + " 异常信息:"+ e.getMessage());
            EventBus.getDefault().post(new InfoEvent(Const.EventCode.PRELOADED,mRawUrl));
            // 关入小黑屋
            blackList.add(mRawUrl);
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
            L.i("预加载结束: " + mPosition);
        }
    }
 
    /**
     * 将预加载任务提交到线程池,准备执行
     */
    public void executeOn(ExecutorService executorService) {
        if (mIsExecuted) return;
        mIsExecuted = true;
        executorService.submit(this);
    }
 
    /**
     * 取消预加载任务
     */
    public void cancel() {
        if (mIsExecuted) {
            mIsCanceled = true;
        }
    }
}