Android 边播边缓存的实现(MP4 未加密m3u8)

实现思路

红色框的 ProxyServer就是需要实现的一个代理服务器。 当客户端拿到一个视频的url(mp4或者m3u8)时,通过proxyServer转化为一个代理的url,然后请求代理服务器;代理服务器接收到客户端的请求后,先查看本地是否存在缓存,如果不存在则向真实服务器发送请求,拿到结果后再存到本地。

实现重点

缓存是一个代理服务器的主要部分,所以这部分是一个重点。本设计的缓存是一个分片的LRU缓存。分片的好处是灵活方便做LRU。当真实服务器返回一个大文件时,我们在进行切割后缓存在本地,并返回给客户端,不用等待所有数据返回后再返回给客户端。

使用方式

在app初始化的时候 创建代理服务器

public class APP extends Application {
  private static VideoCacheServer videoCacheServer;

  @Override
  public void onCreate() {
    super.onCreate();

    if (videoCacheServer == null) {
      // 缓存路径
      String cachePath = getCacheDir().getAbsolutePath();
      // 缓存大小 1024 * 1024 * 500
      videoCacheServer = new VideoCacheServer(cachePath, 1024 * 1024 * 500);
    }
  }

  public static VideoCacheServer getVideoProxyServer() {
    return videoCacheServer;
  }

}

代理服务建立好了 ,使用的时候只需要将真实url转换为代理url就好了

String proxyUrl = APP.getVideoProxyServer().getLocalProxyUrl("https://sina.com-h-sina.com/20181024/21342_8f737b71/1000k/hls/index.m3u8");
 videoView.setVideoPath(proxyUrl);

转换的规则即讲https的请求转换为http的请求 ,并且替换域名为代理服务器的地址,将真实服务器的地址作为参数添加到代理url的后面。
例如 sina.com-h-sina.com/20181024/21… 地址转换后变成了 https://127.0.0.1:3260/20181024/21342_8f737b71/1000k/hls/index.m3u8?RealHostParam=sina.com-h-sina.com  3260是VideoCacheServer监听的端口

实现细节

代理服务器的建立

public class VideoCacheServer{

 private ExecutorService pool = Executors.newFixedThreadPool(20);

 public int start() {
    if (isRunning) {
      return curPort;
    }
    curPort = new Random().nextInt(65535);
    try {
      final ServerSocket server = new ServerSocket(curPort);
      isRunning = true;
      singleService.submit(new Runnable() {
        @Override
        public void run() {
          while (isRunning) {
            try {
              Socket connection = server.accept();
              connection.setKeepAlive(true);
              pool.submit(new ProxyHandler(connection));
            } catch (IOException ex) {
              if (Constant.enableLog) {
                logger.log(Level.WARNING, "Exception accepting connection", ex);
              }
            } catch (Exception ex) {
              if (Constant.enableLog) {
                logger.log(Level.SEVERE, "Unexpected error", ex);
              }
            }
          }
        }
      });
      return curPort;
    } catch (IOException e) {
      e.printStackTrace();
      return start();
    }
  }
}

通过socket实现端口的监听,当请求到来时,使用ProxyHandler来处理。

 public class ProxyHandler implements Runnable {

    private Socket realClientSocket;

    ProxyHandler(Socket realClientSocket) {
      this.realClientSocket = realClientSocket;
    }

    @Override
    public void run() {
      try {
        BufferedOutputStream outputStream = new BufferedOutputStream(realClientSocket.getOutputStream());
        BufferedInputStream inputStream = new BufferedInputStream(realClientSocket.getInputStream());
        HttpRequest realRequest = HttpRequest.parse(inputStream);
        HttpResponse response = getResponseWithInterceptorChain(realRequest);
        writeResponseAndClose(response, outputStream);

      } catch (Exception e) {
        if (Constant.enableLog) {
          logger.log(Level.SEVERE, "error proxy ", e);
        }
      } finally {
        CloseUtil.close(realClientSocket);
      }
    }

    private HttpResponse getResponseWithInterceptorChain(HttpRequest realRequest) {
      List<Interceptor> interceptors = new ArrayList<>();
      interceptors.add(new VideoTypeInterceptor());
      interceptors.add(new HostFilterInterceptor(curPort));
      interceptors.add(new CacheInterceptor(diskCache));
      interceptors.add(new ConnectInterceptor());
      InterceptorChain interceptorChain = new InterceptorChain(interceptors, realRequest, 0);
      return interceptorChain.proceed(realRequest);
    }
}

ProxyHandler中使用拦截器的模式,将请求分部处理

VideoTypeInterceptor 将代理的url 还原为真实的url
CacheInterceptor 用于缓存
ConnectInterceptor 建立代理服务器与真实服务器的连接
VideoTypeInterceptor 主要是针对m3u8类型,因为m3u8会先返回一个m3u8的文件,文件里面记录了每个ts的地址,VideoTypeInterceptor就是将返回的文件中的ts地址转换为代理服务器的地址

项目地址 https://github.com/ZhangHao555/VideoCacheServerDemo

到此这篇关于Android 边播边缓存的实现(MP4 未加密m3u8)的文章就介绍到这了,更多相关Android 边播边缓存内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android 获取应用缓存大小与清除缓存的方法

    如下所示: package com.lucasey.littleant.frame; /** * 文 件 名: FileCacheUtils.java * 描 述: 主要功能有清除内/外缓存,清除数据库,清除sharedPreference,清除files和清除自定义目录 * */ import java.io.File; import java.math.BigDecimal; import android.content.Context; import android.os.Environm

  • Android缓存之DiskLruCache磁盘缓存的使用

    DiskLruCache和LruCache不同的是,LruCache是内存缓存,而DiskLruCache是指磁盘缓存,顾名思义就是把文件缓存到磁盘,也也就是手机的内存卡中.接下来先简单介绍DiskLruCache的使用方法. 下载源码 DiskLruCache并没有在 SDK中存在,但又是谷歌提倡的.所以我们要先把DiskLruCache的源码下载下来. 我们可以通过下面这个地址下载源码:https://github.com/JakeWharton/DiskLruCache/tree/mast

  • android实现清理缓存功能

    android之清理缓存实现,供大家参考,具体内容如下 一. 清理缓存首先要搞清楚清理哪些东西 1.app本身的功能比如录像,录音,更新都会产生文件,需要清理 2.app的默认缓存地址cache 二. 搞清楚要清理的文件夹位置 1.首先app自身的功能就要看自己把它放在了什么位置 2.默认缓存地址:getActivity().getExternalCacheDir(); 这个位置是在storage/emulated/0/Android/data/com.xxxxxapp/cache 三.代码功能

  • Android缓存机制——LruCache的详解

    概述 LruCache的核心原理就是对LinkedHashMap的有效利用,它的内部存在一个LinkedHashMap成员变量,值得注意的4个方法:构造方法.get.put.trimToSize LRU(Least Recently Used)缓存算法便应运而生,LRU是最近最少使用的算法,它的核心思想是当缓存满时,会优先淘汰那些最近最少使用的缓存对象.采用LRU算法的缓存有两种:LrhCache和DisLruCache,分别用于实现内存缓存和硬盘缓存,其核心思想都是LRU缓存算法. LRU原理

  • 关于Android的 DiskLruCache磁盘缓存机制原理

    目录 一.为什么用DiskLruCache 1.LruCache和DiskLruCache 2.为何使用DiskLruCache 二.DiskLruCache使用 1.添加依赖 2.创建DiskLruCache对象 3.添加 / 获取 缓存(一对一) 4.添加 / 获取 缓存(一对多) 三.源码分析 1.open() 2.rebuildJournal() 3.readJournal() 4.get() 5.validateKey 6.trimTOSize() 7.journalRebuildRe

  • 浅谈Android LruCache的缓存策略

    一.Android中的缓存策略 一般来说,缓存策略主要包含缓存的添加.获取和删除这三类操作.如何添加和获取缓存这个比较好理解,那么为什么还要删除缓存呢?这是因为不管是内存缓存还是硬盘缓存,它们的缓存大小都是有限的.当缓存满了之后,再想其添加缓存,这个时候就需要删除一些旧的缓存并添加新的缓存. 因此LRU(Least Recently Used)缓存算法便应运而生,LRU是近期最少使用的算法,它的核心思想是当缓存满时,会优先淘汰那些近期最少使用的缓存对象.采用LRU算法的缓存有两种:LrhCach

  • Android实现清除应用缓存功能

    本文实例为大家分享了Android清除应用缓存的具体代码,供大家参考,具体内容如下 import android.content.Context; import android.os.Environment; import java.io.File; import java.math.BigDecimal; /** * 获取缓存大小并清理缓存 */ public class DataCleanManagerUtils { /** * Context.getExternalFilesDir() -

  • Android Studio缓存文件夹配置教程

    安装完,或者绿色版解压完,先别打开Android Stduio.要先配置下Android Studio 的缓存路径. 这个缓存文件主要是存放一些AndroidStudio设置和插件和项目的缓存信息的. 我用的是AS的老版本,缓存文件夹如图.默认是放在C盘系统盘里面的,这里是没改直接打开的,实际上安装完应该先别打开修改完再打开! 打开会看到 为什么Android Stduio启动速度比Eclipse快,也是托这个缓存文件夹的关系.但缺点是第一次建立缓存会比较慢. 为什么要配置这个文件呢? 因为这个

  • Android 边播边缓存的实现(MP4 未加密m3u8)

    实现思路 红色框的 ProxyServer就是需要实现的一个代理服务器. 当客户端拿到一个视频的url(mp4或者m3u8)时,通过proxyServer转化为一个代理的url,然后请求代理服务器:代理服务器接收到客户端的请求后,先查看本地是否存在缓存,如果不存在则向真实服务器发送请求,拿到结果后再存到本地. 实现重点 缓存是一个代理服务器的主要部分,所以这部分是一个重点.本设计的缓存是一个分片的LRU缓存.分片的好处是灵活方便做LRU.当真实服务器返回一个大文件时,我们在进行切割后缓存在本地,

  • Android视频点播的实现代码(边播边缓存)

    简述 一些知名的视频app客户端(优酷,爱奇艺)播放视频的时候都有一些缓存进度(二级进度缓存),还有一些短视频app,都有边播边缓的处理.还有就是当文件缓存完毕了再次播放的话就不再请求网络了直接播放本地文件了.既节省了流程又提高了加载速度. 今天我们就是来研究讨论实现这个边播边缓存的框架,因为它不和任何的业务逻辑耦合. 开源的项目 目前比较好的开源项目是:https://github.com/danikula/AndroidVideoCache 代码的架构写的也很不错,网络用的httpurlco

  • Android实现WebView删除缓存的方法

    本文实例讲述了Android实现WebView删除缓存的方法.分享给大家供大家参考.具体如下: 删除保存于手机上的缓存: // clear the cache before time numDays private int clearCacheFolder(File dir, long numDays) { int deletedFiles = 0; if (dir!= null && dir.isDirectory()) { try { for (File child:dir.listF

  • Android 图片的三级缓存机制实例分析

    Android 图片的三级缓存机制实例分析 当我们获取图片的时候,如果不加以协调好图片的缓存,就会造成大流量,费流量应用,用户体验不好,影响后期发展.为此,我特地分享Android图片的三级缓存机制之从网络中获取图片,来优化应用,具体分三步进行: (1)从缓存中获取图片 (2)从本地的缓存目录中获取图片,并且获取到之后,放到缓存中 (3)从网络去下载图片,下载完成之后,保存到本地和放到缓存中 很好的协调这三层图片缓存就可以大幅度提升应用的性能和用户体验. 快速实现三级缓存的工具类ImageCac

  • Android开发之删除项目缓存的方法

    本文实例讲述了Android开发之删除项目缓存的方法.分享给大家供大家参考,具体如下: 如何删除项目的缓存: getCacheDir()能够得到当前项目的缓存地址 在项目中经常会使用到WebView 控件,当加载html 页面时,会在/data/data/应用package 目录下生成database与cache 两个文件夹.请求的url 记录是保存在WebViewCache.db,而url 的内容是保存在WebViewCache 文件夹下 打开关闭使用缓存,一共有五个种类 //优先使用缓存:

  • Android使用HBuilder的缓存方法

    代码如下所述: /* * 中间就可以进行封装操作 * mui就代表mui,owner就代表window的app属性,就是一个传值 */ (function(mui,owner) { /** * 获取当前状态 **/ owner.getState = function() { var stateText = plus.storage.getItem('$state'); if(stateText != null && stateText != undefined) { var s = JSO

  • Android 8.0的缓存大小和缓存清理接口方法

    获取缓存大小接口 主要这里的方法已经和7.0不兼容了. import android.app.usage.UsageStats; import android.app.usage.UsageStatsManager; import android.content.Context; import android.content.pm.PackageManager; import android.os.Process; import android.os.storage.StorageManager

  • android轮播图组件的制作方法

    本文实例为大家分享了android轮播图组件的制作方法,供大家参考,具体内容如下 BannerLayout package com.coral3.common_module.components; import android.content.Context; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.view.LayoutInfla

  • Android边播放边缓存视频框架AndroidVideoCache详解

    目录 一.背景 二.PlayerBase 三.AndroidVideoCache 3.1 基本原理 3.2 基本使用 3.3 源码分析 一.背景 现在的移动应用,视频是一个非常重要的组成部分,好像里面不搞一点视频就不是一个正常的移动App.在视频开发方面,可以分为视频录制和视频播放,视频录制的场景可能还比较少,这方面可以使用Google开源的 grafika.相比于视频录制,视频播放可以选择的方案就要多许多,比如Google的 ExoPlayer,B站的 ijkplayer,以及官方的Media

随机推荐