美文网首页
2019-11-20 Exoplayer针对具有时效性的播放地址

2019-11-20 Exoplayer针对具有时效性的播放地址

作者: 兣甅 | 来源:发表于2019-11-20 11:09 被阅读0次

    1.ExoVideoCacheManager

    import android.content.Context;
    
    import com.google.android.exoplayer2.database.ExoDatabaseProvider;
    import com.google.android.exoplayer2.upstream.cache.Cache;
    import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor;
    import com.google.android.exoplayer2.upstream.cache.SimpleCache;
    
    import java.io.File;
    
    public class ExoVideoCacheManager {
    
        private static Cache sCache;
    
        private ExoVideoCacheManager() {
        }
    
        public static Cache getCache(Context context) {
            return sCache == null ? (sCache = newCache(context)) : sCache;
        }
    
        private static Cache newCache(Context context) {
            return new SimpleCache(
                    new File(context.getExternalCacheDir(), "exo-video-cache"),//缓存目录
                    new LeastRecentlyUsedCacheEvictor(512 * 1024 * 1024),//缓存大小,默认512M,使用LRU算法实现
                    new ExoDatabaseProvider(context));
        }
    }
    

    2.工具类

    import android.net.Uri
    import com.blankj.utilcode.util.Utils
    import com.cc.happyrun.widget.video.player.ExoVideoCacheManager
    
    /**
     * Description:
     * @author: caiyoufei
     * @date: 2019/11/14 11:20
     */
    class ExoVideoCacheUtils private constructor() {
      private object SingletonHolder {
        val holder = ExoVideoCacheUtils()
      }
    
      companion object {
        val instance = SingletonHolder.holder
      }
    
      //APP视频的特有标识
      private val appVideoTag = "happyrundianbovideo"
      //APP视频的类型
      private val appVideoType = ".mp4"
      //视频总长度缓存key
      private val appVideoLenKey = "exo_len"
    
      //根据播放地址去获取缓存地址,如果返回没有缓存完成则返回原来的地址
      fun getCacheUrl(originUrl: String?): String? {
        //错误的播放地址
        if (originUrl.isNullOrBlank()) return originUrl
        //非网络地址
        if (!originUrl.startsWith("http", true)) {
          return Uri.parse(originUrl)
            .toString()
        }
        //当前播放地址的前半部分,用于缓存视频判断
        val videoPrefix: String
        //网络地址
        if (originUrl.contains(appVideoTag) && originUrl.contains("${appVideoType}?")) {
          //APP内部播放地址
          videoPrefix = originUrl.split("${appVideoType}?")[0] + appVideoType
        } else {
          //非当前APP
          return originUrl
        }
        //判断是否缓存完成
        val cache = ExoVideoCacheManager.getCache(Utils.getApp())
        //拿到所有缓存的key
        cache.keys?.let { keys ->
          //拿到和当前mp4匹配的key
          val result = keys.filter { key -> key.startsWith(videoPrefix) }
          if (!result.isNullOrEmpty()) {
            //遍历key
            result.forEach { key ->
              //获取视频总的需要缓存的长度
              val mMetadata = cache.getContentMetadata(key)
              val len = mMetadata.get(appVideoLenKey, 0)
              //获取到缓存完成的地址
              if (len > 0L && cache.isCached(key, 0, len)) {
                return key
              }
            }
          } else {
            return originUrl
          }
        }
        return originUrl
      }
    
      //打开APP的时候去清理没有缓存完成的视频信息(★★★子线程中执行★★★)
      fun openAappClearNoCacheComplete() {
        val cache = ExoVideoCacheManager.getCache(Utils.getApp())
        //只处理单独针对APP的
        val result = cache.keys.filter { it.contains(appVideoTag) && it.contains("${appVideoType}?") }
        if (!result.isNullOrEmpty()) {
          for (i in result.size - 1 downTo 0) {
            val key = result[i]
            //获取视频总的需要缓存的长度
            val mMetadata = cache.getContentMetadata(key)
            val len = mMetadata.get(appVideoLenKey, 0)
            //获取到缓存完成的地址
            if (len <= 0L || !cache.isCached(key, 0, len)) {
              val cachedSpans = cache.getCachedSpans(key)
              if (!cachedSpans.isNullOrEmpty()) {
                val list = cachedSpans.toMutableList()
                for (j in list.size - 1 downTo 0) {
                  cache.removeSpan(list[j])
                }
              }
            }
          }
        }
      }
    }
    

    3.具体使用(根据前缀找到已缓存的地址,用已缓存的地址进行播放;因为时效性的地址不同,但是都是针对服务器上的同一个视频)

    地址替换

    4.后期发现的问题优化(2020年3月11日14:52:0)

    可能由于不同的版本,导致总长度有点微小误差,所以判断总长度的时候稍微减少一点即可


    判断优化.png

    相关文章

      网友评论

          本文标题:2019-11-20 Exoplayer针对具有时效性的播放地址

          本文链接:https://www.haomeiwen.com/subject/antoictx.html