【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

原文地址:https://www.cnblogs.com/mamamia/p/12357709.html