Ver Fonte

更新文档

杨充 há 4 anos atrás
pai
commit
293dd5497c

+ 6 - 6
Demo/build.gradle

@@ -60,13 +60,13 @@ dependencies {
 
     //自己封装的库,都有对应的案例项目【欢迎star】:https://github.com/yangchong211
     implementation 'cn.yc:YCStateLib:1.1'                                  //状态管理
-//    implementation project(':VideoCache')
-//    implementation project(':VideoPlayer')
-//    implementation project(':VideoKernel')
+    implementation project(':VideoCache')
+    implementation project(':VideoPlayer')
+    implementation project(':VideoKernel')
 
-    implementation 'cn.yc:VideoPlayer:3.0.1'
-    implementation 'cn.yc:VideoCache:3.0.0'
-    implementation 'cn.yc:VideoKernel:3.0.1'
+//    implementation 'cn.yc:VideoPlayer:3.0.1'
+//    implementation 'cn.yc:VideoCache:3.0.0'
+//    implementation 'cn.yc:VideoKernel:3.0.1'
     implementation 'cn.yc:YCStatusBarLib:1.4.0'
  //状态栏
 }

+ 1 - 1
Demo/src/main/java/org/yczbj/ycvideoplayer/newPlayer/ad/AdActivity.java

@@ -12,7 +12,7 @@ import com.yc.videocache.HttpProxyCacheServer;
 
 import org.yczbj.ycvideoplayer.ConstantVideo;
 import org.yczbj.ycvideoplayer.R;
-import org.yczbj.ycvideoplayer.newPlayer.cache.ProxyVideoCacheManager;
+import com.yc.videocache.cache.ProxyVideoCacheManager;
 import org.yczbj.ycvideoplayerlib.config.ConstantKeys;
 import org.yczbj.ycvideoplayerlib.player.VideoPlayer;
 import org.yczbj.ycvideoplayerlib.tool.BaseToast;

+ 2 - 2
Demo/src/main/java/org/yczbj/ycvideoplayer/newPlayer/tiktok/TikTok2Activity.java

@@ -13,8 +13,8 @@ import com.yc.kernel.utils.VideoLogUtils;
 
 import org.yczbj.ycvideoplayer.ConstantVideo;
 import org.yczbj.ycvideoplayer.R;
-import org.yczbj.ycvideoplayer.newPlayer.cache.PreloadManager;
-import org.yczbj.ycvideoplayer.newPlayer.cache.ProxyVideoCacheManager;
+import com.yc.videocache.cache.PreloadManager;
+import com.yc.videocache.cache.ProxyVideoCacheManager;
 import org.yczbj.ycvideoplayerlib.config.VideoInfoBean;
 import org.yczbj.ycvideoplayerlib.player.VideoPlayer;
 import org.yczbj.ycvideoplayerlib.tool.PlayerUtils;

+ 1 - 1
Demo/src/main/java/org/yczbj/ycvideoplayer/newPlayer/tiktok/Tiktok2Adapter.java

@@ -15,7 +15,7 @@ import androidx.viewpager.widget.PagerAdapter;
 import com.bumptech.glide.Glide;
 
 import org.yczbj.ycvideoplayer.R;
-import org.yczbj.ycvideoplayer.newPlayer.cache.PreloadManager;
+import com.yc.videocache.cache.PreloadManager;
 import org.yczbj.ycvideoplayerlib.config.VideoInfoBean;
 
 import java.util.ArrayList;

+ 2 - 2
Demo/src/main/java/org/yczbj/ycvideoplayer/newPlayer/cache/PreloadManager.java → VideoCache/src/main/java/com/yc/videocache/cache/PreloadManager.java

@@ -1,4 +1,4 @@
-package org.yczbj.ycvideoplayer.newPlayer.cache;
+package com.yc.videocache.cache;
 
 import android.content.Context;
 
@@ -13,7 +13,7 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
 /**
- * 抖音预加载工具,使用AndroidVideoCache实现
+ * 预加载工具,使用AndroidVideoCache实现
  */
 public class PreloadManager {
 

+ 4 - 2
Demo/src/main/java/org/yczbj/ycvideoplayer/newPlayer/cache/PreloadTask.java → VideoCache/src/main/java/com/yc/videocache/cache/PreloadTask.java

@@ -1,4 +1,4 @@
-package org.yczbj.ycvideoplayer.newPlayer.cache;
+package com.yc.videocache.cache;
 
 import com.yc.videocache.HttpProxyCacheServer;
 import com.yc.videocache.Logger;
@@ -91,7 +91,9 @@ public class PreloadTask implements Runnable {
      * 将预加载任务提交到线程池,准备执行
      */
     public void executeOn(ExecutorService executorService) {
-        if (mIsExecuted) return;
+        if (mIsExecuted) {
+            return;
+        }
         mIsExecuted = true;
         executorService.submit(this);
     }

+ 2 - 2
Demo/src/main/java/org/yczbj/ycvideoplayer/newPlayer/cache/ProxyVideoCacheManager.java → VideoCache/src/main/java/com/yc/videocache/cache/ProxyVideoCacheManager.java

@@ -1,4 +1,4 @@
-package org.yczbj.ycvideoplayer.newPlayer.cache;
+package com.yc.videocache.cache;
 
 import android.content.Context;
 
@@ -22,7 +22,7 @@ public class ProxyVideoCacheManager {
         return new HttpProxyCacheServer.Builder(context)
                 .maxCacheSize(512 * 1024 * 1024)       // 512MB for cache
                 //缓存路径,不设置默认在sd_card/Android/data/[app_package_name]/cache中
-//                .cacheDirectory()
+                //.cacheDirectory()
                 .build();
     }
 

+ 21 - 3
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/controller/BaseVideoController.java

@@ -235,18 +235,36 @@ public abstract class BaseVideoController extends FrameLayout implements InterVi
     }
 
     /**
-     * {@link VideoPlayer}调用此方法向控制器设置播放状态
+     * {@link VideoPlayer}调用此方法向控制器设置播放状态。
+     * 这里使用注解限定符,不要使用1,2这种直观数字,不方便知道意思
+     * 播放状态,主要是指播放器的各种状态
+     * -1               播放错误
+     * 0                播放未开始
+     * 1                播放准备中
+     * 2                播放准备就绪
+     * 3                正在播放
+     * 4                暂停播放
+     * 5                正在缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,缓冲区数据足够后恢复播放)
+     * 6                暂停缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,此时暂停播放器,继续缓冲,缓冲区数据足够后恢复暂停
+     * 7                播放完成
+     * 8                开始播放中止
      */
     @CallSuper
-    public void setPlayState(int playState) {
+    public void setPlayState(@ConstantKeys.CurrentStateType int playState) {
+        //设置播放器的状态
         handlePlayStateChanged(playState);
     }
 
     /**
      * {@link VideoPlayer}调用此方法向控制器设置播放器状态
+     * 播放模式
+     * 普通模式,小窗口模式,正常模式三种其中一种
+     * MODE_NORMAL              普通模式
+     * MODE_FULL_SCREEN         全屏模式
+     * MODE_TINY_WINDOW         小屏模式
      */
     @CallSuper
-    public void setPlayerState(final int playerState) {
+    public void setPlayerState(@ConstantKeys.PlayModeType final int playerState) {
         handlePlayerStateChanged(playerState);
     }
 

+ 1 - 1
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/controller/ControlWrapper.java

@@ -24,7 +24,7 @@ import androidx.annotation.NonNull;
 import org.yczbj.ycvideoplayerlib.player.InterVideoPlayer;
 
 /**
- * 此类的目的是为了在ControlComponent中既能调用VideoView的api又能调用BaseVideoController的api,
+ * 此类的目的是为了在InterControlView接口实现类中既能调用VideoPlayer的api又能调用BaseVideoController的api,
  * 并对部分api做了封装,方便使用
  */
 public class ControlWrapper implements InterVideoPlayer, InterVideoController {

+ 17 - 0
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/VideoPlayer.java

@@ -943,6 +943,18 @@ public class VideoPlayer<P extends AbstractVideoPlayer> extends FrameLayout
 
     /**
      * 向Controller设置播放状态,用于控制Controller的ui展示
+     * 这里使用注解限定符,不要使用1,2这种直观数字,不方便知道意思
+     * 播放状态,主要是指播放器的各种状态
+     * -1               播放错误
+     * 0                播放未开始
+     * 1                播放准备中
+     * 2                播放准备就绪
+     * 3                正在播放
+     * 4                暂停播放
+     * 5                正在缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,缓冲区数据足够后恢复播放)
+     * 6                暂停缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,此时暂停播放器,继续缓冲,缓冲区数据足够后恢复暂停
+     * 7                播放完成
+     * 8                开始播放中止
      */
     protected void setPlayState(@ConstantKeys.CurrentStateType int playState) {
         mCurrentPlayState = playState;
@@ -960,6 +972,11 @@ public class VideoPlayer<P extends AbstractVideoPlayer> extends FrameLayout
 
     /**
      * 向Controller设置播放器状态,包含全屏状态和非全屏状态
+     * 播放模式
+     * 普通模式,小窗口模式,正常模式三种其中一种
+     * MODE_NORMAL              普通模式
+     * MODE_FULL_SCREEN         全屏模式
+     * MODE_TINY_WINDOW         小屏模式
      */
     protected void setPlayerState(@ConstantKeys.PlayModeType int playerState) {
         mCurrentPlayerState = playerState;

+ 22 - 0
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/ui/view/BasisVideoController.java

@@ -190,6 +190,14 @@ public class BasisVideoController extends GestureVideoController implements View
         }
     }
 
+    /**
+     * 播放模式
+     * 普通模式,小窗口模式,正常模式三种其中一种
+     * MODE_NORMAL              普通模式
+     * MODE_FULL_SCREEN         全屏模式
+     * MODE_TINY_WINDOW         小屏模式
+     * @param playerState                   播放模式
+     */
     @Override
     protected void onPlayerStateChanged(int playerState) {
         super.onPlayerStateChanged(playerState);
@@ -225,6 +233,20 @@ public class BasisVideoController extends GestureVideoController implements View
 
     }
 
+    /**
+     * 播放状态
+     * -1               播放错误
+     * 0                播放未开始
+     * 1                播放准备中
+     * 2                播放准备就绪
+     * 3                正在播放
+     * 4                暂停播放
+     * 5                正在缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,缓冲区数据足够后恢复播放)
+     * 6                暂停缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,此时暂停播放器,继续缓冲,缓冲区数据足够后恢复暂停
+     * 7                播放完成
+     * 8                开始播放中止
+     * @param playState                     播放状态,主要是指播放器的各种状态
+     */
     @Override
     protected void onPlayStateChanged(int playState) {
         super.onPlayStateChanged(playState);

+ 55 - 0
read/01.视频播放器介绍文档.md

@@ -268,6 +268,20 @@
             LayoutInflater.from(getContext()).inflate(R.layout.layout_ad_control_view, this, true);
         }
        
+        /**
+         * 播放状态
+         * -1               播放错误
+         * 0                播放未开始
+         * 1                播放准备中
+         * 2                播放准备就绪
+         * 3                正在播放
+         * 4                暂停播放
+         * 5                正在缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,缓冲区数据足够后恢复播放)
+         * 6                暂停缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,此时暂停播放器,继续缓冲,缓冲区数据足够后恢复暂停
+         * 7                播放完成
+         * 8                开始播放中止
+         * @param playState                     播放状态,主要是指播放器的各种状态
+         */
         @Override
         public void onPlayStateChanged(int playState) {
             switch (playState) {
@@ -281,6 +295,14 @@
             }
         }
     
+        /**
+         * 播放模式
+         * 普通模式,小窗口模式,正常模式三种其中一种
+         * MODE_NORMAL              普通模式
+         * MODE_FULL_SCREEN         全屏模式
+         * MODE_TINY_WINDOW         小屏模式
+         * @param playerState                   播放模式
+         */
         @Override
         public void onPlayerStateChanged(int playerState) {
             switch (playerState) {
@@ -341,6 +363,39 @@
 
 
 
+#### 9.2 播放器UI抽取封装优化
+- 发展中遇到的问题
+    - 播放器可支持多种场景下的播放,多个产品会用到同一个播放器,这样就会带来一个问题,一个播放业务播放器状态发生变化,其他播放业务必须同步更新播放状态,各个播放业务之间互相交叉,随着播放业务的增多,开发和维护成本会急剧增加, 导致后续开发不可持续。 
+- UI难以自定义或者修改麻烦
+    - 比如常见的视频播放器,会把视频各种视图写到xml中,这种方式在后期代码会很大,而且改动一个小的布局,则会影响大。这样到后期往往只敢加代码,而不敢删除代码……
+    - 有时候难以适应新的场景,比如添加一个播放广告,老师开课,或者视频引导业务需求,则需要到播放器中写一堆业务代码。迭代到后期,违背了开闭原则,视频播放器需要做到和业务分离
+- 视频播放器结构需要清晰
+    - 也就是说视频player和ui操作柔和到了一起,尤其是两者之间的交互。比如播放中需要更新UI进度条,播放异常需要显示异常UI,都比较难处理播放器状态变化更新UI操作
+    - 这个是指该视频播放器能否看了文档后快速上手,知道封装的大概流程。方便后期他人修改和维护,因此需要将视频播放器功能分离。比如切换内核+视频播放器(player+controller+view)
+    - 一定要解耦合,播放器player与视频UI解耦:支持添加自定义视频视图,比如支持添加自定义广告,新手引导,或者视频播放异常等视图,这个需要较强的拓展性
+- 适合多种业务场景
+    - 比如适合播放单个视频,多个视频,以及列表视频,或者类似抖音那种一个页面一个视频,还有小窗口播放视频。也就是适合大多数业务场景
+- 方便播放业务发生变化
+    - 播放状态变化是导致不同播放业务场景之间交叉同步,解除播放业务对播放器的直接操控,采用接口监听进行解耦。比如:player+controller+interface
+- 关于视频播放器
+    - 定义一个视频播放器InterVideoPlayer接口,操作视频播放,暂停,缓冲,进度设置,设置播放模式等多种操作。
+    - 然后写一个播放器接口的具体实现类,在这个里面拿到内核播放器player,然后做相关的实现操作。
+- 关于视频视图View
+    - 定义一个视图InterVideoController接口,主要负责视图显示/隐藏,播放进度,锁屏,状态栏等操作。
+    - 然后写一个播放器视图接口的具体实现类,在这里里面inflate视图操作,然后接口方法实现,为了方便后期开发者自定义view,因此需要addView操作,将添加进来的视图用map集合装起来。
+- 播放器player和controller交互
+    - 在player中创建BaseVideoController对象,这个时候需要把controller添加到播放器中,这个时候有两个要点特别重要,需要把播放器状态监听,和播放模式监听传递给控制器
+    - setPlayState设置视频播放器播放逻辑状态,主要是播放缓冲,加载,播放中,暂停,错误,完成,异常,播放进度等多个状态,方便控制器做UI更新操作
+    - setPlayerState设置视频播放切换模式状态,主要是普通模式,小窗口模式,正常模式三种其中一种,方便控制器做UI更新
+- 播放器player和view交互
+    - 这块非常关键,举个例子,视频播放失败需要显示控制层的异常视图View;播放视频初始化需要显示loading,然后更新UI播放进度条等。都是播放器和视图层交互
+    - 可以定义一个类,同时实现InterVideoPlayer接口和InterVideoController接口,这个时候会重新这两个接口所有的方法。此类的目的是为了在InterControlView接口实现类中既能调用VideoPlayer的api又能调用BaseVideoController的api
+- 如何添加自定义播放器视图
+    - 添加了自定义播放器视图,比如添加视频广告,可以选择跳过,选择播放暂停。那这个视图view,肯定是需要操作player或者获取player的状态的。这个时候就需要暴露监听视频播放的状态接口监听
+    - 首先定义一个InterControlView接口,也就是说所有自定义视频视图view需要实现这个接口,该接口中的核心方法有:绑定视图到播放器,视图显示隐藏变化监听,播放状态监听,播放模式监听,进度监听,锁屏监听等
+    - 在BaseVideoController中的状态监听中,通过InterControlView接口对象就可以把播放器的状态传递到子类中
+
+
 
 #### 9.4 代码方面优化措施
 - **如果是在Activity中的话,建议设置下面这段代码**

+ 110 - 3
read/06.播放器UI抽取封装.md

@@ -11,12 +11,14 @@
 
 
 ### 01.视频播放器UI封装需求
+- 发展中遇到的问题
+    - 播放器可支持多种场景下的播放,多个产品会用到同一个播放器,这样就会带来一个问题,一个播放业务播放器状态发生变化,其他播放业务必须同步更新播放状态,各个播放业务之间互相交叉,随着播放业务的增多,开发和维护成本会急剧增加, 导致后续开发不可持续。 
 - 播放器内核和UI层耦合
     - 也就是说视频player和ui操作柔和到了一起,尤其是两者之间的交互。比如播放中需要更新UI进度条,播放异常需要显示异常UI,都比较难处理播放器状态变化更新UI操作
 - UI难以自定义或者修改麻烦
     - 比如常见的视频播放器,会把视频各种视图写到xml中,这种方式在后期代码会很大,而且改动一个小的布局,则会影响大。这样到后期往往只敢加代码,而不敢删除代码……
     - 有时候难以适应新的场景,比如添加一个播放广告,老师开课,或者视频引导业务需求,则需要到播放器中写一堆业务代码。迭代到后期,违背了开闭原则,视频播放器需要做到和业务分离
-- 视频播放器结构清晰
+- 视频播放器结构需要清晰
     - 这个是指该视频播放器能否看了文档后快速上手,知道封装的大概流程。方便后期他人修改和维护,因此需要将视频播放器功能分离。比如切换内核+视频播放器(player+controller+view)
 - 一定要解耦合
     - 播放器player与视频UI解耦:支持添加自定义视频视图,比如支持添加自定义广告,新手引导,或者视频播放异常等视图,这个需要较强的拓展性
@@ -30,8 +32,25 @@
 
 
 ### 03.如何分离播放和UI分离
-- 
-
+- 方便播放业务发生变化
+    - 播放状态变化是导致不同播放业务场景之间交叉同步,解除播放业务对播放器的直接操控,采用接口监听进行解耦。比如:player+controller+interface
+- 关于视频播放器
+    - 定义一个视频播放器InterVideoPlayer接口,操作视频播放,暂停,缓冲,进度设置,设置播放模式等多种操作。
+    - 然后写一个播放器接口的具体实现类,在这个里面拿到内核播放器player,然后做相关的实现操作。
+- 关于视频视图View
+    - 定义一个视图InterVideoController接口,主要负责视图显示/隐藏,播放进度,锁屏,状态栏等操作。
+    - 然后写一个播放器视图接口的具体实现类,在这里里面inflate视图操作,然后接口方法实现,为了方便后期开发者自定义view,因此需要addView操作,将添加进来的视图用map集合装起来。
+- 播放器player和controller交互
+    - 在player中创建BaseVideoController对象,这个时候需要把controller添加到播放器中,这个时候有两个要点特别重要,需要把播放器状态监听,和播放模式监听传递给控制器
+    - setPlayState设置视频播放器播放逻辑状态,主要是播放缓冲,加载,播放中,暂停,错误,完成,异常,播放进度等多个状态,方便控制器做UI更新操作
+    - setPlayerState设置视频播放切换模式状态,主要是普通模式,小窗口模式,正常模式三种其中一种,方便控制器做UI更新
+- 播放器player和view交互
+    - 这块非常关键,举个例子,视频播放失败需要显示控制层的异常视图View;播放视频初始化需要显示loading,然后更新UI播放进度条等。都是播放器和视图层交互
+    - 可以定义一个类,同时实现InterVideoPlayer接口和InterVideoController接口,这个时候会重新这两个接口所有的方法。此类的目的是为了在InterControlView接口实现类中既能调用VideoPlayer的api又能调用BaseVideoController的api
+- 如何添加自定义播放器视图
+    - 添加了自定义播放器视图,比如添加视频广告,可以选择跳过,选择播放暂停。那这个视图view,肯定是需要操作player或者获取player的状态的。这个时候就需要暴露监听视频播放的状态接口监听
+    - 首先定义一个InterControlView接口,也就是说所有自定义视频视图view需要实现这个接口,该接口中的核心方法有:绑定视图到播放器,视图显示隐藏变化监听,播放状态监听,播放模式监听,进度监听,锁屏监听等
+    - 在BaseVideoController中的状态监听中,通过InterControlView接口对象就可以把播放器的状态传递到子类中
 
 
 ### 04.VideoPlayer如何实现
@@ -46,6 +65,94 @@
 
 
 ### 07.如何添加自定义播放视图
+- 比如,现在有个业务需求,需要在视频播放器刚开始添加一个广告视图,等待广告倒计时120秒后,直接进入播放视频逻辑。相信这个业务场景很常见,大家都碰到过,使用该播放器就特别简单,代码如下所示:
+- 首先创建一个自定义view,需要实现InterControlView接口,重写该接口中所有抽象方法,这里省略了很多代码,具体看demo。
+    ``` java
+    public class AdControlView extends FrameLayout implements InterControlView, View.OnClickListener {
+    
+        private ControlWrapper mControlWrapper;
+        public AdControlView(@NonNull Context context) {
+            super(context);
+            init(context);
+        }
+    
+        private void init(Context context){
+            LayoutInflater.from(getContext()).inflate(R.layout.layout_ad_control_view, this, true);
+        }
+       
+        /**
+         * 播放状态
+         * -1               播放错误
+         * 0                播放未开始
+         * 1                播放准备中
+         * 2                播放准备就绪
+         * 3                正在播放
+         * 4                暂停播放
+         * 5                正在缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,缓冲区数据足够后恢复播放)
+         * 6                暂停缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,此时暂停播放器,继续缓冲,缓冲区数据足够后恢复暂停
+         * 7                播放完成
+         * 8                开始播放中止
+         * @param playState                     播放状态,主要是指播放器的各种状态
+         */
+        @Override
+        public void onPlayStateChanged(int playState) {
+            switch (playState) {
+                case ConstantKeys.CurrentState.STATE_PLAYING:
+                    mControlWrapper.startProgress();
+                    mPlayButton.setSelected(true);
+                    break;
+                case ConstantKeys.CurrentState.STATE_PAUSED:
+                    mPlayButton.setSelected(false);
+                    break;
+            }
+        }
+    
+        /**
+         * 播放模式
+         * 普通模式,小窗口模式,正常模式三种其中一种
+         * MODE_NORMAL              普通模式
+         * MODE_FULL_SCREEN         全屏模式
+         * MODE_TINY_WINDOW         小屏模式
+         * @param playerState                   播放模式
+         */
+        @Override
+        public void onPlayerStateChanged(int playerState) {
+            switch (playerState) {
+                case ConstantKeys.PlayMode.MODE_NORMAL:
+                    mBack.setVisibility(GONE);
+                    mFullScreen.setSelected(false);
+                    break;
+                case ConstantKeys.PlayMode.MODE_FULL_SCREEN:
+                    mBack.setVisibility(VISIBLE);
+                    mFullScreen.setSelected(true);
+                    break;
+            }
+            //暂未实现全面屏适配逻辑,需要你自己补全
+        }
+    }
+    ```
+- 然后该怎么使用这个自定义view呢?很简单,在之前基础上,通过控制器对象add进来即可,代码如下所示
+    ``` java
+    controller = new BasisVideoController(this);
+    AdControlView adControlView = new AdControlView(this);
+    adControlView.setListener(new AdControlView.AdControlListener() {
+        @Override
+        public void onAdClick() {
+            BaseToast.showRoundRectToast( "广告点击跳转");
+        }
+    
+        @Override
+        public void onSkipAd() {
+            playVideo();
+        }
+    });
+    controller.addControlComponent(adControlView);
+    //设置控制器
+    mVideoPlayer.setController(controller);
+    mVideoPlayer.setUrl(proxyUrl);
+    mVideoPlayer.start();
+    ```
+
 
 
 

+ 65 - 1
read/12.视频边播边缓存分析.md

@@ -1,12 +1,76 @@
-# 音频相关知识点学习
+# 12.视频边播边缓存分析
 #### 目录介绍
+- 01.前沿场景介绍一下
+- 02.致敬优秀开源项目
+- 03.边播边缓存原理
+- 04.如何实现预加载
+- 14.视频缓冲后拖动问题
 
 
 
 
+### 01.前沿场景介绍一下
+- 一些知名的视频app客户端(优酷,爱奇艺)播放视频的时候都有一些缓存进度(二级进度缓存),微信有关的小视频,还有一些短视频app,都有边播边缓的处理。
+- 还有就是当文件缓存完毕了再次播放的话就不再请求网络了直接播放本地文件了。既节省了流程又提高了加载速度。
 
 
+
+
+### 02.致敬优秀开源项目
+- 网络上比较好的项目:https://github.com/danikula/AndroidVideoCache
+    - 网络用的HttpURLConnection,文件缓存处理,文件最大限度策略,回调监听处理,断点续传,代理服务等。
+- 但是存在一些问题,比如如下所示
+    - 文件的缓存超过限制后没有按照lru算法删除,
+    - 处理返回给播放器的http响应头消息,响应头消息的获取处理改为head请求(需服务器支持)
+    - 替换网络库为okHttp(因为大部分的项目都是以okHttp为网络请求库的),但是这个改动性比较大
+- 然后看一下怎么使用,超级简单。传入视频url链接,返回一个代理链接,然后就可以呢
+    ```
+    HttpProxyCacheServer cacheServer = ProxyVideoCacheManager.getProxy(this);
+    String proxyUrl = cacheServer.getProxyUrl(URL_AD);
+    mVideoPlayer.setUrl(proxyUrl);
+  
+  
+    public static HttpProxyCacheServer getProxy(Context context) {
+        return sharedProxy == null ? (sharedProxy = newProxy(context)) : sharedProxy;
+    }
+
+    private static HttpProxyCacheServer newProxy(Context context) {
+        return new HttpProxyCacheServer.Builder(context)
+                .maxCacheSize(512 * 1024 * 1024)       // 512MB for cache
+                //缓存路径,不设置默认在sd_card/Android/data/[app_package_name]/cache中
+                //.cacheDirectory()
+                .build();
+    }
+    ```
+
+
+
+### 03.边播边缓存原理
+- 大概的原理
+    - 原始的方式是直接塞播放地址给播放器,它就可以直接播放。现在我们要在中间加一层本地代理,播放器播放的时候(获取数据)是通过我们的本地代理的地址来播放的,这样我们就可以很好的在中间层(本地代理层)做一些处理,比如:文件缓存,预缓存(秒开处理),监控等。
+
+
+
+### 04.如何实现预加载
+
+
+
+
+### 14.视频缓冲后拖动问题
+- 问题描述
+    - 在播放视频的时候,你看到缓冲buffer缓冲到了5分钟,但这个时候你把网络一关闭。然后拖动到3分钟,发现缓冲的视频有时候无法播放,这个是为什么呢?
+    - 
+
+
+
+
+
+
+
+### 参考博客
 - https://blog.csdn.net/ta893115871/article/details/71429738
+- https://blog.csdn.net/weixin_34402090/article/details/91367108
+- https://blog.csdn.net/u010107153/article/details/107091077