ソースを参照

完善视频播放器

杨充 4 年 前
コミット
0dda5ad517

+ 11 - 4
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/AudioFocusHelper.java

@@ -12,16 +12,19 @@ import org.yczbj.ycvideoplayerlib.player.VideoPlayer;
 import java.lang.ref.WeakReference;
 
 /**
- * 音频焦点改变监听
+ * <pre>
+ *     @author yangchong
+ *     blog  : https://github.com/yangchong211
+ *     time  : 2018/11/9
+ *     desc  : 音频焦点改变监听
+ *     revise:
+ * </pre>
  */
 public final class AudioFocusHelper implements AudioManager.OnAudioFocusChangeListener {
 
     private Handler mHandler = new Handler(Looper.getMainLooper());
-
     private WeakReference<VideoPlayer> mWeakVideoView;
-
     private AudioManager mAudioManager;
-
     private boolean mStartRequested = false;
     private boolean mPausedForLoss = false;
     private int mCurrentFocus = 0;
@@ -43,6 +46,7 @@ public final class AudioFocusHelper implements AudioManager.OnAudioFocusChangeLi
         mHandler.post(new Runnable() {
             @Override
             public void run() {
+                //处理音频焦点抢占
                 handleAudioFocusChange(focusChange);
             }
         });
@@ -116,6 +120,9 @@ public final class AudioFocusHelper implements AudioManager.OnAudioFocusChangeLi
         mAudioManager.abandonAudioFocus(this);
     }
 
+    /**
+     * 销毁资源
+     */
     public void release(){
         abandonFocus();
         if (mHandler!=null){

+ 16 - 20
app/src/main/java/org/yczbj/ycvideoplayer/newPlayer/list/RecyclerViewFragment.java

@@ -1,5 +1,6 @@
 package org.yczbj.ycvideoplayer.newPlayer.list;
 
+import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.os.Bundle;
 import android.view.LayoutInflater;
@@ -28,7 +29,7 @@ import java.util.List;
 /**
  * RecyclerView demo
  */
-public class RecyclerViewFragment extends Fragment implements OnItemChildClickListener {
+public class RecyclerViewFragment extends Fragment {
 
     protected List<VideoInfoBean> mVideos = new ArrayList<>();
     protected VideoRecyclerViewAdapter mAdapter;
@@ -46,7 +47,13 @@ public class RecyclerViewFragment extends Fragment implements OnItemChildClickLi
      * 上次播放的位置,用于页面切回来之后恢复播放
      */
     protected int mLastPos = mCurPos;
+    private Context context;
 
+    @Override
+    public void onAttach(@NonNull Context context) {
+        super.onAttach(context);
+        this.context = context;
+    }
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -62,14 +69,16 @@ public class RecyclerViewFragment extends Fragment implements OnItemChildClickLi
 
     protected void initView(View view) {
         initVideoView();
-        //保存进度
-//        mVideoView.setProgressManager(new ProgressManagerImpl());
-
         mRecyclerView = view.findViewById(R.id.recyclerView);
         mLinearLayoutManager = new LinearLayoutManager(getContext());
         mRecyclerView.setLayoutManager(mLinearLayoutManager);
         mAdapter = new VideoRecyclerViewAdapter(mVideos);
-        mAdapter.setOnItemChildClickListener(this);
+        mAdapter.setOnItemChildClickListener(new OnItemChildClickListener() {
+            @Override
+            public void onItemChildClick(int position) {
+                startPlay(position);
+            }
+        });
         mRecyclerView.setAdapter(mAdapter);
         mRecyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
             @Override
@@ -89,7 +98,7 @@ public class RecyclerViewFragment extends Fragment implements OnItemChildClickLi
     }
 
     protected void initVideoView() {
-        mVideoView = new VideoPlayer(getActivity());
+        mVideoView = new VideoPlayer(context);
         mVideoView.setOnStateChangeListener(new VideoPlayer.SimpleOnStateChangeListener() {
             @Override
             public void onPlayStateChanged(int playState) {
@@ -101,7 +110,7 @@ public class RecyclerViewFragment extends Fragment implements OnItemChildClickLi
                 }
             }
         });
-        mController = new BasisVideoController(getActivity());
+        mController = new BasisVideoController(context);
         mVideoView.setController(mController);
     }
 
@@ -142,14 +151,6 @@ public class RecyclerViewFragment extends Fragment implements OnItemChildClickLi
         startPlay(mLastPos);
     }
 
-    /**
-     * PrepareView被点击
-     */
-    @Override
-    public void onItemChildClick(int position) {
-        startPlay(position);
-    }
-
     /**
      * 开始播放
      * @param position 列表位置
@@ -160,10 +161,6 @@ public class RecyclerViewFragment extends Fragment implements OnItemChildClickLi
             releaseVideoView();
         }
         VideoInfoBean videoBean = mVideos.get(position);
-        //边播边存
-//        String proxyUrl = ProxyVideoCacheManager.getProxy(getActivity()).getProxyUrl(videoBean.getUrl());
-//        mVideoView.setUrl(proxyUrl);
-
         mVideoView.setUrl(videoBean.getVideoUrl());
         View itemView = mLinearLayoutManager.findViewByPosition(position);
         if (itemView == null) return;
@@ -176,7 +173,6 @@ public class RecyclerViewFragment extends Fragment implements OnItemChildClickLi
         VideoViewManager.instance().add(mVideoView, "list");
         mVideoView.start();
         mCurPos = position;
-
     }
 
     private void releaseVideoView() {

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

@@ -23,6 +23,7 @@
 #### 1.1 该库说明
 |**播放器功能** | MediaPlayer | ExoPlayer | IjkPlayer | RTC | TXPlayer |
 |--------   |-----        |---        |---        |---  |---     |
+|**UI/Player/业务解耦**| 支持  |支持   |支持   |   |   |
 |**切换视频播放模式** | 支持     |支持   |支持   |   |   |
 |**视频无缝切换** | 支持     |支持   |支持   |   |   |
 |**调节播放进度** | 支持     |支持   |支持   |   |   |
@@ -55,7 +56,7 @@
 |**画面** | 调整显示比例:默认、16:9、4:3、填充;播放时旋转画面角度(0,90,180,270);镜像旋转 |
 |**布局** | 内核和UI分离,和市面GitHub上大多数播放器不一样,方便定制,通过addView添加 |
 |**播放** | 正常播放,小窗播放,列表播放,仿抖音播放 |
-|**自定义** | 可以自定义添加视频UI层,支持自定义渲染层SurfaceView |
+|**自定义** | 可以自定义添加视频UI层,可以说UI和Player高度分离,支持自定义渲染层SurfaceView |
 
 
 

+ 23 - 35
read/02.视频播放器整体结构.md

@@ -51,9 +51,9 @@
 
 
 ### 03.需要达到的目的和效果
-- 基础封装视频播放器player,可以在ExoPlayer、MediaPlayer,声网视频播放器内核可以自由切换
-- 对于视图状态切换和后期维护拓展,避免功能和业务出现耦合
-- 针对视频播放,视频投屏,音频播放,播放回放
+- 基础封装视频播放器player,可以在ExoPlayer、MediaPlayer,声网RTC视频播放器内核,原生MediaPlayer可以自由切换
+- 对于视图状态切换和后期维护拓展,避免功能和业务出现耦合。比如需要支持播放器UI高度定制,而不是该lib库中UI代码
+- 针对视频播放,视频投屏,音频播放,播放回放,以及视频直播的功能
 
 
 
@@ -65,30 +65,21 @@
 
 
 
-
 ### 05.整体架构思路分析流程
 #### 5.1 视频分层
-- BasisMediaPlayer基础播放器
-    - 可以切换ExoPlayer、MediaPlayer,声网视频播放器
-    - 可以使用适配器设计模式,定义接口,子类不同实现来创建不同对象
-    - 针对不同视频播放器,可能存在api不同,所以这个类需要统一封装
+- 播放器内核
+    - 可以切换ExoPlayer、MediaPlayer,IjkPlayer,声网视频播放器,这里使用工厂模式Factory + AbstractVideoPlayer + 各个实现AbstractVideoPlayer抽象类的播放器类
+    - 定义抽象的播放器,主要包含视频初始化,设置,状态设置,以及播放监听。由于每个内核播放器api可能不一样,所以这里需要实现AbstractVideoPlayer抽象类的播放器类,方便后期统一调用
+    - 为了方便创建不同内核player,所以需要创建一个PlayerFactory,定义一个createPlayer创建播放器的抽象方法,然后各个内核都实现它,各自创建自己的播放器
 - VideoPlayer播放器
-    - 创建BasisMediaPlayer对象,可以自由切换视频内核
-    - 视频播放监听事件
-    - 播放暂停,开始,播放进度,获取视频属性
-- StatesPlayerController
-    - 负责视频各个不同视图view的切换。尽量保证功能单一性
-    - 以及将VideoPlayer添加进来,以及各种自定义视图view添加进来
-    - 负责给外部开发者xml里
-- 各种自定义视图view
-    - 各种自定义视图View
-    - 比如,添加视频,图片等广告,主要是负责UI操作的逻辑处理
-    - 比如,基础视频播放器view
-        - top,bottom
-    - 比如播放状态视图view
-        - 播放loading,失败,异常,完成
-- VideoPlayerManager
-    - 视频播放器统一管理者
+    - 可以自由切换视频内核,Player+Controller。player负责播放的逻辑,Controller负责视图相关的逻辑,两者之间用接口进行通信
+    - 针对Controller,需要定义一个接口,主要负责视图UI处理逻辑,支持添加各种自定义视图View【统一实现自定义接口Control】,每个view尽量保证功能单一性,最后通过addView形式添加进来
+    - 针对Player,需要定义一个接口,主要负责视频播放处理逻辑,比如视频播放,暂停,设置播放进度,设置视频链接,切换播放模式等操作。需要注意把Controller设置到Player里面,两者之间通过接口交互
+- UI控制器视图
+    - 定义一个BaseVideoController类,这个主要是集成各种事件的处理逻辑,比如播放器状态改变,控制视图隐藏和显示,播放进度改变,锁定状态改变,设备方向监听等等操作
+    - 定义一个view的接口InterControlView,在这里类里定义绑定视图,视图隐藏和显示,播放状态,播放模式,播放进度,锁屏等操作。这个每个实现类则都可以拿到这些属性呢
+    - 在BaseVideoController中使用LinkedHashMap保存每个自定义view视图,添加则put进来后然后通过addView将视图添加到该控制器中,这样非常方便添加自定义视图
+    - 播放器切换状态需要改变Controller视图,比如视频异常则需要显示异常视图view,则它们之间的交互是通过ControlWrapper(同时实现Controller接口和Player接口)实现
 
 
 ### 5.2 类架构图
@@ -98,27 +89,24 @@
 - 目标要求
     - 基础播放器封装了包含ExoPlayer、MediaPlayer,ijkPlayer,声网视频播放器等
     - 可以自由切换初始化任何一种视频播放器,比如通过构造传入类型参数来创建不同的视频播放器
-    ```
-    //创建rtc播放器
-    BasisMediaPlayer trcMediaPlayer = new BasisMediaPlayer(ConstantKeys.IjkPlayerType.TYPE_RTC);
-    //创建谷歌播放器
-    BasisMediaPlayer exoMediaPlayer = new BasisMediaPlayer(ConstantKeys.IjkPlayerType.TYPE_EXO);
-    //创建ijk播放器
-    BasisMediaPlayer ijkMediaPlayer = new BasisMediaPlayer(ConstantKeys.IjkPlayerType.TYPE_IJK);
+    ``` java
+    PlayerFactory playerFactory = IjkPlayerFactory.create();
+    IjkVideoPlayer ijkVideoPlayer = (IjkVideoPlayer) playerFactory.createPlayer(this);
+    PlayerFactory playerFactory = ExoPlayerFactory.create();
+    ExoMediaPlayer exoMediaPlayer = (ExoMediaPlayer) playerFactory.createPlayer(this);
+    PlayerFactory playerFactory = MediaPlayerFactory.create();
+    AndroidMediaPlayer androidMediaPlayer = (AndroidMediaPlayer) playerFactory.createPlayer(this);
     ```
 - 使用那种形式创建播放器
     - 工厂模式
     - 适配器模式
         - https://www.runoob.com/design-pattern/adapter-pattern.html
-- 遇到问题
-    
+        - 这个也是事后补救模式,但是在该库中,没有尝试这种方式
 
 
 ### 07.如何友好处理状态控制器
 - 状态控制器职责
     - 负责所有视图(自定义view视频视图)的状态管理切换
-- n中状态视图显示规则
-    - 初始化是gone
 
 
 ### 08.交互交给外部开发者

+ 82 - 444
read/03.视频播放器Api说明.md

@@ -11,6 +11,7 @@
 - 09.播放多个视频
 - 10.VideoPlayer相关Api
 - 11.Controller相关Api
+- 12.仿快手播放视频
 
 
 
@@ -186,11 +187,87 @@
     ```
 
 
-
-
-
 ### 06.在列表中播放
-
+- 第一步:初始化视频播放器,创建VideoPlayer对象
+    ``` java
+    mVideoView = new VideoPlayer(context);
+    mVideoView.setOnStateChangeListener(new VideoPlayer.SimpleOnStateChangeListener() {
+        @Override
+        public void onPlayStateChanged(int playState) {
+            //监听VideoViewManager释放,重置状态
+            if (playState == ConstantKeys.CurrentState.STATE_IDLE) {
+                PlayerUtils.removeViewFormParent(mVideoView);
+                mLastPos = mCurPos;
+                mCurPos = -1;
+            }
+        }
+    });
+    mController = new BasisVideoController(context);
+    mVideoView.setController(mController);
+    ```
+- 第二步:设置RecyclerView和Adapter
+    ```
+    mAdapter.setOnItemChildClickListener(new OnItemChildClickListener() {
+        @Override
+        public void onItemChildClick(int position) {
+            //点击item播放视频
+            startPlay(position);
+        }
+    });
+    mRecyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
+        @Override
+        public void onChildViewAttachedToWindow(@NonNull View view) {
+    
+        }
+    
+        @Override
+        public void onChildViewDetachedFromWindow(@NonNull View view) {
+            FrameLayout playerContainer = view.findViewById(R.id.player_container);
+            View v = playerContainer.getChildAt(0);
+            if (v != null && v == mVideoView && !mVideoView.isFullScreen()) {
+                //销毁视频
+                releaseVideoView();
+            }
+        }
+    });
+    ```
+- 第三步:播放视频和销毁视频的逻辑代码
+    ``` java
+    /**
+     * 开始播放
+     * @param position 列表位置
+     */
+    protected void startPlay(int position) {
+        if (mCurPos == position) return;
+        if (mCurPos != -1) {
+            releaseVideoView();
+        }
+        VideoInfoBean videoBean = mVideos.get(position);
+        mVideoView.setUrl(videoBean.getVideoUrl());
+        View itemView = mLinearLayoutManager.findViewByPosition(position);
+        if (itemView == null) return;
+        VideoRecyclerViewAdapter.VideoHolder viewHolder = (VideoRecyclerViewAdapter.VideoHolder) itemView.getTag();
+        //把列表中预置的PrepareView添加到控制器中,注意isPrivate此处只能为true。
+        mController.addControlComponent(viewHolder.mPrepareView, true);
+        PlayerUtils.removeViewFormParent(mVideoView);
+        viewHolder.mPlayerContainer.addView(mVideoView, 0);
+        //播放之前将VideoView添加到VideoViewManager以便在别的页面也能操作它
+        VideoViewManager.instance().add(mVideoView, "list");
+        mVideoView.start();
+        mCurPos = position;
+    }
+    
+    private void releaseVideoView() {
+        mVideoView.release();
+        if (mVideoView.isFullScreen()) {
+            mVideoView.stopFullScreen();
+        }
+        if(getActivity().getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
+            getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+        }
+        mCurPos = -1;
+    }
+    ```
 
 
 ### 08.其他重要功能Api
@@ -395,458 +472,19 @@
     controller.destroy();
     ```
 
+### 12.仿快手播放视频
 
 
 
 
 
 
-- 代码如下所示
-    - 在recyclerView中
-    ```
-    recyclerView.setRecyclerListener(new RecyclerView.RecyclerListener() {
-        @Override
-        public void onViewRecycled(RecyclerView.ViewHolder holder) {
-            VideoPlayer videoPlayer = ((VideoAdapter.VideoViewHolder) holder).mVideoPlayer;
-            if (videoPlayer == VideoPlayerManager.instance().getCurrentVideoPlayer()) {
-                VideoPlayerManager.instance().releaseVideoPlayer();
-            }
-        }
-    });
-    ```
-    - 在adapter中,仅仅展示部分代码
-    ```
-    @Override
-    public VideoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-        View itemView = LayoutInflater.from(mContext).inflate(R.layout.item_test_my_video, parent, false);
-        VideoViewHolder holder = new VideoViewHolder(itemView);
-        //创建视频播放控制器,主要只要创建一次就可以呢
-        VideoPlayerController controller = new VideoPlayerController(mContext);
-        holder.setController(controller);
-        return holder;
-    }
-
-    public class VideoViewHolder extends RecyclerView.ViewHolder {
-
-        public VideoPlayerController mController;
-        public VideoPlayer mVideoPlayer;
-
-        VideoViewHolder(View itemView) {
-            super(itemView);
-            mVideoPlayer = (VideoPlayer) itemView.findViewById(R.id.nice_video_player);
-            // 将列表中的每个视频设置为默认16:9的比例
-            ViewGroup.LayoutParams params = mVideoPlayer.getLayoutParams();
-            // 宽度为屏幕宽度
-            params.width = itemView.getResources().getDisplayMetrics().widthPixels;
-            // 高度为宽度的9/16
-            params.height = (int) (params.width * 9f / 16f);
-            mVideoPlayer.setLayoutParams(params);
-        }
-
-        /**
-         * 设置视频控制器参数
-         * @param controller            控制器对象
-         */
-        void setController(VideoPlayerController controller) {
-            mController = controller;
-            mVideoPlayer.setPlayerType(ConstantKeys.IjkPlayerType.TYPE_IJK);
-            mVideoPlayer.setController(mController);
-        }
-
-        void bindData(Video video) {
-            mController.setTitle(video.getTitle());
-            //mController.setLength(video.getLength());
-            ImageUtil.loadImgByPicasso(itemView.getContext(),video.getImageUrl(),R.drawable.image_default,mController.imageView());
-            mVideoPlayer.setUp(video.getVideoUrl(), null);
-        }
-    }
-    ```
-
-
-### 07.在activity播放视频处理home键逻辑
-- 代码如下所示
-    ```
-    private boolean pressedHome;
-    private HomeKeyWatcher mHomeKeyWatcher;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mHomeKeyWatcher = new HomeKeyWatcher(this);
-        mHomeKeyWatcher.setOnHomePressedListener(new HomeKeyWatcher.OnHomePressedListener() {
-            @Override
-            public void onHomePressed() {
-                pressedHome = true;
-            }
-        });
-        pressedHome = false;
-        mHomeKeyWatcher.startWatch();
-    }
-
-    @Override
-    protected void onStop() {
-        // 在OnStop中是release还是suspend播放器,需要看是不是因为按了Home键
-        if (pressedHome) {
-            VideoPlayerManager.instance().suspendVideoPlayer();
-        } else {
-            VideoPlayerManager.instance().releaseVideoPlayer();
-        }
-        super.onStop();
-        mHomeKeyWatcher.stopWatch();
-    }
-
-    @Override
-    protected void onRestart() {
-        mHomeKeyWatcher.startWatch();
-        pressedHome = false;
-        super.onRestart();
-        VideoPlayerManager.instance().resumeVideoPlayer();
-    }
-
-    @Override
-    public void onBackPressed() {
-        if (VideoPlayerManager.instance().onBackPressed()) {
-            return;
-        }
-        super.onBackPressed();
-    }
-    ```
-
-
-### 08.在fragment中播放
-- 和activity中一样,不同点在于处理fragment返回键逻辑
-    ```
-    //在宿主Activity中设置代码如下
-    @Override
-    protected void onStop() {
-        super.onStop();
-        VideoPlayerManager.instance().releaseVideoPlayer();
-    }
 
-    @Override
-    public void onBackPressed() {
-        if (VideoPlayerManager.instance().onBackPressed()) return;
-        super.onBackPressed();
-    }
 
-    //--------------------------------------------------
 
-    //在此Fragment中设置代码如下
-    @Override
-    public void onStop() {
-        super.onStop();
-        VideoPlayerManager.instance().releaseVideoPlayer();
-    }
-    ```
 
 
 
-### 09.1 显示视频top[分享,下载,更多按钮控件]
-- 默认是不显示这几个控件的,一般实际项目中,会对播放器做很多UI方面拓展
-    ```
-    controller.setTopVisibility(true);
-    ```
-- 给按钮设置点击事件
-    ```
-    controller.setOnVideoControlListener(new OnVideoControlListener() {
-        @Override
-        public void onVideoControlClick(int type) {
-            switch (type){
-                case ConstantKeys.VideoControl.DOWNLOAD:
-                    ToastUtils.showShort("下载");
-                    break;
-                case ConstantKeys.VideoControl.AUDIO:
-                    ToastUtils.showShort("转音频");
-                    break;
-                case ConstantKeys.VideoControl.SHARE:
-                    ToastUtils.showShort("分享");
-                    break;
-                case ConstantKeys.VideoControl.MENU:
-                    ToastUtils.showShort("更多");
-                    break;
-                case ConstantKeys.VideoControl.TV:
-                    ToastUtils.showShort("tv投影");
-                    break;
-                case ConstantKeys.VideoControl.HOR_AUDIO:
-                    ToastUtils.showShort("下载");
-                    break;
-                default:
-                    break;
-            }
-        }
-    });
-    ```
-
-
-### 09.2 显示横屏视频top[tv投影,切换音频控件]
-- 默认是不显示这几个控件的,一般实际项目中,会对播放器做很多UI方面拓展
-    ```
-    //设置横屏播放时,tv和audio图标是否显示
-    controller.setTvAndAudioVisibility(true,true);
-    ```
-- 给按钮设置点击事件
-    ```
-    controller.setOnVideoControlListener(new OnVideoControlListener() {
-        @Override
-        public void onVideoControlClick(int type) {
-            switch (type){
-                case ConstantKeys.VideoControl.TV:
-                    BaseToast.showRoundRectToast("投影tv电视");
-                    break;
-                case ConstantKeys.VideoControl.HOR_AUDIO:
-                    BaseToast.showRoundRectToast("切换音频");
-                    break;
-                default:
-                    break;
-            }
-        }
-    });
-    ```
-    
-    
-### 10.全局悬浮播放视频
-- 代码如下所示
-    ```
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        /*
-         * 这里在返回主页的时候销毁了,因为不想和DEMO中其他页面冲突
-         */
-        VideoPlayerManager.instance().releaseVideoPlayer();
-        FloatWindow.destroy();
-    }
-
-
-    private void startWindow() {
-        if (FloatWindow.get() != null) {
-            return;
-        }
-        String url = "http://play.g3proxy.lecloud.com/vod/v2/MjUxLzE2LzgvbGV0di11dHMvMTQvdmVyXzAwXzIyLTExMDc2NDEzODctYXZjLTE5OTgxOS1hYWMtNDgwMDAtNTI2MTEwLTE3MDg3NjEzLWY1OGY2YzM1NjkwZTA2ZGFmYjg2MTVlYzc5MjEyZjU4LTE0OTg1NTc2ODY4MjMubXA0?b=259&mmsid=65565355&tm=1499247143&key=f0eadb4f30c404d49ff8ebad673d3742&platid=3&splatid=345&playid=0&tss=no&vtype=21&cvid=2026135183914&payff=0&pip=08cc52f8b09acd3eff8bf31688ddeced&format=0&sign=mb&dname=mobile&expect=1&tag=mobile&xformat=super";
-        FloatPlayerView.setUrl(url);
-        FloatPlayerView floatPlayerView = new FloatPlayerView(getApplicationContext());
-        floatPlayerView.setCompletedListener(new FloatPlayerView.CompletedListener() {
-            @Override
-            public void Completed() {
-                FloatWindow.get().hide();
-            }
-        });
-        FloatWindow
-                .with(getApplicationContext())
-                .setView(floatPlayerView)
-                //.setWidth(WindowScreen.width, 0.4f)
-                //.setHeight(WindowScreen.width, 0.3f)
-                .setX(WindowScreen.width, 0.8f)             //这个是设置位置
-                .setY(WindowScreen.height, 0.3f)
-                .setMoveType(MoveType.slide)
-                .setFilter(false)
-                //.setFilter(true, WindowActivity.class, EmptyActivity.class)
-                .setMoveStyle(500, new BounceInterpolator())
-                .build();
-        FloatWindow.get().show();
-    }
-    ```
-
-
-
-### 11.常见api说明
-#### 11.1 关于VideoPlayer中设置属性方法
-- 如下所示
-    ```
-    //进入全屏模式
-    videoPlayer.enterFullScreen();
-    //进入竖屏的全屏模式
-    videoPlayer.enterVerticalScreenScreen();
-    //进入小窗口播放
-    //注意:小窗口播放视频比例是        16:9
-    videoPlayer.enterTinyWindow();
-
-    //释放,内部的播放器被释放掉,同时如果在全屏、小窗口模式下都会退出
-    videoPlayer.release();
-    //释放播放器,注意一定要判断对象是否为空,增强严谨性
-    videoPlayer.releasePlayer();
-
-    //设置播放器类型,必须设置
-    //输入值:ConstantKeys.IjkPlayerType.TYPE_IJK   或者  ConstantKeys.IjkPlayerType.TYPE_NATIVE
-    videoPlayer.setPlayerType(ConstantKeys.IjkPlayerType.TYPE_NATIVE);
-    //设置播放位置
-    videoPlayer.seekTo(100);
-    //设置播放速度,不必须
-    videoPlayer.setSpeed(100);
-    //设置视频链接
-    videoPlayer.setUp("",null);
-    //设置音量
-    videoPlayer.setVolume(50);
-
-    //是否从上一次的位置继续播放
-    videoPlayer.continueFromLastPosition(true);
-    ```
-
-
-#### 11.2 关于VideoPlayer中获取属性方法
-- 如下所示
-    ```
-    //关于视频播放相关api
-    //获取缓冲区百分比
-    int bufferPercentage = videoPlayer.getBufferPercentage();
-    //获取播放位置
-    long currentPosition = videoPlayer.getCurrentPosition();
-    //获取当前播放模式
-    int currentState = videoPlayer.getCurrentState();
-    //获取持续时长
-    long duration = videoPlayer.getDuration();
-    //获取最大音量
-    int maxVolume = videoPlayer.getMaxVolume();
-    //获取当前播放状态
-    int playType = videoPlayer.getPlayType();
-    //获取播放速度
-    long tcpSpeed = videoPlayer.getTcpSpeed();
-    //获取音量值
-    int volume = videoPlayer.getVolume();
-    ```
-
-#### 11.3 关于VideoPlayer中设置播放状态方法
-- 如下所示
-    ```
-    //判断是否是否缓冲暂停
-    boolean bufferingPaused = videoPlayer.isBufferingPaused();
-    //判断视频是否正在缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,缓冲区数据足够后恢复播放)
-    boolean bufferingPlaying = videoPlayer.isBufferingPlaying();
-    //判断视频是否播放完成
-    boolean completed = videoPlayer.isCompleted();
-    //判断视频是否播放错误
-    boolean error = videoPlayer.isError();
-    //判断视频是否播放全屏
-    boolean fullScreen = videoPlayer.isFullScreen();
-    //判断是否开始播放
-    boolean idle = videoPlayer.isIdle();
-    //判断视频是否正常播放
-    boolean normal = videoPlayer.isNormal();
-    //判断视频是否暂停播放
-    boolean paused = videoPlayer.isPaused();
-    //判断视频是否正在播放
-    boolean playing = videoPlayer.isPlaying();
-    //判断视频是否准备就绪
-    boolean prepared = videoPlayer.isPrepared();
-    //判断视频是否播放准备中
-    boolean preparing = videoPlayer.isPreparing();
-    //判断视频是否播放小窗口
-    boolean tinyWindow = videoPlayer.isTinyWindow();
-
-
-    //开始播放
-    videoPlayer.start();
-    //暂停播放
-    videoPlayer.pause();
-    //开始播放
-    videoPlayer.start(100);
-    //重新播放
-    videoPlayer.restart();
-    ```
-
-
-#### 11.4 关于controller控制器api
-- 如下所示
-    ```
-    //设置是否显示视频头部的下载,分享,其他等控件是否显示
-    controller.setTopVisibility(true);
-    controller.setTop(20);
-    //设置top到顶部的距离
-    controller.setTopPadding(30);
-    //设置加载loading类型
-    controller.setLoadingType(ConstantKeys.Loading.LOADING_RING);
-    //设置不操作后,多久自动隐藏头部和底部布局
-    controller.setHideTime(8000);
-    //设置中间播放按钮是否显示,并且支持设置自定义图标
-    controller.setCenterPlayer(true,R.drawable.image_default);
-    //获取ImageView的对象
-    ImageView imageView = controller.imageView();
-    //重新设置
-    controller.reset();
-    //设置图片
-    controller.setImage(R.drawable.ic_back_right);
-    //设置视频时长
-    controller.setLength(1000);
-    //设置视频标题
-    controller.setTitle("小杨逗比");
-    boolean lock = controller.getLock();
-    //设置横屏播放时,tv和audio图标是否显示
-    controller.setTvAndAudioVisibility(true,true);
-    //让用户自己处理返回键事件的逻辑
-    controller.setOnVideoBackListener(new OnVideoBackListener() {
-        @Override
-        public void onBackClick() {
-
-        }
-    });
-    //播放暂停监听事件
-    controller.setOnPlayOrPauseListener(new OnPlayOrPauseListener() {
-        @Override
-        public void onPlayOrPauseClick(boolean isPlaying) {
-
-        }
-    });
-    //监听视频播放完成事件
-    controller.setOnCompletedListener(new OnCompletedListener() {
-        @Override
-        public void onCompleted() {
-
-        }
-    });
-    //设置视频分享,下载,音视频转化点击事件
-    controller.setOnVideoControlListener(new OnVideoControlListener() {
-        @Override
-        public void onVideoControlClick(int type) {
-
-        }
-    });
-
-    //视频播放模式监听
-    controller.setOnPlayerTypeListener(new OnPlayerTypeListener() {
-        /**
-         * 切换到全屏播放监听
-         */
-        @Override
-        public void onFullScreen() {
-            LogUtils.e("setOnPlayerTypeListener"+"onFullScreen");
-        }
-        /**
-         * 切换到小窗口播放监听
-         */
-        @Override
-        public void onTinyWindow() {
-            LogUtils.e("setOnPlayerTypeListener"+"onTinyWindow");
-        }
-        /**
-         * 切换到正常播放监听
-         */
-        @Override
-        public void onNormal() {
-            LogUtils.e("setOnPlayerTypeListener"+"onNormal");
-        }
-    });
-    ```
-
-#### 11.5 关于视频播放器管理器api
-- 如下所示
-    ```
-    //VideoPlayerManager对象
-    VideoPlayerManager instance = VideoPlayerManager.instance();
-    //当视频暂停时或者缓冲暂停时,调用该方法重新开启视频播放
-    instance.resumeVideoPlayer();
-    //当视频正在播放或者正在缓冲时,调用该方法暂停视频
-    instance.suspendVideoPlayer();
-    //释放,内部的播放器被释放掉,同时如果在全屏、小窗口模式下都会退出
-    instance.releaseVideoPlayer();
-    //处理返回键逻辑
-    //如果是全屏,则退出全屏
-    //如果是小窗口,则退出小窗口
-    instance.onBackPressed();
-    //获取对象
-    VideoPlayer currentVideoPlayer = instance.getCurrentVideoPlayer();
-    //设置VideoPlayer
-    instance.setCurrentVideoPlayer(videoPlayer);
-    ```