【android 視頻播放那些事之緩存】


視頻緩存解決問題:

1.回看時不再重新網絡請求。

2.提前緩存,加速播放。

現有輪子:

AndroidVideoCache

git地址:

 https://github.com/danikula/AndroidVideoCache

使用很簡單參考git說明就可以。

AndroidVideoCache的用法

    1.添加依賴  compile 'com.danikula:videocache:2.7.1'
    2.在Application里面創建全局單例 HttpProxyCacheServer,代碼如下

public class App extends Application {
 
    private HttpProxyCacheServer proxy;
 
    public static HttpProxyCacheServer getProxy(Context context) {
        App app = (App) context.getApplicationContext();
        return app.proxy == null ? (app.proxy = app.newProxy()) : app.proxy;
    }
 
    private HttpProxyCacheServer newProxy() {
        return new HttpProxyCacheServer(this);
    }
}
    3.在給播放器設置url的時候通過生成代理url來實現視頻的緩存,示例代碼如下

    private void startVideo() {
        //拿到全局的單例 HttpProxyCacheServer
        HttpProxyCacheServer proxy = App.getProxy(getActivity());
        //注冊下載緩存監聽
        proxy.registerCacheListener(this, url);
        //生成代理url
        String proxyUrl = proxy.getProxyUrl(url);
        //給播放器設置播放路徑的時候設置為上一步生成的proxyUrl
        videoView.setVideoPath(proxyUrl);
        videoView.start();
    }
    以上就是AndroidVideoCache的使用,是不是特簡單!當然它還可以設置緩存的大小,緩存路徑、緩存文件的數量等,在初始化的時候設置即可,代碼如下

private HttpProxyCacheServer newProxy() {
        return new HttpProxyCacheServer.Builder(this)
                .cacheDirectory(Utils.getVideoCacheDir(this))//緩存路徑
                .maxCacheFilesCount(100)//最大緩存文件數量
                .maxCacheSize(500 * 1024 * 1024)//最大緩存大小
                .build();
    }

現實原理:

 

 參這張圖,非常清析。

由代碼去請求遠程數據。本地文件流返給videoView顯示。

 

問題解決

包沖突問題加入以下代碼

//包沖突解方法
implementation ('org.slf4j:slf4j-api:1.7.24',{
exclude group:'slf4j-api'
})

優化播放速度的思路

想要做到快速播放那必須提前緩存。方法是模擬videoView加載播放。預測哪個視頻會在將來播放就先緩存起來,當播放時視頻打開速將大幅提高。

package com.dueeeke.dkplayer.util.cache;

import com.danikula.videocache.HttpProxyCacheServer;
import com.dueeeke.videoplayer.util.L;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutorService;

public class PreloadTask implements Runnable {

    /**
     * 原始地址
     */
    public String mRawUrl;

    /**
     * 列表中的位置
     */
    public int mPosition;

    /**
     * VideoCache服務器
     */
    public HttpProxyCacheServer mCacheServer;

    /**
     * 是否被取消
     */
    private boolean mIsCanceled;

    /**
     * 是否正在預加載
     */
    private boolean mIsExecuted;

    @Override
    public void run() {
        if (!mIsCanceled) {
            start();
        }
        mIsExecuted = false;
        mIsCanceled = false;
    }

    /**
     * 開始預加載
     */
    private void start() {
        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) {
                    L.i("結束預加載:" + mPosition);
                    break;
                }
            }
            if (read == -1) { //這種情況一般是預加載出錯了,刪掉緩存
                L.i("預加載失敗:" +  mPosition);
                File cacheFile = mCacheServer.getCacheFile(mRawUrl);
                if (cacheFile.exists()) {
                    cacheFile.delete();
                }
            }
        } catch (Exception e) {
            L.i("異常結束預加載:" + mPosition);
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    /**
     * 將預加載任務提交到線程池,准備執行
     */
    public void executeOn(ExecutorService executorService) {
        if (mIsExecuted) return;
        mIsExecuted = true;
        executorService.submit(this);
    }

    /**
     * 取消預加載任務
     */
    public void cancel() {
        if (mIsExecuted) {
            mIsCanceled = true;
        }
    }
}

 

其它問題:

https://blog.csdn.net/qq_25017839/article/details/89948220?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM