zoukankan      html  css  js  c++  java
  • 【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

  • 相关阅读:
    Linux安装nginx
    linux目录结构
    Django-admin
    celery
    Flask-Migrate
    Flask-Script
    Flask-SQLAlchemy
    SQLAlchemy
    mongodb的增删改查
    websocket的加密和解密过程
  • 原文地址:https://www.cnblogs.com/mamamia/p/12357709.html
Copyright © 2011-2022 走看看