視頻緩存解決問題:
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; } } }
其它問題: