admin 发表于 2018-10-18 09:23:23

GsyVideoPlayer视频播放器使用

https://github.com/CarGuo/GSYVideoPlayer

1.GSYVideoPlayer的初始化

2.视频播放实现

3.全屏实现

4.滑动时,小窗口出现和消失实现逻辑

5.小窗口视频创建

6.小窗口视频恢复为列表视频

7.边缓存边播放实现

8.弹幕效果实现



一.初始化分析

1.初始化主要是构造了一个StandardGSYVideoPlayer

2.设置全屏布局的容器

代码如下:

listVideoUtil = new ListVideoUtil(this);
listVideoUtil.setFullViewContainer(videoFullContainer);



public ListVideoUtil(Context context) {
      gsyVideoPlayer = new StandardGSYVideoPlayer(context);
      this.context = context;
}

StandardGSYVideoPlayer的初始化化主要是加载R.layout.video_layout_standard这个布局,并且实例化一些组件,为组件设置监听事件;

初始化组件包括:播放/暂停按钮,播放时长,总时长,播放进度条,返回按钮,全屏按钮和视频标题,

初始化组件不包括:用于显示视频的TextureView,这个TextureView是动态添加的,放在下片文章中讲述;

初始化内容比较简单;



思考以下几个问题:

1.视频窗口的大小和位置是如何匹配ListView的item大小和位置的?

2.视频播放画面是如何显示出来的?

3.视频播放的声音如何显示出来的?



通过代码分析;


@Override
public View getView(final int position, View convertView, ViewGroup parent) {

      ....

      ....

   listVideoUtil.addVideoPlayer(position, holder.imageView, TAG, holder.videoContainer, holder.playerBtn);

   holder.playerBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                notifyDataSetChanged();
                //listVideoUtil.setLoop(true);
                listVideoUtil.setPlayPositionAndTag(position, TAG);
//                final String url = "https://tv.miguvideo.com/?from=singlemessage&isappinstalled=0#video/live/761358370/room201706301600304971_R1";
                //listVideoUtil.setCachePath(new File(FileUtils.getPath()));
                final String url = "http://baobab.wdjcdn.com/14564977406580.mp4";
                listVideoUtil.startPlay(url);
            }
      });

       ........

      .......

}

listview的adapter的getview方法每次都会走一次listVideoUtil.addVideoPlayer(position, holder.imageView, TAG, holder.videoContainer, holder.playerBtn);

/**
   * 动态添加视频播放
   *
   * @param position位置
   * @param imgView   封面
   * @param tag       TAG类型
   * @param container player的容器
   * @param playBtn   播放按键
   */
    public void addVideoPlayer(final int position, View imgView, String tag,
                               ViewGroup container, View playBtn) {
      container.removeAllViews();
      if (isCurrentViewPlaying(position, tag)) {
            if (!isFull) {
                ViewGroup viewGroup = (ViewGroup) gsyVideoPlayer.getParent();
                if (viewGroup != null)
                  viewGroup.removeAllViews();
                container.addView(gsyVideoPlayer);
                playBtn.setVisibility(View.INVISIBLE);
            }
      } else {
            playBtn.setVisibility(View.VISIBLE);
            container.removeAllViews();   //增加封面
            container.addView(imgView);
      }
    }

代码可以看出addVideoPlayer方法的意思是,如果当前的position等于listVideoUtil中获取到的position,videoContainer中就显示gsyVideoPlayer,否则显示视频封面;

点击播放按钮的作用:

1.向listVideoUtil中设置position,并通过notifyDataSetChanged方法使重新走getview(),重新走getview方法时,会重新进入addVideoPlayer方法判断;

   至此第一个疑问已经解决:视频显示在哪个item就是这个position决定的;视频窗口的大小由videoContainer的大小决定;

2.执行代码listVideoUtil.startPlay(url);



下面开始分析startPlay(url)中做了哪些操作?

/**
   * 开始播放
   *
   * @param url 播放的URL
   */
    public void startPlay(String url) {

      if (isSmall()) {
            smallVideoToNormal();//如果是小窗口,就转为正常窗口播放,这个问题后面再说
      }

      this.url = url;

      gsyVideoPlayer.release();

      gsyVideoPlayer.setLooping(isLoop);//视频是否循环播放

      gsyVideoPlayer.setSpeed(speed);//视频播放速度

      gsyVideoPlayer.setNeedShowWifiTip(needShowWifiTip);//非wifi环境下,显示流量提醒

      gsyVideoPlayer.setNeedLockFull(needLockFull);//是否需要全屏锁屏

      gsyVideoPlayer.setUp(url, true, cachePath, mapHeadData, objects);//设置边缓存边播放

      //增加title
      gsyVideoPlayer.getTitleTextView().setVisibility(View.GONE);

      //设置返回键
      gsyVideoPlayer.getBackButton().setVisibility(View.GONE);

      //设置全屏按键功能
      gsyVideoPlayer.getFullscreenButton().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                resolveFullBtn();
            }
      });

      gsyVideoPlayer.startPlayLogic();
    }



就是一些简单设置项,其中gsyVideoPlayer.setUp(url, true, cachePath, mapHeadData, objects);会把url改为全局的mUrl;



    @Override
    public void startPlayLogic() {
      if (mStandardVideoAllCallBack != null) {
            Debuger.printfLog("onClickStartThumb");
            mStandardVideoAllCallBack.onClickStartThumb(mUrl, mObjects);
      }
      prepareVideo();
      startDismissControlViewTimer();
    }





    /**
   * 开始状态视频播放
   */
    protected void prepareVideo() {
      if (GSYVideoManager.instance().listener() != null) {
            GSYVideoManager.instance().listener().onCompletion();
      }
      GSYVideoManager.instance().setListener(this);
      GSYVideoManager.instance().setPlayTag(mPlayTag);
      GSYVideoManager.instance().setPlayPosition(mPlayPosition);
      addTextureView();//动态添加TextureView
      mAudioManager.requestAudioFocus(onAudioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);//暂时获取音频焦点
      ((Activity) getContext()).getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//保持屏幕常亮不灭屏
      GSYVideoManager.instance().prepare(mUrl, mMapHeadData, mLooping, mSpeed);
      setStateAndUi(CURRENT_STATE_PREPAREING);
    }

    科普1,音频焦点分类:

    AudioManager.AUDIOFOCUS_REQUEST_GRANTED------------永久获取音频焦点

    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT-------------暂时获取音频焦点,比如音乐后台播放,当前视频播放会抢夺音频焦点,视频播放完成,音乐自动播放;

   AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK--------提示类型获取音频焦点,比如听音乐的时候来短信,音乐声音降低



   /**
   * 添加播放的view
   */
    protected void addTextureView() {
      if (mTextureViewContainer.getChildCount() > 0) {
            mTextureViewContainer.removeAllViews();
      }
      mTextureView = null;
      mTextureView = new GSYTextureView(getContext());
      mTextureView.setSurfaceTextureListener(this);
      mTextureView.setRotation(mRotate);

      RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
      layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
      mTextureViewContainer.addView(mTextureView, layoutParams);
    }

    构造了一个TextureView,并添加到gsyVideoPlayer布局中。

    TextureView设置了SurfaceTextureListener;

   科普2:SurfaceTextureListener回调方法:

1.onSurfaceTextureAvailable(SurfaceTexture arg0, int arg1, int arg2)-------------TextureView可用时调用

2.onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height)

3.onSurfaceTextureDestroyed(SurfaceTexture surface)------------TextureView销毁时调用

4.onSurfaceTextureUpdated(SurfaceTexture surface)

   回到代码:

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
      mSurface = new Surface(surface);
      GSYVideoManager.instance().setDisplay(mSurface);
      //显示暂停切换显示的图片
      showPauseCover();
    }

    意思是:在TextureView可以使用时,将surface交给GSYVideoManager,用于显示视频的画面,至此第二个问题已经解决,当然此时还没有开始播放视频, 真正播放视频是在

GSYVideoManager.instance().prepare(mUrl, mMapHeadData, mLooping, mSpeed)中,此处的mUrl就是上面保存的url;

页: [1]
查看完整版本: GsyVideoPlayer视频播放器使用