├── Document ├── qplayer2-core │ └── html │ │ ├── images │ │ ├── anchor-copy-button.svg │ │ ├── arrow_down.svg │ │ ├── copy-icon.svg │ │ ├── copy-successful-icon.svg │ │ ├── footer-go-to-link.svg │ │ ├── go-to-top-icon.svg │ │ ├── logo-icon.svg │ │ └── theme-toggle.svg │ │ ├── index.html │ │ ├── navigation.html │ │ ├── qplayer2-core │ │ ├── com.qiniu.qmedia.component.player │ │ │ ├── -q-authentication-error-type │ │ │ │ ├── -companion │ │ │ │ │ ├── index.html │ │ │ │ │ └── value-of.html │ │ │ │ ├── -n-o-n-e │ │ │ │ │ └── index.html │ │ │ │ ├── -n-o_-a-p-m_-a-u-t-h │ │ │ │ │ └── index.html │ │ │ │ ├── -n-o_-b-a-s-e_-a-u-t-h │ │ │ │ │ └── index.html │ │ │ │ ├── -n-o_-b-l-i-n-d_-a-u-t-h │ │ │ │ │ └── index.html │ │ │ │ ├── -n-o_-s-e-i_-a-u-t-h │ │ │ │ │ └── index.html │ │ │ │ ├── -n-o_-s-r-t_-a-u-t-h │ │ │ │ │ └── index.html │ │ │ │ ├── -n-o_-v-r_-a-u-t-h │ │ │ │ │ └── index.html │ │ │ │ ├── code.html │ │ │ │ └── index.html │ │ │ ├── -q-i-media-item-command-not-allow-listener │ │ │ │ ├── index.html │ │ │ │ └── on-command-not-allow.html │ │ │ ├── -q-i-media-item-control-handler │ │ │ │ ├── index.html │ │ │ │ ├── pause.html │ │ │ │ ├── resume.html │ │ │ │ ├── start.html │ │ │ │ └── stop.html │ │ │ ├── -q-i-media-item-log-handler │ │ │ │ ├── index.html │ │ │ │ ├── log.html │ │ │ │ └── set-log-level.html │ │ │ ├── -q-i-media-item-state-change-listener-collection │ │ │ │ ├── add-media-item-state-change-listener.html │ │ │ │ ├── index.html │ │ │ │ ├── remove-all-play-media-state-change-listener.html │ │ │ │ └── remove-play-media-state-change-listener.html │ │ │ ├── -q-i-media-item-state-change-listener │ │ │ │ ├── index.html │ │ │ │ └── on-state-changed.html │ │ │ ├── -q-i-player-audio-data-listener │ │ │ │ ├── -q-channel-layout │ │ │ │ │ ├── -companion │ │ │ │ │ │ ├── index.html │ │ │ │ │ │ └── value-of.html │ │ │ │ │ ├── -l-a-y-o-u-t_-s-t-e-r-e-o │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -n-o-n-e │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── value.html │ │ │ │ ├── -q-sample-format │ │ │ │ │ ├── -companion │ │ │ │ │ │ ├── index.html │ │ │ │ │ │ └── value-of.html │ │ │ │ │ ├── -n-o-n-e │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -s-i-g-n_-i-n-t_16 │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── value.html │ │ │ │ ├── index.html │ │ │ │ └── on-audio-data.html │ │ │ ├── -q-i-player-audio-listener │ │ │ │ ├── index.html │ │ │ │ └── on-mute-changed.html │ │ │ ├── -q-i-player-authentication-listener │ │ │ │ ├── index.html │ │ │ │ ├── on_authentication_failed.html │ │ │ │ └── on_authentication_success.html │ │ │ ├── -q-i-player-bite-rate-listener │ │ │ │ ├── index.html │ │ │ │ └── on-bite-rate-changed.html │ │ │ ├── -q-i-player-buffering-listener │ │ │ │ ├── index.html │ │ │ │ ├── on-buffering-end.html │ │ │ │ └── on-buffering-start.html │ │ │ ├── -q-i-player-command-not-allow-listener │ │ │ │ ├── index.html │ │ │ │ └── on-command-not-allow.html │ │ │ ├── -q-i-player-control-handler │ │ │ │ ├── force-authentication-from-network.html │ │ │ │ ├── index.html │ │ │ │ ├── init.html │ │ │ │ ├── pause-render.html │ │ │ │ ├── play-media-item.html │ │ │ │ ├── play-media-model.html │ │ │ │ ├── release.html │ │ │ │ ├── resume-render.html │ │ │ │ ├── seek.html │ │ │ │ ├── set-audio-data-callback-enable.html │ │ │ │ ├── set-decode-type.html │ │ │ │ ├── set-log-level.html │ │ │ │ ├── set-mute.html │ │ │ │ ├── set-s-e-i-enable.html │ │ │ │ ├── set-seek-mode.html │ │ │ │ ├── set-speed.html │ │ │ │ ├── set-start-action.html │ │ │ │ ├── set-subtitle-enable.html │ │ │ │ ├── set-subtitle.html │ │ │ │ ├── set-video-data-callback-enable.html │ │ │ │ ├── set-video-data-callback-type.html │ │ │ │ ├── shoot-video.html │ │ │ │ ├── stop.html │ │ │ │ └── switch-quality.html │ │ │ ├── -q-i-player-download-listener │ │ │ │ ├── index.html │ │ │ │ └── on-download-changed.html │ │ │ ├── -q-i-player-f-p-s-listener │ │ │ │ ├── index.html │ │ │ │ └── on-f-p-s-changed.html │ │ │ ├── -q-i-player-format-listener │ │ │ │ ├── index.html │ │ │ │ └── on-format-not-support.html │ │ │ ├── -q-i-player-log-handler │ │ │ │ └── index.html │ │ │ ├── -q-i-player-media-network-listener │ │ │ │ ├── -open-error │ │ │ │ │ ├── -companion │ │ │ │ │ │ ├── index.html │ │ │ │ │ │ └── value-of.html │ │ │ │ │ ├── -f-o-r-m-a-t_-i-n-v-a-l-i-d │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -i-n-t-e-r-r-u-p-t │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -i-o-e-r-r-o-r │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -n-o-n-e │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -u-n-k-o-w-n │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -u-r-l_-i-n-v-a-l-i-d │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── error.html │ │ │ │ │ └── index.html │ │ │ │ ├── index.html │ │ │ │ ├── on-open-failed.html │ │ │ │ ├── on-reconnect-end.html │ │ │ │ └── on-reconnect-start.html │ │ │ ├── -q-i-player-progress-listener │ │ │ │ ├── index.html │ │ │ │ └── on-progress-changed.html │ │ │ ├── -q-i-player-quality-listener │ │ │ │ ├── index.html │ │ │ │ ├── on-quality-switch-canceled.html │ │ │ │ ├── on-quality-switch-complete.html │ │ │ │ ├── on-quality-switch-failed.html │ │ │ │ ├── on-quality-switch-retry-later.html │ │ │ │ └── on-quality-switch-start.html │ │ │ ├── -q-i-player-render-handler │ │ │ │ ├── index.html │ │ │ │ ├── set-blind-type.html │ │ │ │ ├── set-mirror-type.html │ │ │ │ ├── set-panorama-view-rotate.html │ │ │ │ ├── set-panorama-view-scale.html │ │ │ │ ├── set-render-ratio.html │ │ │ │ ├── set-rotation.html │ │ │ │ ├── set-scale.html │ │ │ │ ├── set-surface.html │ │ │ │ └── synch-surface-size.html │ │ │ ├── -q-i-player-render-listener │ │ │ │ ├── index.html │ │ │ │ └── on-first-frame-rendered.html │ │ │ ├── -q-i-player-s-e-i-data-listener │ │ │ │ ├── index.html │ │ │ │ └── on-s-e-i-data.html │ │ │ ├── -q-i-player-seek-listener │ │ │ │ ├── index.html │ │ │ │ ├── on-seek-failed.html │ │ │ │ └── on-seek-success.html │ │ │ ├── -q-i-player-shoot-video-listener │ │ │ │ ├── -shoot-video-type │ │ │ │ │ ├── -companion │ │ │ │ │ │ ├── index.html │ │ │ │ │ │ └── value-of.html │ │ │ │ │ ├── -j-p-e-g │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -n-o-n-e │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── type.html │ │ │ │ ├── index.html │ │ │ │ ├── on-shoot-failed.html │ │ │ │ └── on-shoot-successful.html │ │ │ ├── -q-i-player-speed-listener │ │ │ │ ├── index.html │ │ │ │ └── on-speed-changed.html │ │ │ ├── -q-i-player-state-change-listener-collection │ │ │ │ ├── add-player-state-change-listener.html │ │ │ │ ├── index.html │ │ │ │ ├── remove-all-player-state-change-listener.html │ │ │ │ └── remove-player-state-change-listener.html │ │ │ ├── -q-i-player-state-change-listener │ │ │ │ ├── index.html │ │ │ │ └── on-state-changed.html │ │ │ ├── -q-i-player-subtitle-listener │ │ │ │ ├── index.html │ │ │ │ ├── on_subtitle_close.html │ │ │ │ ├── on_subtitle_decoded.html │ │ │ │ ├── on_subtitle_loaded.html │ │ │ │ ├── on_subtitle_name_change.html │ │ │ │ ├── on_subtitle_open.html │ │ │ │ └── on_subtitle_text_change.html │ │ │ ├── -q-i-player-video-data-listener │ │ │ │ ├── -q-video-data-type │ │ │ │ │ ├── -companion │ │ │ │ │ │ ├── index.html │ │ │ │ │ │ └── value-of.html │ │ │ │ │ ├── -n-o-n-e │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -n-v21 │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -r-g-b-a │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -y-u-v_420-p │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── value.html │ │ │ │ ├── index.html │ │ │ │ └── on-video-data.html │ │ │ ├── -q-i-player-video-decode-listener │ │ │ │ ├── index.html │ │ │ │ ├── not-support-codec-format.html │ │ │ │ ├── on-decode-failed.html │ │ │ │ └── on-video-decode-by-type.html │ │ │ ├── -q-i-player-video-frame-size-change-listener │ │ │ │ ├── index.html │ │ │ │ └── on-video-frame-size-changed.html │ │ │ ├── -q-log-level │ │ │ │ ├── -l-o-g_-d-e-b-u-g │ │ │ │ │ └── index.html │ │ │ │ ├── -l-o-g_-e-r-r-o-r │ │ │ │ │ └── index.html │ │ │ │ ├── -l-o-g_-i-n-f-o │ │ │ │ │ └── index.html │ │ │ │ ├── -l-o-g_-q-u-i-t │ │ │ │ │ └── index.html │ │ │ │ ├── -l-o-g_-v-e-r-b-o-s-e │ │ │ │ │ └── index.html │ │ │ │ ├── -l-o-g_-w-a-r-n-i-n-g │ │ │ │ │ └── index.html │ │ │ │ ├── index.html │ │ │ │ └── level.html │ │ │ ├── -q-media-item-context │ │ │ │ ├── -q-media-item-context.html │ │ │ │ ├── index.html │ │ │ │ └── play-media-control-handler.html │ │ │ ├── -q-media-item-control-handler │ │ │ │ ├── current-state.html │ │ │ │ └── index.html │ │ │ ├── -q-media-item-notify │ │ │ │ ├── -companion │ │ │ │ │ ├── index.html │ │ │ │ │ └── value-of.html │ │ │ │ ├── -n-o-n-e │ │ │ │ │ └── index.html │ │ │ │ ├── -n-o-t-i-f-y_-e-v-e-n-t_-l-o-o-p_-c-o-m-m-o-n-d_-n-o-t_-a-l-l-o-w │ │ │ │ │ └── index.html │ │ │ │ ├── -n-o-t-i-f-y_-i-n-p-u-t_-s-t-r-e-a-m_-i-o_-e-r-r-o-r │ │ │ │ │ └── index.html │ │ │ │ ├── -n-o-t-i-f-y_-i-n-p-u-t_-s-t-r-e-a-m_-o-p-e-n │ │ │ │ │ └── index.html │ │ │ │ ├── -n-o-t-i-f-y_-i-n-p-u-t_-s-t-r-e-a-m_-o-p-e-n_-e-r-r-o-r │ │ │ │ │ └── index.html │ │ │ │ ├── index.html │ │ │ │ └── value.html │ │ │ ├── -q-media-item-state │ │ │ │ ├── -companion │ │ │ │ │ ├── index.html │ │ │ │ │ └── value-of.html │ │ │ │ ├── -d-i-s-c-a-r-d │ │ │ │ │ └── index.html │ │ │ │ ├── -e-r-r-o-r │ │ │ │ │ └── index.html │ │ │ │ ├── -l-o-a-d-i-n-g │ │ │ │ │ └── index.html │ │ │ │ ├── -n-o-n-e │ │ │ │ │ └── index.html │ │ │ │ ├── -p-a-u-s-e-d │ │ │ │ │ └── index.html │ │ │ │ ├── -p-r-e-p-a-r-e │ │ │ │ │ └── index.html │ │ │ │ ├── -p-r-e-p-a-r-e_-u-s-e │ │ │ │ │ └── index.html │ │ │ │ ├── -s-t-o-p-e-d │ │ │ │ │ └── index.html │ │ │ │ ├── -u-s-e-d │ │ │ │ │ └── index.html │ │ │ │ ├── index.html │ │ │ │ └── value.html │ │ │ ├── -q-media-model-builder │ │ │ │ ├── -q-media-model-builder.html │ │ │ │ ├── add-stream-element.html │ │ │ │ ├── add-subtitle-element.html │ │ │ │ ├── build.html │ │ │ │ └── index.html │ │ │ ├── -q-media-model │ │ │ │ ├── index.html │ │ │ │ ├── is-live.html │ │ │ │ ├── stream-elements.html │ │ │ │ └── subtitle-elements.html │ │ │ ├── -q-play-media-notify-param-keys │ │ │ │ ├── index.html │ │ │ │ └── value.html │ │ │ ├── -q-player-context │ │ │ │ ├── -q-player-context.html │ │ │ │ ├── get-player-control-handler.html │ │ │ │ ├── get-player-render-handler.html │ │ │ │ └── index.html │ │ │ ├── -q-player-control-handler │ │ │ │ ├── -companion │ │ │ │ │ ├── -i-n-v-a-l-i-d_-q-u-a-l-i-t-y_-i-d.html │ │ │ │ │ └── index.html │ │ │ │ ├── add-player-audio-data-listener.html │ │ │ │ ├── add-player-audio-listener.html │ │ │ │ ├── add-player-authentication-listener.html │ │ │ │ ├── add-player-bite-rate-change-listener.html │ │ │ │ ├── add-player-buffering-change-listener.html │ │ │ │ ├── add-player-command-not-allow-listener.html │ │ │ │ ├── add-player-download-change-listener.html │ │ │ │ ├── add-player-f-p-s-change-listener.html │ │ │ │ ├── add-player-format-listener.html │ │ │ │ ├── add-player-media-network-listener.html │ │ │ │ ├── add-player-progress-change-listener.html │ │ │ │ ├── add-player-quality-listener.html │ │ │ │ ├── add-player-s-e-i-data-listener.html │ │ │ │ ├── add-player-seek-listener.html │ │ │ │ ├── add-player-shoot-video-listener.html │ │ │ │ ├── add-player-speed-change-listener.html │ │ │ │ ├── add-player-subtitle-listener.html │ │ │ │ ├── add-player-video-data-listener.html │ │ │ │ ├── add-player-video-decode-type-listener.html │ │ │ │ ├── add-player-video-frame-size-change-listener.html │ │ │ │ ├── bite-rate.html │ │ │ │ ├── buffer-positon.html │ │ │ │ ├── current-player-state.html │ │ │ │ ├── current-position.html │ │ │ │ ├── download-speed.html │ │ │ │ ├── duration.html │ │ │ │ ├── fps.html │ │ │ │ ├── get-current-quality.html │ │ │ │ ├── get-switching-quality.html │ │ │ │ ├── index.html │ │ │ │ ├── is-buffering.html │ │ │ │ ├── is-mute.html │ │ │ │ ├── remove-all-player-audio-data-listeners.html │ │ │ │ ├── remove-all-player-audio-listeners.html │ │ │ │ ├── remove-all-player-authentications.html │ │ │ │ ├── remove-all-player-bite-rate-change-listener.html │ │ │ │ ├── remove-all-player-buffering-change-listener.html │ │ │ │ ├── remove-all-player-command-not-allow-listener.html │ │ │ │ ├── remove-all-player-download-change-listener.html │ │ │ │ ├── remove-all-player-f-p-s-change-listener.html │ │ │ │ ├── remove-all-player-format-listeners.html │ │ │ │ ├── remove-all-player-media-network-listener.html │ │ │ │ ├── remove-all-player-progress-change-listener.html │ │ │ │ ├── remove-all-player-quality-listener.html │ │ │ │ ├── remove-all-player-s-e-i-data-listeners.html │ │ │ │ ├── remove-all-player-seek-listeners.html │ │ │ │ ├── remove-all-player-shoot-video-listeners.html │ │ │ │ ├── remove-all-player-speed-change-listener.html │ │ │ │ ├── remove-all-player-subtitle-listeners.html │ │ │ │ ├── remove-all-player-video-data-listeners.html │ │ │ │ ├── remove-all-player-video-decode-type-listener.html │ │ │ │ ├── remove-all-player-video-frame-size-change-listeners.html │ │ │ │ ├── remove-player-audio-data-listener.html │ │ │ │ ├── remove-player-audio-listener.html │ │ │ │ ├── remove-player-authentication-listener.html │ │ │ │ ├── remove-player-bite-rate-change-listener.html │ │ │ │ ├── remove-player-buffering-change-listener.html │ │ │ │ ├── remove-player-command-not-allow-listener.html │ │ │ │ ├── remove-player-download-change-listener.html │ │ │ │ ├── remove-player-f-p-s-change-listener.html │ │ │ │ ├── remove-player-format-listener.html │ │ │ │ ├── remove-player-media-network-listener.html │ │ │ │ ├── remove-player-progress-change-listener.html │ │ │ │ ├── remove-player-quality-listener.html │ │ │ │ ├── remove-player-s-e-i-data-listener.html │ │ │ │ ├── remove-player-seek-listener.html │ │ │ │ ├── remove-player-shoot-video-listener.html │ │ │ │ ├── remove-player-speed-change-listener.html │ │ │ │ ├── remove-player-subtitle-listener.html │ │ │ │ ├── remove-player-video-data-listener.html │ │ │ │ ├── remove-player-video-decode-type-listener.html │ │ │ │ ├── remove-player-video-frame-size-change-listener.html │ │ │ │ ├── set-speed.html │ │ │ │ ├── speed.html │ │ │ │ ├── subtitle-name.html │ │ │ │ ├── subtitle-text.html │ │ │ │ ├── switch-quality.html │ │ │ │ ├── video-height.html │ │ │ │ └── video-width.html │ │ │ ├── -q-player-decode-type │ │ │ │ ├── -companion │ │ │ │ │ ├── index.html │ │ │ │ │ └── value-of.html │ │ │ │ ├── -f-i-r-s-t_-f-r-a-m-e_-a-c-c-e-l │ │ │ │ │ └── index.html │ │ │ │ ├── -h-a-r-d-w-a-r-e_-b-u-f-f-e-r │ │ │ │ │ └── index.html │ │ │ │ ├── -h-a-r-d-w-a-r-e_-s-u-r-f-a-c-e │ │ │ │ │ └── index.html │ │ │ │ ├── -n-o-n-e │ │ │ │ │ └── index.html │ │ │ │ ├── -s-o-f-t-w-a-r-e │ │ │ │ │ └── index.html │ │ │ │ ├── index.html │ │ │ │ └── value.html │ │ │ ├── -q-player-render-handler │ │ │ │ ├── add-player-render-listener.html │ │ │ │ ├── index.html │ │ │ │ ├── remove-all-player-render-listener.html │ │ │ │ └── remove-player-render-listener.html │ │ │ ├── -q-player-setting │ │ │ │ ├── -q-player-blind │ │ │ │ │ ├── -q-p-l-a-y-e-r_-b-l-i-n-d_-s-e-t-t-i-n-g_-b-l-u-e │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -q-p-l-a-y-e-r_-b-l-i-n-d_-s-e-t-t-i-n-g_-g-r-e-e-n │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -q-p-l-a-y-e-r_-b-l-i-n-d_-s-e-t-t-i-n-g_-n-o-n-e │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -q-p-l-a-y-e-r_-b-l-i-n-d_-s-e-t-t-i-n-g_-r-e-d │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── value.html │ │ │ │ ├── -q-player-decoder │ │ │ │ │ ├── -q-p-l-a-y-e-r_-d-e-c-o-d-e-r_-s-e-t-t-i-n-g_-a-u-t-o │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -q-p-l-a-y-e-r_-d-e-c-o-d-e-r_-s-e-t-t-i-n-g_-f-i-r-s-t_-f-r-a-m-e_-a-c-c-e-l_-p-r-i-o-r-i-t-y │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -q-p-l-a-y-e-r_-d-e-c-o-d-e-r_-s-e-t-t-i-n-g_-h-a-r-d-w-a-r-e_-p-r-i-o-r-i-t-y │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -q-p-l-a-y-e-r_-d-e-c-o-d-e-r_-s-e-t-t-i-n-g_-s-o-f-t_-p-r-i-o-r-i-t-y │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── value.html │ │ │ │ ├── -q-player-mirror │ │ │ │ │ ├── -q-p-l-a-y-e-r_-m-i-r-r-o-r_-n-o-n-e │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -q-p-l-a-y-e-r_-m-i-r-r-o-r_-x-y │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -q-p-l-a-y-e-r_-m-i-r-r-o-r_-x │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -q-p-l-a-y-e-r_-m-i-r-r-o-r_-y │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── value.html │ │ │ │ ├── -q-player-render-ratio │ │ │ │ │ ├── -q-p-l-a-y-e-r_-r-a-t-i-o_-s-e-t-t-i-n-g_-a-u-t-o │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -q-p-l-a-y-e-r_-r-a-t-i-o_-s-e-t-t-i-n-g_-f-u-l-l_-s-c-r-e-e-n │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -q-p-l-a-y-e-r_-r-a-t-i-o_-s-e-t-t-i-n-g_-s-t-r-e-t-c-h │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -q-p-l-a-y-e-r_-r-a-t-i-o_-s-e-t-t-i-n-g_16_9 │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -q-p-l-a-y-e-r_-r-a-t-i-o_-s-e-t-t-i-n-g_4_3 │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── value.html │ │ │ │ ├── -q-player-seek │ │ │ │ │ ├── -q-p-l-a-y-e-r_-s-e-e-k_-s-e-t-t-i-n-g_-a-c-c-u-r-a-t-e │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -q-p-l-a-y-e-r_-s-e-e-k_-s-e-t-t-i-n-g_-n-o-r-m-a-l │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── value.html │ │ │ │ ├── -q-player-setting.html │ │ │ │ ├── -q-player-start │ │ │ │ │ ├── -q-p-l-a-y-e-r_-s-t-a-r-t_-s-e-t-t-i-n-g_-p-a-u-s-e │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── -q-p-l-a-y-e-r_-s-t-a-r-t_-s-e-t-t-i-n-g_-p-l-a-y-i-n-g │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── value.html │ │ │ │ └── index.html │ │ │ ├── -q-player-state │ │ │ │ ├── -c-o-m-p-l-e-t-e-d │ │ │ │ │ └── index.html │ │ │ │ ├── -companion │ │ │ │ │ ├── index.html │ │ │ │ │ └── value-of.html │ │ │ │ ├── -e-n-d │ │ │ │ │ └── index.html │ │ │ │ ├── -e-r-r-o-r │ │ │ │ │ └── index.html │ │ │ │ ├── -i-n-i-t │ │ │ │ │ └── index.html │ │ │ │ ├── -m-e-d-i-a_-i-t-e-m_-p-r-e-p-a-r-e │ │ │ │ │ └── index.html │ │ │ │ ├── -n-o-n-e │ │ │ │ │ └── index.html │ │ │ │ ├── -p-a-u-s-e-d_-r-e-n-d-e-r │ │ │ │ │ └── index.html │ │ │ │ ├── -p-l-a-y-i-n-g │ │ │ │ │ └── index.html │ │ │ │ ├── -p-r-e-p-a-r-e │ │ │ │ │ └── index.html │ │ │ │ ├── -r-e-l-e-a-s-e │ │ │ │ │ └── index.html │ │ │ │ ├── -s-e-e-k-i-n-g │ │ │ │ │ └── index.html │ │ │ │ ├── -s-t-o-p-p-e-d │ │ │ │ │ └── index.html │ │ │ │ ├── index.html │ │ │ │ └── value.html │ │ │ ├── -q-quality │ │ │ │ ├── -q-quality.html │ │ │ │ ├── index.html │ │ │ │ ├── quality.html │ │ │ │ ├── url-type.html │ │ │ │ └── user-type.html │ │ │ ├── -q-stream-element │ │ │ │ ├── -q-stream-element.html │ │ │ │ ├── backup-url.html │ │ │ │ ├── hls-d-r-m-key.html │ │ │ │ ├── index.html │ │ │ │ ├── is-selected.html │ │ │ │ ├── mp4-drm-key.html │ │ │ │ ├── mp4-q-n-drm-com-key.html │ │ │ │ ├── mp4-q-n-drm-file-key.html │ │ │ │ ├── quality.html │ │ │ │ ├── referer.html │ │ │ │ ├── url-type.html │ │ │ │ ├── url.html │ │ │ │ ├── user-type.html │ │ │ │ └── video-render-type.html │ │ │ ├── -q-subtitle-element │ │ │ │ ├── -q-subtitle-element.html │ │ │ │ ├── backup-url.html │ │ │ │ ├── index.html │ │ │ │ ├── is-selected.html │ │ │ │ ├── name.html │ │ │ │ └── url.html │ │ │ ├── -q-u-r-l-type │ │ │ │ ├── -companion │ │ │ │ │ ├── index.html │ │ │ │ │ └── value-of.html │ │ │ │ ├── -n-o-n-e │ │ │ │ │ └── index.html │ │ │ │ ├── -q-a-u-d-i-o │ │ │ │ │ └── index.html │ │ │ │ ├── -q-a-u-d-i-o_-a-n-d_-v-i-d-e-o │ │ │ │ │ └── index.html │ │ │ │ ├── -q-v-i-d-e-o │ │ │ │ │ └── index.html │ │ │ │ ├── index.html │ │ │ │ └── value.html │ │ │ ├── -q-video-data-callback-type │ │ │ │ ├── -n-v12 │ │ │ │ │ └── index.html │ │ │ │ ├── -r-g-b-a │ │ │ │ │ └── index.html │ │ │ │ ├── -y-u-v420-p │ │ │ │ │ └── index.html │ │ │ │ ├── index.html │ │ │ │ └── type.html │ │ │ ├── -q-video-render-type │ │ │ │ ├── -n-o-n-e │ │ │ │ │ └── index.html │ │ │ │ ├── -p-a-n-o-r-a-m-a_-e-q-u-i-r-e-c-t_-a-n-g-u-l-a-r │ │ │ │ │ └── index.html │ │ │ │ ├── -p-l-a-n-e │ │ │ │ │ └── index.html │ │ │ │ ├── index.html │ │ │ │ └── value.html │ │ │ ├── get-audio-quality-list.html │ │ │ ├── get-subtitle-list.html │ │ │ ├── get-video-quality-list.html │ │ │ └── index.html │ │ ├── com.qiniu.qmedia.render.screen │ │ │ ├── -q-surface-render-view │ │ │ │ ├── -q-surface-render-view.html │ │ │ │ ├── attach-render-handler.html │ │ │ │ ├── index.html │ │ │ │ ├── surface-changed.html │ │ │ │ ├── surface-created.html │ │ │ │ ├── surface-destroyed.html │ │ │ │ └── surface-redraw-needed.html │ │ │ ├── -q-texture-render-view │ │ │ │ ├── -companion │ │ │ │ │ ├── -t-a-g.html │ │ │ │ │ └── index.html │ │ │ │ ├── -q-texture-render-view.html │ │ │ │ ├── attach-render-handler.html │ │ │ │ ├── index.html │ │ │ │ ├── on-surface-texture-available.html │ │ │ │ ├── on-surface-texture-destroyed.html │ │ │ │ ├── on-surface-texture-size-changed.html │ │ │ │ └── on-surface-texture-updated.html │ │ │ └── index.html │ │ ├── com.qiniu.qmedia.ui │ │ │ ├── -q-surface-player-view │ │ │ │ ├── -q-surface-player-view.html │ │ │ │ ├── index.html │ │ │ │ ├── player-control-handler.html │ │ │ │ └── player-render-handler.html │ │ │ ├── -q-texture-player-view │ │ │ │ ├── -q-texture-player-view.html │ │ │ │ ├── index.html │ │ │ │ ├── player-control-handler.html │ │ │ │ └── player-render-handler.html │ │ │ └── index.html │ │ └── package-list │ │ ├── scripts │ │ ├── clipboard.js │ │ ├── main.js │ │ ├── navigation-loader.js │ │ ├── pages.json │ │ ├── platform-content-handler.js │ │ ├── prism.js │ │ └── sourceset_dependencies.js │ │ └── styles │ │ ├── jetbrains-mono.css │ │ ├── logo-styles.css │ │ ├── main.css │ │ ├── prism.css │ │ └── style.css └── qplayer2-ext │ └── html │ ├── images │ ├── anchor-copy-button.svg │ ├── arrow_down.svg │ ├── copy-icon.svg │ ├── copy-successful-icon.svg │ ├── footer-go-to-link.svg │ ├── go-to-top-icon.svg │ ├── logo-icon.svg │ └── theme-toggle.svg │ ├── index.html │ ├── navigation.html │ ├── qplayer2-ext │ ├── com.qiniu.qplayer2ext.common.collection │ │ ├── -collections │ │ │ ├── -iterator-action-with-index │ │ │ │ ├── index.html │ │ │ │ └── run.html │ │ │ ├── -iterator-action │ │ │ │ ├── index.html │ │ │ │ └── run.html │ │ │ ├── -safe-iterator-collection │ │ │ │ ├── for-each-with-index.html │ │ │ │ ├── for-each.html │ │ │ │ ├── index.html │ │ │ │ └── is-iterating.html │ │ │ ├── -safe-iterator-list │ │ │ │ ├── add-all.html │ │ │ │ ├── add.html │ │ │ │ ├── clear.html │ │ │ │ ├── contains-all.html │ │ │ │ ├── contains.html │ │ │ │ ├── for-each-with-index.html │ │ │ │ ├── for-each.html │ │ │ │ ├── get.html │ │ │ │ ├── index-of.html │ │ │ │ ├── index.html │ │ │ │ ├── is-empty.html │ │ │ │ ├── is-iterating.html │ │ │ │ ├── iterator.html │ │ │ │ ├── last-index-of.html │ │ │ │ ├── list-iterator.html │ │ │ │ ├── remove-all.html │ │ │ │ ├── remove.html │ │ │ │ ├── retain-all.html │ │ │ │ ├── set.html │ │ │ │ ├── size.html │ │ │ │ ├── sub-list.html │ │ │ │ └── to-array.html │ │ │ ├── -safe-iterator-map │ │ │ │ ├── clear.html │ │ │ │ ├── contains-key.html │ │ │ │ ├── contains-value.html │ │ │ │ ├── entry-set.html │ │ │ │ ├── for-each-with-index.html │ │ │ │ ├── for-each.html │ │ │ │ ├── get.html │ │ │ │ ├── index.html │ │ │ │ ├── is-empty.html │ │ │ │ ├── is-iterating.html │ │ │ │ ├── key-set.html │ │ │ │ ├── put-all.html │ │ │ │ ├── put.html │ │ │ │ ├── remove.html │ │ │ │ ├── size.html │ │ │ │ └── values.html │ │ │ ├── index.html │ │ │ ├── safe-iterator-list.html │ │ │ └── safe-iterator-map.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.common.measure │ │ ├── -dp-utils │ │ │ ├── dp-to-px.html │ │ │ └── index.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.common.rxjava3 │ │ ├── -completable-subscriber-builder │ │ │ ├── -completable-subscriber-builder.html │ │ │ ├── complete-action.html │ │ │ ├── index.html │ │ │ └── on-complete.html │ │ ├── -disposable-helper │ │ │ ├── -disposable-helper.html │ │ │ ├── activate.html │ │ │ ├── add.html │ │ │ ├── deactivate.html │ │ │ └── index.html │ │ ├── -error-subscriber-builder │ │ │ ├── -error-subscriber-builder.html │ │ │ ├── error-consumer.html │ │ │ ├── index.html │ │ │ └── on-error.html │ │ ├── -function-action │ │ │ ├── -function-action.html │ │ │ ├── function.html │ │ │ ├── index.html │ │ │ └── run.html │ │ ├── -function-consumer │ │ │ ├── -function-consumer.html │ │ │ ├── accept.html │ │ │ ├── function.html │ │ │ └── index.html │ │ ├── -maybe-subscriber-builder │ │ │ ├── -maybe-subscriber-builder.html │ │ │ ├── complete-action.html │ │ │ ├── index.html │ │ │ └── on-complete.html │ │ ├── -observable-flowable-subscriber-builder │ │ │ ├── -observable-flowable-subscriber-builder.html │ │ │ ├── index.html │ │ │ ├── next-consumer.html │ │ │ └── on-next.html │ │ ├── -single-subscriber-builder │ │ │ ├── -single-subscriber-builder.html │ │ │ ├── index.html │ │ │ ├── on-success.html │ │ │ └── success-consumer.html │ │ ├── add-to-composite-disposable.html │ │ ├── add-to-disposable-helper.html │ │ ├── attach-to-lifecycle.html │ │ ├── index.html │ │ ├── into.html │ │ ├── io-subscribe-ui-observe.html │ │ ├── never-dispose.html │ │ ├── run-on-computation-scheduler.html │ │ ├── run-on-io-scheduler.html │ │ └── subscribe-by.html │ ├── com.qiniu.qplayer2ext.common.thread │ │ ├── -b-thread-pool-executor │ │ │ ├── -b-thread-pool-executor.html │ │ │ ├── -companion │ │ │ │ └── index.html │ │ │ ├── await-termination.html │ │ │ ├── execute.html │ │ │ ├── high-priority.html │ │ │ ├── index.html │ │ │ ├── is-shutdown.html │ │ │ ├── is-terminated.html │ │ │ ├── shutdown-now.html │ │ │ └── shutdown.html │ │ ├── -b-thread-pool │ │ │ ├── -b-thread-pool.html │ │ │ ├── -companion │ │ │ │ ├── index.html │ │ │ │ ├── init.html │ │ │ │ └── new-single-thread-executor.html │ │ │ ├── -pool-reporter │ │ │ │ ├── index.html │ │ │ │ ├── report-core-thread-state.html │ │ │ │ └── report-thread-time-out.html │ │ │ └── index.html │ │ ├── -handler-threads │ │ │ ├── -t-h-r-e-a-d_-b-a-c-k-g-r-o-u-n-d.html │ │ │ ├── -t-h-r-e-a-d_-b-a-c-k_-i-o.html │ │ │ ├── -t-h-r-e-a-d_-r-e-p-o-r-t.html │ │ │ ├── -t-h-r-e-a-d_-s-i-z-e.html │ │ │ ├── -t-h-r-e-a-d_-u-i.html │ │ │ ├── -thread-model │ │ │ │ └── index.html │ │ │ ├── get-handler.html │ │ │ ├── get-looper.html │ │ │ ├── index.html │ │ │ ├── post-at-front.html │ │ │ ├── post-delayed.html │ │ │ ├── post.html │ │ │ ├── remove.html │ │ │ ├── run-on-blocking.html │ │ │ ├── run-on.html │ │ │ └── running-on.html │ │ ├── -p-o-o-l_-n-a-m-e_-c-o-r-e.html │ │ ├── -p-o-o-l_-n-a-m-e_-d-i-s-c-a-r-d.html │ │ ├── -p-o-o-l_-n-a-m-e_-r-i-s-k.html │ │ ├── -pool-name │ │ │ ├── -pool-name.html │ │ │ └── index.html │ │ ├── -r-e-p-o-r-t_-w-h-e-n_-d-i-s-c-a-r-d.html │ │ ├── -r-e-p-o-r-t_-w-h-e-n_-q-u-e-u-e.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.commonplayer.controller │ │ ├── -common-player-video-switcher │ │ │ ├── add-video-play-event-listener.html │ │ │ ├── get-current-playable-params.html │ │ │ ├── get-current-video-params.html │ │ │ ├── get-switch-playable-params.html │ │ │ ├── get-switch-video-params.html │ │ │ ├── has-next-playable-params.html │ │ │ ├── has-next-video.html │ │ │ ├── index.html │ │ │ ├── on-state-changed.html │ │ │ ├── on-update.html │ │ │ ├── remove-video-play-event-listener.html │ │ │ ├── replay-current-video.html │ │ │ ├── switch-first-video.html │ │ │ ├── switch-next-playable-params.html │ │ │ ├── switch-next-video.html │ │ │ ├── switch-playable-params-subject.html │ │ │ ├── switch-video-id-subject.html │ │ │ ├── switch-video.html │ │ │ └── update-data-source.html │ │ ├── -i-common-chain-auto-play-strategy │ │ │ ├── index.html │ │ │ ├── on-all-video-completed.html │ │ │ ├── on-video-completed.html │ │ │ ├── on-video-item-completed.html │ │ │ ├── on-video-item-start.html │ │ │ ├── on-video-item-will-change.html │ │ │ ├── on-video-will-change.html │ │ │ ├── start.html │ │ │ └── stop.html │ │ ├── -i-common-player-video-switcher │ │ │ ├── -i-common-video-play-event-listener │ │ │ │ ├── index.html │ │ │ │ ├── on-all-video-params-completed.html │ │ │ │ ├── on-playable-params-completed.html │ │ │ │ ├── on-playable-params-start.html │ │ │ │ ├── on-playable-params-will-change.html │ │ │ │ ├── on-video-params-completed.html │ │ │ │ ├── on-video-params-set-changed.html │ │ │ │ ├── on-video-params-start.html │ │ │ │ └── on-video-params-will-change.html │ │ │ ├── add-video-play-event-listener.html │ │ │ ├── index.html │ │ │ └── remove-video-play-event-listener.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.commonplayer.data │ │ ├── -common-playable-params │ │ │ ├── -common-playable-params.html │ │ │ ├── control-panel-type.html │ │ │ ├── display-orientation.html │ │ │ ├── environment-type.html │ │ │ ├── index.html │ │ │ ├── media-model.html │ │ │ └── start-pos.html │ │ ├── -common-player-data-source │ │ │ ├── -common-playable-params-updater │ │ │ │ ├── filter.html │ │ │ │ ├── index.html │ │ │ │ └── update.html │ │ │ ├── -common-player-data-source.html │ │ │ ├── -data-source-builder │ │ │ │ ├── -companion │ │ │ │ │ ├── -t-a-g.html │ │ │ │ │ └── index.html │ │ │ │ ├── -data-source-builder.html │ │ │ │ ├── add-video.html │ │ │ │ ├── build.html │ │ │ │ └── index.html │ │ │ ├── get-first-video-params.html │ │ │ ├── get-next-video-params-by-id.html │ │ │ ├── get-playable-params-count.html │ │ │ ├── get-playable-params.html │ │ │ ├── get-video-params-list.html │ │ │ ├── get-video-params.html │ │ │ ├── index.html │ │ │ └── update-data-source.html │ │ ├── -common-video-params │ │ │ ├── -common-video-params.html │ │ │ ├── id.html │ │ │ └── index.html │ │ ├── -display-orientation │ │ │ ├── -l-a-n-d-s-c-a-p-e │ │ │ │ └── index.html │ │ │ ├── -n-o-n-e │ │ │ │ └── index.html │ │ │ ├── -v-e-r-t-i-c-a-l │ │ │ │ └── index.html │ │ │ └── index.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.commonplayer.enviroment │ │ ├── -i-common-player-environment │ │ │ ├── authentication.html │ │ │ ├── index.html │ │ │ ├── name.html │ │ │ ├── service-types.html │ │ │ ├── start.html │ │ │ └── stop.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.commonplayer.external │ │ ├── -i-common-player-life-cycle-dispatcher │ │ │ ├── index.html │ │ │ ├── on-create-view.html │ │ │ ├── on-create.html │ │ │ ├── on-destroy-view.html │ │ │ ├── on-destroy.html │ │ │ ├── on-pause.html │ │ │ ├── on-resume.html │ │ │ ├── on-start.html │ │ │ ├── on-stop.html │ │ │ └── on-view-created.html │ │ ├── -i-common-player-out-video-switcher │ │ │ ├── get-current-video-id.html │ │ │ ├── index.html │ │ │ ├── switch-playable-params-subject.html │ │ │ ├── switch-video-id-subject.html │ │ │ └── switch-video.html │ │ ├── -i-common-player-system-u-i-event-dispatcher │ │ │ ├── index.html │ │ │ ├── on-back-pressed.html │ │ │ ├── on-configuration-changed.html │ │ │ ├── on-multi-window-mode-changed.html │ │ │ └── perform-window-focus-changed.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.commonplayer.gravitysensor │ │ ├── -gravity-sensor-handler │ │ │ ├── -companion │ │ │ │ ├── -t-a-g.html │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ └── set-gravity-sensor-enable.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.commonplayer.layer.control │ │ ├── -control-panel-config-element │ │ │ ├── -control-panel-config-element.html │ │ │ ├── display-orientation.html │ │ │ ├── index.html │ │ │ ├── layout-res.html │ │ │ └── screen-types.html │ │ ├── -control-panel-config │ │ │ ├── -control-panel-config.html │ │ │ ├── elements.html │ │ │ ├── index.html │ │ │ └── name.html │ │ ├── -i-control-widget │ │ │ ├── index.html │ │ │ ├── on-widget-active.html │ │ │ └── on-widget-inactive.html │ │ ├── -i-player-control-panel-container │ │ │ ├── hide.html │ │ │ ├── index.html │ │ │ ├── is-show.html │ │ │ └── show.html │ │ ├── -player-control-panel-container │ │ │ ├── -companion │ │ │ │ └── index.html │ │ │ ├── -control-panel-root │ │ │ │ ├── -control-panel-root.html │ │ │ │ ├── display-orientation.html │ │ │ │ ├── index.html │ │ │ │ ├── panel-type.html │ │ │ │ ├── root-view.html │ │ │ │ ├── screen-type.html │ │ │ │ └── widgets.html │ │ │ ├── get-view.html │ │ │ ├── hide.html │ │ │ ├── index.html │ │ │ ├── is-show.html │ │ │ ├── release.html │ │ │ ├── show.html │ │ │ └── switch-screen.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.commonplayer.layer.function │ │ ├── -base-function-widget │ │ │ ├── -base-function-widget.html │ │ │ ├── -configuration │ │ │ │ ├── different.html │ │ │ │ └── index.html │ │ │ ├── function-inset-config.html │ │ │ ├── function-widget-config.html │ │ │ ├── get-view.html │ │ │ ├── index.html │ │ │ ├── on-configuration-changed.html │ │ │ ├── on-new-layout-params.html │ │ │ ├── on-release.html │ │ │ ├── on-widget-dismiss.html │ │ │ ├── on-widget-show.html │ │ │ ├── tag.html │ │ │ └── token.html │ │ ├── -function-widget-config │ │ │ ├── -builder │ │ │ │ ├── -builder.html │ │ │ │ ├── build.html │ │ │ │ ├── change-orientation-disable-when-show.html │ │ │ │ ├── dismiss-when-activity-stop.html │ │ │ │ ├── dismiss-when-screen-type-change.html │ │ │ │ ├── dismiss-when-video-change.html │ │ │ │ ├── dismiss-when-video-completed.html │ │ │ │ ├── force-new-instance.html │ │ │ │ ├── index.html │ │ │ │ ├── launch-type.html │ │ │ │ ├── persistent.html │ │ │ │ └── remove-when-video-change.html │ │ │ ├── -companion │ │ │ │ ├── -f-l-a-g_-c-h-a-n-g-e_-o-r-i-e-n-t-a-t-i-o-n_-d-i-s-a-b-l-e_-w-h-e-n_-s-h-o-w.html │ │ │ │ ├── -f-l-a-g_-d-i-s-m-i-s-s_-a-c-t-i-v-i-t-y_-s-t-o-p.html │ │ │ │ ├── -f-l-a-g_-d-i-s-m-i-s-s_-c-h-a-n-g-e_-v-i-d-e-o.html │ │ │ │ ├── -f-l-a-g_-d-i-s-m-i-s-s_-s-c-r-e-e-n_-m-o-d-e_-c-h-a-n-g-e.html │ │ │ │ ├── -f-l-a-g_-d-i-s-m-i-s-s_-v-i-d-e-o_-c-o-m-p-l-e-t-e-d.html │ │ │ │ ├── -f-l-a-g_-p-e-r-s-i-s-t-e-n-t_-w-i-d-g-e-t.html │ │ │ │ ├── -f-l-a-g_-r-e-m-o-v-e_-c-h-a-n-g-e_-v-i-d-e-o.html │ │ │ │ └── index.html │ │ │ ├── -launch-type │ │ │ │ ├── -normal │ │ │ │ │ └── index.html │ │ │ │ ├── -singleton │ │ │ │ │ └── index.html │ │ │ │ ├── index.html │ │ │ │ └── type.html │ │ │ ├── flag.html │ │ │ ├── force-new-instance.html │ │ │ ├── index.html │ │ │ ├── launch-type.html │ │ │ └── to-string.html │ │ ├── -function-widget-inset-config │ │ │ ├── -function-widget-inset-config.html │ │ │ ├── content-bottom-padding.html │ │ │ ├── content-left-padding.html │ │ │ ├── content-right-padding.html │ │ │ ├── content-top-padding.html │ │ │ ├── index.html │ │ │ └── support.html │ │ ├── -function-widget-layout-params │ │ │ ├── -companion │ │ │ │ ├── -f-l-a-g_-t-o-u-c-h_-e-n-a-b-l-e.html │ │ │ │ ├── -f-l-a-g_-t-o-u-c-h_-o-u-t-s-i-d-e_-d-i-s-m-i-s-s.html │ │ │ │ ├── -n-o_-a-n-i-m-a-t-i-o-n.html │ │ │ │ ├── index.html │ │ │ │ └── layout-type-alias.html │ │ │ ├── -function-type │ │ │ │ ├── -d-i-a-l-o-g │ │ │ │ │ └── index.html │ │ │ │ ├── -e-m-b-e-d-d-e-d_-v-i-e-w │ │ │ │ │ └── index.html │ │ │ │ ├── -n-o-r-m-a-l │ │ │ │ │ └── index.html │ │ │ │ ├── -p-o-p-u-p_-w-i-n-d-o-w │ │ │ │ │ └── index.html │ │ │ │ ├── index.html │ │ │ │ └── type.html │ │ │ ├── -function-widget-layout-params.html │ │ │ ├── -layout-align-type │ │ │ │ ├── -b-o-t-t-o-m │ │ │ │ │ └── index.html │ │ │ │ ├── -c-e-n-t-e-r │ │ │ │ │ └── index.html │ │ │ │ ├── -l-e-f-t │ │ │ │ │ └── index.html │ │ │ │ ├── -r-i-g-h-t │ │ │ │ │ └── index.html │ │ │ │ ├── -t-o-p │ │ │ │ │ └── index.html │ │ │ │ ├── -u-n-d-e-f-i-n-e-d │ │ │ │ │ └── index.html │ │ │ │ ├── align.html │ │ │ │ └── index.html │ │ │ ├── background-drawable.html │ │ │ ├── bottom-margin.html │ │ │ ├── different.html │ │ │ ├── enter-anim.html │ │ │ ├── exit-anim.html │ │ │ ├── flag.html │ │ │ ├── function-type.html │ │ │ ├── height.html │ │ │ ├── index.html │ │ │ ├── layout-type.html │ │ │ ├── left-margin.html │ │ │ ├── right-margin.html │ │ │ ├── top-margin.html │ │ │ ├── touch-enable.html │ │ │ ├── touch-outside-dismiss.html │ │ │ └── width.html │ │ ├── -i-on-function-widget-visibility-change-listener │ │ │ ├── index.html │ │ │ ├── on-widget-dismiss.html │ │ │ └── on-widget-show.html │ │ ├── -player-function-container │ │ │ ├── -companion │ │ │ │ ├── -empty-layout-params.html │ │ │ │ ├── -t-a-g.html │ │ │ │ └── index.html │ │ │ ├── -function-widget-token │ │ │ │ ├── -function-widget-inset-config │ │ │ │ │ ├── -function-widget-inset-config.html │ │ │ │ │ ├── content-bottom-padding.html │ │ │ │ │ ├── content-left-padding.html │ │ │ │ │ ├── content-right-padding.html │ │ │ │ │ ├── content-top-padding.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── support.html │ │ │ │ ├── -function-widget-token.html │ │ │ │ ├── -widget-changed-listener │ │ │ │ │ ├── index.html │ │ │ │ │ ├── on-dismiss.html │ │ │ │ │ ├── on-removed.html │ │ │ │ │ └── on-show.html │ │ │ │ ├── clazz.html │ │ │ │ ├── id.html │ │ │ │ ├── index.html │ │ │ │ ├── is-removed.html │ │ │ │ ├── is-showing.html │ │ │ │ ├── to-string.html │ │ │ │ └── widget-changed-listener.html │ │ │ ├── add-on-function-widget-visibility-change-listener.html │ │ │ ├── get-view.html │ │ │ ├── hide-all-widget.html │ │ │ ├── hide-widget.html │ │ │ ├── index.html │ │ │ ├── on-back-pressed.html │ │ │ ├── release.html │ │ │ ├── remove-on-function-widget-visibility-change-listener.html │ │ │ ├── remove-widget.html │ │ │ ├── show-widget.html │ │ │ └── update-widget.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.commonplayer.layer.gesture.detector │ │ ├── -rotate-gesture-detector │ │ │ ├── -on-rotate-gesture-listener │ │ │ │ ├── index.html │ │ │ │ ├── on-rotate-begin.html │ │ │ │ ├── on-rotate-end.html │ │ │ │ └── on-rotate.html │ │ │ ├── -rotate-gesture-detector.html │ │ │ ├── -simple-rotate-gesture-listener │ │ │ │ ├── index.html │ │ │ │ ├── on-rotate-begin.html │ │ │ │ ├── on-rotate-end.html │ │ │ │ └── on-rotate.html │ │ │ ├── get-degree.html │ │ │ ├── index.html │ │ │ ├── is-in-progress.html │ │ │ └── on-touch-event.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.commonplayer.layer.gesture │ │ ├── -horizontal-scroll-listener │ │ │ ├── index.html │ │ │ ├── on-cancel.html │ │ │ ├── on-scroll-start.html │ │ │ ├── on-scroll-stop.html │ │ │ └── on-scroll.html │ │ ├── -i-on-resizable-gesture-listener │ │ │ ├── index.html │ │ │ ├── on-resizable-gesture-end.html │ │ │ └── on-resizable-gesture-start.html │ │ ├── -layer-inner-resizable-gesture-listener │ │ │ ├── index.html │ │ │ ├── on-down.html │ │ │ ├── on-fling.html │ │ │ ├── on-long-press.html │ │ │ ├── on-resizable-gesture-end.html │ │ │ ├── on-resizable-gesture-start.html │ │ │ ├── on-rotate-begin.html │ │ │ ├── on-rotate-end.html │ │ │ ├── on-rotate.html │ │ │ ├── on-scale-begin.html │ │ │ ├── on-scale-end.html │ │ │ ├── on-scale.html │ │ │ ├── on-scroll.html │ │ │ ├── on-show-press.html │ │ │ └── on-single-tap-up.html │ │ ├── -on-double-tap-listener │ │ │ ├── index.html │ │ │ └── on-double-tap.html │ │ ├── -on-down-listener │ │ │ ├── index.html │ │ │ └── on-down.html │ │ ├── -on-long-press-listener │ │ │ ├── index.html │ │ │ ├── on-long-press-end.html │ │ │ └── on-long-press.html │ │ ├── -on-single-tap-listener │ │ │ ├── index.html │ │ │ └── on-single-tap.html │ │ ├── -on-touch-listener │ │ │ ├── index.html │ │ │ └── on-touch.html │ │ ├── -on-two-finger-double-tap-listener │ │ │ ├── index.html │ │ │ └── on-two-finger-double-tap.html │ │ ├── -player-gesture-layer │ │ │ ├── add-on-double-tap-listener.html │ │ │ ├── add-on-down-listener.html │ │ │ ├── add-on-long-press-listener.html │ │ │ ├── add-on-single-tap-listener.html │ │ │ ├── add-on-two-finger-double-tap-listener.html │ │ │ ├── forbidden-inner-touch-event.html │ │ │ ├── forbidden-resize-gesture.html │ │ │ ├── get-gesture-height.html │ │ │ ├── get-gesture-width.html │ │ │ ├── get-view.html │ │ │ ├── index.html │ │ │ ├── is-resize-gesture-forbidden.html │ │ │ ├── remove-on-double-tap-listener.html │ │ │ ├── remove-on-down-listener.html │ │ │ ├── remove-on-long-press-listener.html │ │ │ ├── remove-on-single-tap-listener.html │ │ │ ├── remove-on-two-finger-double-tap-listener.html │ │ │ ├── set-horizontal-scroll-listener.html │ │ │ ├── set-on-touch-listener.html │ │ │ ├── set-resizable-gesture-listener.html │ │ │ ├── set-vertical-scroll-left-listener.html │ │ │ └── set-vertical-scroll-right-listener.html │ │ ├── -player-gesture-listener │ │ │ ├── -player-gesture-listener.html │ │ │ ├── cancel.html │ │ │ ├── index.html │ │ │ ├── on-double-tap.html │ │ │ ├── on-down.html │ │ │ ├── on-long-press.html │ │ │ ├── on-scroll.html │ │ │ ├── on-single-tap-confirmed.html │ │ │ ├── on-up.html │ │ │ ├── set-gesture-size.html │ │ │ └── set-touch-gesture-listener.html │ │ ├── -vertical-scroll-left-listener │ │ │ ├── index.html │ │ │ ├── on-cancel.html │ │ │ ├── on-scroll-start.html │ │ │ ├── on-scroll-stop.html │ │ │ └── on-scroll.html │ │ ├── -vertical-scroll-right-listener │ │ │ ├── index.html │ │ │ ├── on-cancel.html │ │ │ ├── on-scroll-start.html │ │ │ ├── on-scroll-stop.html │ │ │ └── on-scroll.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.commonplayer.layer.toast │ │ ├── -i-player-toast-container │ │ │ ├── dismiss-toast.html │ │ │ ├── index.html │ │ │ ├── refresh-toast.html │ │ │ ├── set-padding.html │ │ │ └── show-toast.html │ │ ├── -player-toast-config │ │ │ ├── -d-u-r-a-t-i-o-n_-f-o-r-e-v-e-r.html │ │ │ ├── -d-u-r-a-t-i-o-n_-n-o-n-e.html │ │ │ ├── -d-u-r-a-t-i-o-n_1.html │ │ │ ├── -d-u-r-a-t-i-o-n_10.html │ │ │ ├── -d-u-r-a-t-i-o-n_2.html │ │ │ ├── -d-u-r-a-t-i-o-n_3.html │ │ │ ├── -d-u-r-a-t-i-o-n_4.html │ │ │ ├── -d-u-r-a-t-i-o-n_5.html │ │ │ ├── -d-u-r-a-t-i-o-n_6.html │ │ │ ├── -d-u-r-a-t-i-o-n_7.html │ │ │ ├── -d-u-r-a-t-i-o-n_8.html │ │ │ ├── -d-u-r-a-t-i-o-n_9.html │ │ │ ├── -e-x-t-r-a_-a-c-t-i-o-n_-n-e-e-d_-c-l-o-s-e.html │ │ │ ├── -e-x-t-r-a_-a-c-t-i-o-n_-t-e-x-t.html │ │ │ ├── -e-x-t-r-a_-a-c-t-i-o-n_-t-e-x-t_-c-o-l-o-r_-r-e-s_-i-d.html │ │ │ ├── -e-x-t-r-a_-b-g_-d-r-a-w-a-b-l-e_-r-e-s_-i-d.html │ │ │ ├── -e-x-t-r-a_-b-g_-f-i-n-a-l_-d-r-a-w-a-b-l-e_-r-e-s_-i-d.html │ │ │ ├── -e-x-t-r-a_-d-a-n-m-a-k-u_-r-e-c-o-m-m-e-n-d-e-d.html │ │ │ ├── -e-x-t-r-a_-d-a-n-m-a-k-u_-r-e-m-o-t-e_-i-d.html │ │ │ ├── -e-x-t-r-a_-f-i-n-a-l_-a-c-t-i-o-n_-t-e-x-t_-c-o-l-o-r_-r-e-s_-i-d.html │ │ │ ├── -e-x-t-r-a_-f-r-o-n-t_-d-r-a-w-a-b-l-e_-r-e-s_-i-d.html │ │ │ ├── -e-x-t-r-a_-t-i-t-l-e.html │ │ │ ├── -e-x-t-r-a_-t-i-t-l-e_-b-o-l-d.html │ │ │ ├── -e-x-t-r-a_-t-i-t-l-e_-c-o-l-o-r.html │ │ │ ├── -e-x-t-r-a_-t-i-t-l-e_-s-i-z-e.html │ │ │ ├── -e-x-t-r-a_-t-o-a-s-t_-l-e-n-g-t-h.html │ │ │ ├── -l-e-v-e-l_-f-o-u-r-t-h.html │ │ │ ├── -l-e-v-e-l_-h-i-g-h-e-s-t.html │ │ │ ├── -l-e-v-e-l_-l-o-w-e-s-t.html │ │ │ ├── -l-e-v-e-l_-s-e-c-o-n-d.html │ │ │ ├── -l-e-v-e-l_-t-h-i-r-d.html │ │ │ ├── -l-o-c-a-t_-c-e-n-t-e-r.html │ │ │ ├── -l-o-c-a-t_-l-e-f-t_-s-i-d-e.html │ │ │ ├── -level │ │ │ │ └── index.html │ │ │ ├── -location │ │ │ │ └── index.html │ │ │ ├── -q-u-e-u-e_-i-n-s-e-r-t.html │ │ │ ├── -q-u-e-u-e_-r-e-f-r-e-s-h.html │ │ │ ├── -queue-type │ │ │ │ └── index.html │ │ │ ├── -t-y-p-e_-a-c-t-i-o-n.html │ │ │ ├── -t-y-p-e_-a-c-t-i-o-n_-a-n-i-m-a-t-i-o-n.html │ │ │ ├── -t-y-p-e_-c-u-s-t-o-m.html │ │ │ ├── -t-y-p-e_-e-n-d.html │ │ │ ├── -t-y-p-e_-n-o-r-m-a-l.html │ │ │ ├── -t-y-p-e_-s-t-a-r-t.html │ │ │ ├── -t-y-p-e_-s-y-s-t-e-m.html │ │ │ ├── -toast-duration │ │ │ │ └── index.html │ │ │ ├── -toast-item-type │ │ │ │ └── index.html │ │ │ ├── get-action-text.html │ │ │ ├── get-title-bold.html │ │ │ ├── get-title.html │ │ │ └── index.html │ │ ├── -player-toast-container │ │ │ ├── -companion │ │ │ │ └── index.html │ │ │ ├── dismiss-toast.html │ │ │ ├── get-view.html │ │ │ ├── index.html │ │ │ ├── refresh-toast.html │ │ │ ├── set-padding.html │ │ │ └── show-toast.html │ │ ├── -player-toast │ │ │ ├── -builder │ │ │ │ ├── -builder.html │ │ │ │ ├── build.html │ │ │ │ ├── duration.html │ │ │ │ ├── index.html │ │ │ │ ├── level.html │ │ │ │ ├── location.html │ │ │ │ ├── message-click-listener.html │ │ │ │ ├── queue-type.html │ │ │ │ ├── refresh-duration.html │ │ │ │ ├── set-custom-view.html │ │ │ │ ├── set-extra-boolean.html │ │ │ │ ├── set-extra-color-resource.html │ │ │ │ ├── set-extra-drawable-resource.html │ │ │ │ ├── set-extra-float.html │ │ │ │ ├── set-extra-int.html │ │ │ │ ├── set-extra-layout-id.html │ │ │ │ ├── set-extra-parcelable.html │ │ │ │ ├── set-extra-string.html │ │ │ │ └── toast-item-type.html │ │ │ ├── -companion │ │ │ │ ├── -t-a-g.html │ │ │ │ ├── generate-create-time-millis.html │ │ │ │ └── index.html │ │ │ ├── -message-click-listener │ │ │ │ ├── -companion │ │ │ │ │ ├── -c-l-i-c-k_-i-d1.html │ │ │ │ │ └── index.html │ │ │ │ ├── index.html │ │ │ │ ├── on-action.html │ │ │ │ └── on-dismiss.html │ │ │ ├── click-listener.html │ │ │ ├── clone.html │ │ │ ├── create-time.html │ │ │ ├── custom-view.html │ │ │ ├── duration.html │ │ │ ├── get-extra-boolean-value.html │ │ │ ├── get-extra-float-value.html │ │ │ ├── get-extra-int-value.html │ │ │ ├── get-extra-parcelable.html │ │ │ ├── get-extra-string.html │ │ │ ├── index.html │ │ │ ├── level.html │ │ │ ├── location.html │ │ │ ├── queue-type.html │ │ │ ├── refresh-duration.html │ │ │ ├── set-extra-boolean.html │ │ │ ├── set-extra-color-resource.html │ │ │ ├── set-extra-drawable-resource.html │ │ │ ├── set-extra-float.html │ │ │ ├── set-extra-int.html │ │ │ ├── set-extra-layout-id.html │ │ │ ├── set-extra-parcelable.html │ │ │ ├── set-extra-string.html │ │ │ └── toast-type.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.commonplayer.screen │ │ ├── -common-player-screen-handler │ │ │ ├── add-screen-changed-listener.html │ │ │ ├── get-current-screen-type.html │ │ │ ├── index.html │ │ │ ├── is-gravity-orientation-enable.html │ │ │ ├── remove-all-screen-changed-listeners.html │ │ │ ├── remove-screen-changed-listener.html │ │ │ └── switch-screen-type.html │ │ ├── -i-common-player-screen-changed-listener │ │ │ ├── index.html │ │ │ └── on-screen-type-changed.html │ │ ├── -i-common-player-screen-handler │ │ │ ├── add-screen-changed-listener.html │ │ │ ├── get-current-screen-type.html │ │ │ ├── index.html │ │ │ ├── remove-screen-changed-listener.html │ │ │ └── switch-screen-type.html │ │ ├── -i-window-inset-observer │ │ │ ├── index.html │ │ │ └── on-window-inset-changed.html │ │ ├── -screen-type │ │ │ ├── -f-u-l-l_-s-c-r-e-e-n │ │ │ │ └── index.html │ │ │ ├── -h-a-l-f_-s-c-r-e-e-n │ │ │ │ └── index.html │ │ │ ├── -n-o-n-e │ │ │ │ └── index.html │ │ │ ├── -r-e-v-e-r-s-e_-f-u-l-l_-s-c-r-e-e-n │ │ │ │ └── index.html │ │ │ └── index.html │ │ ├── -window-inset │ │ │ ├── -window-inset.html │ │ │ ├── bottom-padding.html │ │ │ ├── index.html │ │ │ ├── left-padding.html │ │ │ ├── right-padding.html │ │ │ └── top-padding.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.commonplayer.service │ │ ├── -i-common-player-environment-service-manager │ │ │ ├── get-player-service.html │ │ │ └── index.html │ │ ├── -i-player-service-manager │ │ │ ├── bind-service.html │ │ │ ├── index.html │ │ │ ├── release.html │ │ │ ├── start-service.html │ │ │ ├── stop-service.html │ │ │ └── unbind-service.html │ │ ├── -i-player-service-owner │ │ │ ├── index.html │ │ │ ├── name.html │ │ │ ├── service.html │ │ │ ├── start.html │ │ │ └── stop.html │ │ ├── -i-player-service │ │ │ ├── index.html │ │ │ ├── on-player-reset.html │ │ │ ├── on-start.html │ │ │ ├── on-stop.html │ │ │ └── service-config.html │ │ ├── -player-service-manager │ │ │ ├── -client │ │ │ │ ├── -client.html │ │ │ │ ├── index.html │ │ │ │ ├── on-player-service-stop.html │ │ │ │ └── service.html │ │ │ ├── -companion │ │ │ │ └── index.html │ │ │ ├── -player-service-manager.html │ │ │ ├── -service-config │ │ │ │ ├── -companion │ │ │ │ │ ├── index.html │ │ │ │ │ └── obtain.html │ │ │ │ ├── index.html │ │ │ │ └── is-persistent.html │ │ │ ├── -service-descriptor │ │ │ │ ├── -companion │ │ │ │ │ ├── index.html │ │ │ │ │ └── obtain.html │ │ │ │ ├── clazz.html │ │ │ │ ├── id.html │ │ │ │ ├── index.html │ │ │ │ └── to-string.html │ │ │ ├── bind-service.html │ │ │ ├── index.html │ │ │ ├── release.html │ │ │ ├── start-service.html │ │ │ ├── stop-service.html │ │ │ └── unbind-service.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.commonplayer.view │ │ ├── -fixed-width-text-view │ │ │ ├── -fixed-width-text-view.html │ │ │ ├── index.html │ │ │ ├── request-layout.html │ │ │ └── set-text.html │ │ └── index.html │ ├── com.qiniu.qplayer2ext.commonplayer │ │ ├── -common-player-config │ │ │ ├── -builder │ │ │ │ ├── -builder.html │ │ │ │ ├── add-control-panel.html │ │ │ │ ├── add-enviroment.html │ │ │ │ ├── add-service-owner.html │ │ │ │ ├── build.html │ │ │ │ ├── enable-control-panel.html │ │ │ │ ├── enable-function-widget.html │ │ │ │ ├── enable-gesture.html │ │ │ │ ├── enable-screen-render.html │ │ │ │ ├── enable-toast.html │ │ │ │ ├── index.html │ │ │ │ ├── set-author-id.html │ │ │ │ ├── set-blind-type.html │ │ │ │ ├── set-common-player-screen-changed-listener.html │ │ │ │ ├── set-context.html │ │ │ │ ├── set-decode-type.html │ │ │ │ ├── set-log-level.html │ │ │ │ ├── set-logic-provider.html │ │ │ │ ├── set-mirror-type.html │ │ │ │ ├── set-mute.html │ │ │ │ ├── set-player-data-source.html │ │ │ │ ├── set-render-ratio.html │ │ │ │ ├── set-root-u-i-contanier.html │ │ │ │ ├── set-rotation.html │ │ │ │ ├── set-s-e-i-enable.html │ │ │ │ ├── set-scale.html │ │ │ │ ├── set-seek-mode.html │ │ │ │ ├── set-so-path.html │ │ │ │ ├── set-speed.html │ │ │ │ ├── set-start-action.html │ │ │ │ └── set-subtitle-enable.html │ │ │ ├── -common-player-config.html │ │ │ ├── -common-player-core-config │ │ │ │ ├── -common-player-core-config.html │ │ │ │ ├── activity.html │ │ │ │ ├── angle.html │ │ │ │ ├── author-id.html │ │ │ │ ├── blind-type.html │ │ │ │ ├── common-player-screen-changed-listener.html │ │ │ │ ├── context.html │ │ │ │ ├── control-container-config.html │ │ │ │ ├── control-panel-enable.html │ │ │ │ ├── decode-type.html │ │ │ │ ├── enviroments.html │ │ │ │ ├── function-widget-enable.html │ │ │ │ ├── gesture-enable.html │ │ │ │ ├── index.html │ │ │ │ ├── log-level.html │ │ │ │ ├── logic-provider.html │ │ │ │ ├── mirror-type.html │ │ │ │ ├── mute.html │ │ │ │ ├── player-data-source.html │ │ │ │ ├── render-ratio.html │ │ │ │ ├── root-container.html │ │ │ │ ├── scale.html │ │ │ │ ├── screen-render-enable.html │ │ │ │ ├── screen-render-type.html │ │ │ │ ├── seek-mode.html │ │ │ │ ├── sei-enable.html │ │ │ │ ├── service-owners.html │ │ │ │ ├── so-path.html │ │ │ │ ├── speed.html │ │ │ │ ├── start-action.html │ │ │ │ ├── subtitle-enable.html │ │ │ │ └── toast-enable.html │ │ │ ├── -screen-render-type │ │ │ │ ├── -s-u-r-f-a-c-e_-v-i-e-w │ │ │ │ │ └── index.html │ │ │ │ ├── -t-e-x-t-u-r-e_-v-i-e-w │ │ │ │ │ └── index.html │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ └── player-core-config.html │ │ ├── -common-player-core │ │ │ ├── -common-player-core.html │ │ │ ├── bind-common-player-core.html │ │ │ ├── get-common-player-screen-handler.html │ │ │ ├── get-player-enviroment-service-manager.html │ │ │ ├── index.html │ │ │ ├── logic-provider.html │ │ │ ├── m-android-context.html │ │ │ ├── m-common-player-video-switcher.html │ │ │ ├── m-player-context.html │ │ │ ├── player-control-panel-container.html │ │ │ ├── player-data-source.html │ │ │ ├── player-function-widget-container.html │ │ │ ├── player-gesture-layer.html │ │ │ ├── player-toast-container.html │ │ │ └── release.html │ │ ├── -common-player │ │ │ ├── -common-player.html │ │ │ ├── -companion │ │ │ │ └── index.html │ │ │ ├── index.html │ │ │ ├── player-video-switcher.html │ │ │ └── release.html │ │ ├── -i-common-player-core-binder-proxy │ │ │ ├── bind-common-player-core.html │ │ │ └── index.html │ │ ├── -i-common-player-core-binder │ │ │ ├── bind-player-core.html │ │ │ └── index.html │ │ ├── -i-logic-provider │ │ │ └── index.html │ │ └── index.html │ └── package-list │ ├── scripts │ ├── clipboard.js │ ├── main.js │ ├── navigation-loader.js │ ├── pages.json │ ├── platform-content-handler.js │ ├── prism.js │ └── sourceset_dependencies.js │ └── styles │ ├── jetbrains-mono.css │ ├── logo-styles.css │ ├── main.css │ ├── prism.css │ └── style.css ├── Qplayer2Demo ├── .gitignore ├── .idea │ ├── .name │ ├── compiler.xml │ ├── jarRepositories.xml │ ├── kotlinc.xml │ └── vcs.xml ├── app │ ├── .gitignore │ ├── build.gradle │ ├── libs │ │ └── qndroid-miku-delivery-v1.1.2.jar │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── TODO.md │ │ ├── ic_qplayer2_launcher2-playstore.png │ │ ├── java │ │ └── com │ │ │ └── qiniu │ │ │ └── qplayer2 │ │ │ ├── application │ │ │ ├── QPlayerApplication.kt │ │ │ └── QPlayerApplicationContext.kt │ │ │ ├── common │ │ │ ├── system │ │ │ │ ├── FileUtils.kt │ │ │ │ ├── PermissionHelper.kt │ │ │ │ ├── RomUtils.java │ │ │ │ ├── SaveUtils.kt │ │ │ │ └── SystemProperties.java │ │ │ └── type │ │ │ │ ├── CharSequenceUtils.java │ │ │ │ ├── ObjectUtils.java │ │ │ │ └── StringUtils.java │ │ │ ├── logic │ │ │ ├── BasePlayerControlVM.kt │ │ │ ├── BasePlayerRenderVM.kt │ │ │ ├── PlayerBiteRateVM.kt │ │ │ ├── PlayerBufferingVM.kt │ │ │ ├── PlayerDownloadVM.kt │ │ │ ├── PlayerFPSVM.kt │ │ │ ├── PlayerFirstFrameVM.kt │ │ │ ├── PlayerPausePlayVM.kt │ │ │ ├── PlayerProgressVM.kt │ │ │ └── PlayerSettingVM.kt │ │ │ ├── repository │ │ │ ├── common │ │ │ │ └── SharedPerencesHelper.kt │ │ │ ├── setting │ │ │ │ └── PlayerSettingRespostory.kt │ │ │ └── shortvideo │ │ │ │ ├── ModelFactory.java │ │ │ │ ├── ShortVideoApiService.kt │ │ │ │ ├── UpgradeInfo.java │ │ │ │ └── VideoItem.java │ │ │ ├── tools │ │ │ ├── AudioFrame.kt │ │ │ ├── BaseFrame.kt │ │ │ ├── MediaEncoder.kt │ │ │ ├── MediaMuxerWrapper.kt │ │ │ ├── MediaRecord.kt │ │ │ ├── MediaType.kt │ │ │ └── VideoFrame.kt │ │ │ └── ui │ │ │ ├── common │ │ │ ├── notch │ │ │ │ ├── DefaultNotchScreenSupport.java │ │ │ │ ├── HwNotchScreenSupport.java │ │ │ │ ├── INotchScreenSupport.java │ │ │ │ ├── MeiZuNotchScreenSupport.java │ │ │ │ ├── MiNotchScreenSupport.java │ │ │ │ ├── NotchCompat.java │ │ │ │ ├── OnePLusNotchScreenSupport.java │ │ │ │ ├── OppoNotchScreenSupport.java │ │ │ │ ├── PNotchScreenSupport.java │ │ │ │ ├── SamsungNotchScreenSupport.java │ │ │ │ └── VivoNotchScreenSupport.java │ │ │ └── statusbar │ │ │ │ └── StatusBarCompat.java │ │ │ ├── page │ │ │ ├── doubleplayer │ │ │ │ └── DoublePlayerActivity.kt │ │ │ ├── longvideo │ │ │ │ ├── LongCommonPlayerScreenChangedListener.kt │ │ │ │ ├── LongControlPanelType.kt │ │ │ │ ├── LongEnviromentType.kt │ │ │ │ ├── LongLogicProvider.kt │ │ │ │ ├── LongPlayableParams.kt │ │ │ │ ├── LongPlayerDataSourceFactory.kt │ │ │ │ ├── LongPlayerEnviroment.kt │ │ │ │ ├── LongVideoActivity.kt │ │ │ │ ├── LongVideoParams.kt │ │ │ │ └── service │ │ │ │ │ ├── ServiceOwnerType.kt │ │ │ │ │ ├── buffering │ │ │ │ │ ├── IPlayerBufferingService.kt │ │ │ │ │ ├── PlayerBufferingService.kt │ │ │ │ │ └── PlayerBufferingServiceOwner.kt │ │ │ │ │ ├── controlpanelcontainervisible │ │ │ │ │ ├── IPlayerControlPanelContainerVisibleService.kt │ │ │ │ │ ├── PlayerControlPanelContainerVisibleService.kt │ │ │ │ │ └── PlayerControlPanelContainerVisibleServiceOwner.kt │ │ │ │ │ ├── network │ │ │ │ │ ├── IPlayerNetworkService.kt │ │ │ │ │ ├── PlayerNetworkService.kt │ │ │ │ │ └── PlayerNetworkServiceOwner.kt │ │ │ │ │ ├── panorama │ │ │ │ │ ├── IPlayerPanoramaTouchSerivice.kt │ │ │ │ │ ├── PanoramaOnResizableGestureListener.java │ │ │ │ │ ├── PlayerPanoramaTouchSerivice.kt │ │ │ │ │ └── PlayerPanoramaTouchSeriviceOwner.kt │ │ │ │ │ ├── shoot │ │ │ │ │ ├── IPlayerCaptureService.kt │ │ │ │ │ ├── PlayerCaptureService.kt │ │ │ │ │ └── PlayerShootVideoServiceOwner.kt │ │ │ │ │ ├── subtitle │ │ │ │ │ ├── IPlayerSubtitleService.kt │ │ │ │ │ ├── PlayerSubtitleService.kt │ │ │ │ │ └── PlayerSubtitleServiceOwner.kt │ │ │ │ │ ├── toast │ │ │ │ │ ├── IPlayerToastService.kt │ │ │ │ │ ├── PlayerToastService.kt │ │ │ │ │ └── PlayerToastServiceOwner.kt │ │ │ │ │ ├── videoquality │ │ │ │ │ ├── IPlayerVideoQualityService.kt │ │ │ │ │ └── PlayerVideoQualityService.kt │ │ │ │ │ └── volume │ │ │ │ │ ├── IPlayerVolumeService.kt │ │ │ │ │ ├── PlayerVolumeService.kt │ │ │ │ │ └── PlayerVolumeServiceOwner.kt │ │ │ ├── main │ │ │ │ └── MainActivity.kt │ │ │ ├── setting │ │ │ │ └── SettingActivity.kt │ │ │ ├── shortvideoV2 │ │ │ │ ├── IAllPlayerStateEndListener.kt │ │ │ │ ├── IShortVideoPlayerViewCacheRecycler.kt │ │ │ │ ├── MediaItemContextManager.kt │ │ │ │ ├── MikuClientManager.java │ │ │ │ ├── PlayItem.kt │ │ │ │ ├── PlayItemManager.kt │ │ │ │ ├── ShortVideoActivityV2.kt │ │ │ │ ├── ShortVideoHolderV2.kt │ │ │ │ ├── ShortVideoListAdapterV2.kt │ │ │ │ ├── ShortVideoPlayerViewCache.kt │ │ │ │ └── SurfacePlayerViewManager.kt │ │ │ └── simplelongvideo │ │ │ │ ├── IVideoHolderClickListener.kt │ │ │ │ ├── SimpleLongVideoActivity.kt │ │ │ │ ├── VideoHolder.kt │ │ │ │ └── VideoListAdapter.kt │ │ │ └── widget │ │ │ ├── PlayerBiteRateTextWidget.kt │ │ │ ├── PlayerBufferingWidget.kt │ │ │ ├── PlayerDownloadTextWidget.kt │ │ │ ├── PlayerFPSTextWidget.kt │ │ │ ├── PlayerFirstFrameWidget.kt │ │ │ ├── PlayerFullScreenPlayClickWidget.kt │ │ │ ├── PlayerFullScreenWidget.kt │ │ │ ├── PlayerPausePlayWidget.kt │ │ │ ├── PlayerPlayWidget.kt │ │ │ ├── PlayerProgressTextWidget.kt │ │ │ ├── PlayerSeekWidget.kt │ │ │ └── commonplayer │ │ │ ├── controlwidget │ │ │ ├── CommonPlayerBackWidget.kt │ │ │ ├── CommonPlayerBiteRateTextWidget.kt │ │ │ ├── CommonPlayerCaptureWidget.kt │ │ │ ├── CommonPlayerDownloadTextWidget.kt │ │ │ ├── CommonPlayerFPSTextWidget.kt │ │ │ ├── CommonPlayerFullScreenWidget.kt │ │ │ ├── CommonPlayerInsetControllerWidget.kt │ │ │ ├── CommonPlayerMoreSettingWidget.kt │ │ │ ├── CommonPlayerMuteWidget.kt │ │ │ ├── CommonPlayerPausePlayWidget.kt │ │ │ ├── CommonPlayerProgressTextWidget.kt │ │ │ ├── CommonPlayerSeekWidget.kt │ │ │ ├── CommonPlayerSelectQualityWidget.kt │ │ │ ├── CommonPlayerSelectSpeedWidget.kt │ │ │ ├── CommonPlayerSelectVideoWidget.kt │ │ │ ├── CommonPlayerStopWidget.kt │ │ │ └── CommonPlayerSubtitleWidget.kt │ │ │ └── functionwidget │ │ │ ├── buffering │ │ │ └── BufferingFunctionWidget.kt │ │ │ ├── error │ │ │ └── ErrorFunctionWidget.kt │ │ │ ├── setting │ │ │ └── SettingFunctionWidget.kt │ │ │ ├── shoot │ │ │ └── PlayerShootVideoFunctionWidget.kt │ │ │ ├── speed │ │ │ ├── SpeedFunctionWidget.kt │ │ │ └── SpeedListAdapter.kt │ │ │ ├── subtitle │ │ │ ├── SubtitleFunctionWidget.kt │ │ │ ├── SubtitleListAdapter.kt │ │ │ └── SubtitleListFunctionWidget.kt │ │ │ ├── videolist │ │ │ ├── VideoListAdapter.kt │ │ │ └── VideoListFunctionWidget.kt │ │ │ ├── videoquality │ │ │ ├── VideoQualityFunctionWidget.kt │ │ │ └── VideoQualityListAdapter.kt │ │ │ └── volume │ │ │ └── PlayerVolumeFunctionWidget.kt │ │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── bplayer_seek_pink__scrubber_horizontal.xml │ │ ├── ic_launcher_background.xml │ │ ├── nike.png │ │ ├── qmedia_ic_back.png │ │ ├── qmedia_ic_new_vod_back_normal.png │ │ ├── qmedia_ic_picture_bold.xml │ │ ├── qmedia_ic_player_back_vector.xml │ │ ├── qmedia_ic_player_fullscreen_vector.xml │ │ ├── qmedia_ic_player_replay_vector.xml │ │ ├── qmedia_ic_player_setting_vector.xml │ │ ├── qmedia_ic_qcode.png │ │ ├── qmedia_ic_vod_add.png │ │ ├── qmedia_ic_vod_search.png │ │ ├── qmedia_ic_volume_mute.xml │ │ ├── qmedia_ic_volume_unmute.xml │ │ ├── qmedia_player_pause_selector.xml │ │ ├── qmedia_player_pause_vector.xml │ │ ├── qmedia_player_play_pause_level_list.xml │ │ ├── qmedia_player_play_selector.xml │ │ ├── qmedia_player_play_vector.xml │ │ ├── qmedia_player_replay_selector.xml │ │ ├── qmedia_player_roundrect_black_alpha30_shape.xml │ │ ├── qmedia_player_seek_bar_drawable.xml │ │ ├── qmedia_player_selector_panel_text_purple.xml │ │ ├── qmedia_player_stop_vector.xml │ │ └── qmedia_question_link.png │ │ ├── layout │ │ ├── activity_double_player.xml │ │ ├── activity_long_video.xml │ │ ├── activity_main.xml │ │ ├── activity_setting.xml │ │ ├── activity_short_video.xml │ │ ├── activity_short_video2.xml │ │ ├── activity_simple_long_video.xml │ │ ├── control_panel_fullscreen_landscape_normal.xml │ │ ├── control_panel_halfscreen_landscape_normal.xml │ │ ├── function_audio_volume.xml │ │ ├── function_buffering.xml │ │ ├── function_error.xml │ │ ├── function_setting.xml │ │ ├── function_shoot_video.xml │ │ ├── function_speed_list.xml │ │ ├── function_subtitle.xml │ │ ├── function_subtitle_list.xml │ │ ├── function_video_list.xml │ │ ├── function_video_quality_list.xml │ │ ├── holder_common_player_list_item.xml │ │ ├── holder_common_player_video_list_item.xml │ │ ├── holder_short_video.xml │ │ ├── holder_video_item.xml │ │ ├── player_controller_half_screen.xml │ │ └── player_controller_short_video_screen.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_qplayer2_launcher2.xml │ │ └── ic_qplayer2_launcher2_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_qplayer2_launcher2.png │ │ ├── ic_qplayer2_launcher2_foreground.png │ │ └── ic_qplayer2_launcher2_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_qplayer2_launcher2.png │ │ ├── ic_qplayer2_launcher2_foreground.png │ │ └── ic_qplayer2_launcher2_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_qplayer2_launcher2.png │ │ ├── ic_qplayer2_launcher2_foreground.png │ │ └── ic_qplayer2_launcher2_round.png │ │ ├── mipmap-xxhdpi │ │ ├── common_player_control_panel_shape_shadow_bottom.png │ │ ├── common_player_control_panel_shape_shadow_top.png │ │ ├── ic_qplayer2_launcher2.png │ │ ├── ic_qplayer2_launcher2_foreground.png │ │ └── ic_qplayer2_launcher2_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_qplayer2_launcher2.png │ │ ├── ic_qplayer2_launcher2_foreground.png │ │ ├── ic_qplayer2_launcher2_round.png │ │ └── play.png │ │ ├── raw │ │ ├── nike.mp4 │ │ └── qiniu_2023_1080p.mp4 │ │ ├── values-night │ │ └── themes.xml │ │ ├── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── ic_qplayer2_launcher2_background.xml │ │ ├── strings.xml │ │ ├── styles.xml │ │ └── themes.xml │ │ └── xml │ │ └── network_security_config.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── key └── settings.gradle ├── README.md └── ReleaseNote ├── ReleaseNote-0.0.7.md ├── ReleaseNote-1.0.3.md ├── ReleaseNote-1.1.4.md ├── ReleaseNote-1.2.0.md ├── ReleaseNote-1.2.1.md ├── ReleaseNote-1.2.2.md ├── ReleaseNote-1.2.3.md ├── ReleaseNote-1.2.4.md ├── ReleaseNote-1.3.0.md ├── ReleaseNote-1.3.1.md ├── ReleaseNote-1.3.2.md ├── ReleaseNote-1.3.4.md ├── ReleaseNote-1.4.0.md ├── ReleaseNote-1.4.1.md ├── ReleaseNote-1.4.3.md └── ReleaseNote-1.5.0.md /Document/qplayer2-core/html/images/anchor-copy-button.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Document/qplayer2-core/html/images/arrow_down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Document/qplayer2-core/html/images/copy-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Document/qplayer2-core/html/images/copy-successful-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Document/qplayer2-core/html/images/footer-go-to-link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Document/qplayer2-core/html/images/go-to-top-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Document/qplayer2-core/html/images/logo-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Document/qplayer2-core/html/images/theme-toggle.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /Document/qplayer2-core/html/scripts/clipboard.js: -------------------------------------------------------------------------------- 1 | window.addEventListener('load', () => { 2 | document.querySelectorAll('span.copy-icon').forEach(element => { 3 | element.addEventListener('click', (el) => copyElementsContentToClipboard(element)); 4 | }) 5 | 6 | document.querySelectorAll('span.anchor-icon').forEach(element => { 7 | element.addEventListener('click', (el) => { 8 | if(element.hasAttribute('pointing-to')){ 9 | const location = hrefWithoutCurrentlyUsedAnchor() + '#' + element.getAttribute('pointing-to') 10 | copyTextToClipboard(element, location) 11 | } 12 | }); 13 | }) 14 | }) 15 | 16 | const copyElementsContentToClipboard = (element) => { 17 | const selection = window.getSelection(); 18 | const range = document.createRange(); 19 | range.selectNodeContents(element.parentNode.parentNode); 20 | selection.removeAllRanges(); 21 | selection.addRange(range); 22 | 23 | copyAndShowPopup(element, () => selection.removeAllRanges()) 24 | } 25 | 26 | const copyTextToClipboard = (element, text) => { 27 | var textarea = document.createElement("textarea"); 28 | textarea.textContent = text; 29 | textarea.style.position = "fixed"; 30 | document.body.appendChild(textarea); 31 | textarea.select(); 32 | 33 | copyAndShowPopup(element, () => document.body.removeChild(textarea)) 34 | } 35 | 36 | const copyAndShowPopup = (element, after) => { 37 | try { 38 | document.execCommand('copy'); 39 | element.nextElementSibling.classList.add('active-popup'); 40 | setTimeout(() => { 41 | element.nextElementSibling.classList.remove('active-popup'); 42 | }, 1200); 43 | } catch (e) { 44 | console.error('Failed to write to clipboard:', e) 45 | } 46 | finally { 47 | if(after) after() 48 | } 49 | } 50 | 51 | const hrefWithoutCurrentlyUsedAnchor = () => window.location.href.split('#')[0] 52 | 53 | -------------------------------------------------------------------------------- /Document/qplayer2-core/html/scripts/navigation-loader.js: -------------------------------------------------------------------------------- 1 | navigationPageText = fetch(pathToRoot + "navigation.html").then(response => response.text()) 2 | 3 | displayNavigationFromPage = () => { 4 | navigationPageText.then(data => { 5 | document.getElementById("sideMenu").innerHTML = data; 6 | }).then(() => { 7 | document.querySelectorAll(".overview > a").forEach(link => { 8 | link.setAttribute("href", pathToRoot + link.getAttribute("href")); 9 | }) 10 | }).then(() => { 11 | document.querySelectorAll(".sideMenuPart").forEach(nav => { 12 | if (!nav.classList.contains("hidden")) 13 | nav.classList.add("hidden") 14 | }) 15 | }).then(() => { 16 | revealNavigationForCurrentPage() 17 | }) 18 | document.querySelectorAll('.footer a[href^="#"]').forEach(anchor => { 19 | anchor.addEventListener('click', function (e) { 20 | e.preventDefault(); 21 | document.querySelector(this.getAttribute('href')).scrollIntoView({ 22 | behavior: 'smooth' 23 | }); 24 | }); 25 | }); 26 | } 27 | 28 | revealNavigationForCurrentPage = () => { 29 | let pageId = document.getElementById("content").attributes["pageIds"].value.toString(); 30 | let parts = document.querySelectorAll(".sideMenuPart"); 31 | let found = 0; 32 | do { 33 | parts.forEach(part => { 34 | if (part.attributes['pageId'].value.indexOf(pageId) !== -1 && found === 0) { 35 | found = 1; 36 | if (part.classList.contains("hidden")) { 37 | part.classList.remove("hidden"); 38 | part.setAttribute('data-active', ""); 39 | } 40 | revealParents(part) 41 | } 42 | }); 43 | pageId = pageId.substring(0, pageId.lastIndexOf("/")) 44 | } while (pageId.indexOf("/") !== -1 && found === 0) 45 | }; 46 | revealParents = (part) => { 47 | if (part.classList.contains("sideMenuPart")) { 48 | if (part.classList.contains("hidden")) 49 | part.classList.remove("hidden"); 50 | revealParents(part.parentNode) 51 | } 52 | }; 53 | 54 | /* 55 | This is a work-around for safari being IE of our times. 56 | It doesn't fire a DOMContentLoaded, presumabely because eventListener is added after it wants to do it 57 | */ 58 | if (document.readyState == 'loading') { 59 | window.addEventListener('DOMContentLoaded', () => { 60 | displayNavigationFromPage() 61 | }) 62 | } else { 63 | displayNavigationFromPage() 64 | } -------------------------------------------------------------------------------- /Document/qplayer2-core/html/scripts/sourceset_dependencies.js: -------------------------------------------------------------------------------- 1 | sourceset_dependencies='{":qplayer2-core:dokkaHtml/androidTestRelease":[],":qplayer2-core:dokkaHtml/debug":[],":qplayer2-core:dokkaHtml/main":[],":qplayer2-core:dokkaHtml/release":[],":qplayer2-core:dokkaHtml/testFixtures":[],":qplayer2-core:dokkaHtml/testFixturesDebug":[],":qplayer2-core:dokkaHtml/testFixturesRelease":[]}' 2 | -------------------------------------------------------------------------------- /Document/qplayer2-core/html/styles/jetbrains-mono.css: -------------------------------------------------------------------------------- 1 | @font-face{ 2 | font-family: 'JetBrains Mono'; 3 | src: url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/web/JetBrainsMono-Regular.eot') format('embedded-opentype'), 4 | url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/webfonts/JetBrainsMono-Regular.woff2') format('woff2'), 5 | url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/ttf/JetBrainsMono-Regular.ttf') format('truetype'); 6 | font-weight: normal; 7 | font-style: normal; 8 | } 9 | 10 | @font-face{ 11 | font-family: 'JetBrains Mono'; 12 | src: url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/web/JetBrainsMono-Bold.eot') format('embedded-opentype'), 13 | url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/webfonts/JetBrainsMono-Bold.woff2') format('woff2'), 14 | url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/ttf/JetBrainsMono-Bold.ttf') format('truetype'); 15 | font-weight: bold; 16 | font-style: bold; 17 | } -------------------------------------------------------------------------------- /Document/qplayer2-core/html/styles/logo-styles.css: -------------------------------------------------------------------------------- 1 | .library-name a { 2 | position: relative; 3 | margin-left: 55px; 4 | } 5 | 6 | .library-name a::before { 7 | content: ''; 8 | background: url("../images/logo-icon.svg") center no-repeat; 9 | background-size: contain; 10 | position: absolute; 11 | width: 50px; 12 | height: 50px; 13 | top: -18px; 14 | left: -55px; 15 | } -------------------------------------------------------------------------------- /Document/qplayer2-core/html/styles/prism.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --keyword-color: #07a; 3 | --property-color: #905; 4 | --function-color: #DD4A68; 5 | } 6 | 7 | :root.theme-dark { 8 | --keyword-color: #cc7832; 9 | --property-color: #9876aa; 10 | --function-color: #ffc66d; 11 | } 12 | 13 | code .token { 14 | white-space: pre; 15 | } 16 | 17 | /* PrismJS 1.24.1 18 | https://prismjs.com/download.html#themes=prism&languages=clike+java+javadoclike+kotlin&plugins=keep-markup */ 19 | /** 20 | * prism.js default theme for JavaScript, CSS and HTML 21 | * Based on dabblet (http://dabblet.com) 22 | * @author Lea Verou 23 | */ 24 | 25 | .token.comment, 26 | .token.prolog, 27 | .token.doctype, 28 | .token.cdata { 29 | color: slategray; 30 | } 31 | 32 | .token.punctuation { 33 | color: #999; 34 | } 35 | 36 | .token.namespace { 37 | opacity: .7; 38 | } 39 | 40 | .token.property, 41 | .token.tag, 42 | .token.boolean, 43 | .token.number, 44 | .token.constant, 45 | .token.symbol, 46 | .token.deleted { 47 | color: var(--property-color); 48 | } 49 | 50 | .token.selector, 51 | .token.attr-name, 52 | .token.string, 53 | .token.char, 54 | .token.builtin, 55 | .token.annotation, 56 | .token.inserted { 57 | color: #690; 58 | } 59 | 60 | .token.operator, 61 | .token.entity, 62 | .token.url, 63 | .language-css .token.string, 64 | .style .token.string { 65 | color: #9a6e3a; 66 | /* This background color was intended by the author of this theme. */ 67 | /*background: hsla(0, 0%, 100%, .5);*/ 68 | } 69 | 70 | .token.atrule, 71 | .token.attr-value, 72 | .token.keyword { 73 | color: var(--keyword-color); 74 | font-size: inherit; /* to override .keyword */ 75 | } 76 | 77 | .token.function, 78 | .token.class-name { 79 | color: var(--function-color); 80 | } 81 | 82 | .token.regex, 83 | .token.important, 84 | .token.variable { 85 | color: #e90; 86 | } 87 | 88 | .token.important, 89 | .token.bold { 90 | font-weight: bold; 91 | } 92 | .token.italic { 93 | font-style: italic; 94 | } 95 | 96 | .token.entity { 97 | cursor: help; 98 | } 99 | 100 | .annotation,.control,.field,.filename,.keyword,.menupath,.property,.string,.value { 101 | color: #27282c; 102 | font-weight: 700; 103 | } -------------------------------------------------------------------------------- /Document/qplayer2-ext/html/images/anchor-copy-button.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Document/qplayer2-ext/html/images/arrow_down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Document/qplayer2-ext/html/images/copy-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Document/qplayer2-ext/html/images/copy-successful-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Document/qplayer2-ext/html/images/footer-go-to-link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Document/qplayer2-ext/html/images/go-to-top-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Document/qplayer2-ext/html/images/logo-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Document/qplayer2-ext/html/images/theme-toggle.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /Document/qplayer2-ext/html/scripts/clipboard.js: -------------------------------------------------------------------------------- 1 | window.addEventListener('load', () => { 2 | document.querySelectorAll('span.copy-icon').forEach(element => { 3 | element.addEventListener('click', (el) => copyElementsContentToClipboard(element)); 4 | }) 5 | 6 | document.querySelectorAll('span.anchor-icon').forEach(element => { 7 | element.addEventListener('click', (el) => { 8 | if(element.hasAttribute('pointing-to')){ 9 | const location = hrefWithoutCurrentlyUsedAnchor() + '#' + element.getAttribute('pointing-to') 10 | copyTextToClipboard(element, location) 11 | } 12 | }); 13 | }) 14 | }) 15 | 16 | const copyElementsContentToClipboard = (element) => { 17 | const selection = window.getSelection(); 18 | const range = document.createRange(); 19 | range.selectNodeContents(element.parentNode.parentNode); 20 | selection.removeAllRanges(); 21 | selection.addRange(range); 22 | 23 | copyAndShowPopup(element, () => selection.removeAllRanges()) 24 | } 25 | 26 | const copyTextToClipboard = (element, text) => { 27 | var textarea = document.createElement("textarea"); 28 | textarea.textContent = text; 29 | textarea.style.position = "fixed"; 30 | document.body.appendChild(textarea); 31 | textarea.select(); 32 | 33 | copyAndShowPopup(element, () => document.body.removeChild(textarea)) 34 | } 35 | 36 | const copyAndShowPopup = (element, after) => { 37 | try { 38 | document.execCommand('copy'); 39 | element.nextElementSibling.classList.add('active-popup'); 40 | setTimeout(() => { 41 | element.nextElementSibling.classList.remove('active-popup'); 42 | }, 1200); 43 | } catch (e) { 44 | console.error('Failed to write to clipboard:', e) 45 | } 46 | finally { 47 | if(after) after() 48 | } 49 | } 50 | 51 | const hrefWithoutCurrentlyUsedAnchor = () => window.location.href.split('#')[0] 52 | 53 | -------------------------------------------------------------------------------- /Document/qplayer2-ext/html/scripts/navigation-loader.js: -------------------------------------------------------------------------------- 1 | navigationPageText = fetch(pathToRoot + "navigation.html").then(response => response.text()) 2 | 3 | displayNavigationFromPage = () => { 4 | navigationPageText.then(data => { 5 | document.getElementById("sideMenu").innerHTML = data; 6 | }).then(() => { 7 | document.querySelectorAll(".overview > a").forEach(link => { 8 | link.setAttribute("href", pathToRoot + link.getAttribute("href")); 9 | }) 10 | }).then(() => { 11 | document.querySelectorAll(".sideMenuPart").forEach(nav => { 12 | if (!nav.classList.contains("hidden")) 13 | nav.classList.add("hidden") 14 | }) 15 | }).then(() => { 16 | revealNavigationForCurrentPage() 17 | }) 18 | document.querySelectorAll('.footer a[href^="#"]').forEach(anchor => { 19 | anchor.addEventListener('click', function (e) { 20 | e.preventDefault(); 21 | document.querySelector(this.getAttribute('href')).scrollIntoView({ 22 | behavior: 'smooth' 23 | }); 24 | }); 25 | }); 26 | } 27 | 28 | revealNavigationForCurrentPage = () => { 29 | let pageId = document.getElementById("content").attributes["pageIds"].value.toString(); 30 | let parts = document.querySelectorAll(".sideMenuPart"); 31 | let found = 0; 32 | do { 33 | parts.forEach(part => { 34 | if (part.attributes['pageId'].value.indexOf(pageId) !== -1 && found === 0) { 35 | found = 1; 36 | if (part.classList.contains("hidden")) { 37 | part.classList.remove("hidden"); 38 | part.setAttribute('data-active', ""); 39 | } 40 | revealParents(part) 41 | } 42 | }); 43 | pageId = pageId.substring(0, pageId.lastIndexOf("/")) 44 | } while (pageId.indexOf("/") !== -1 && found === 0) 45 | }; 46 | revealParents = (part) => { 47 | if (part.classList.contains("sideMenuPart")) { 48 | if (part.classList.contains("hidden")) 49 | part.classList.remove("hidden"); 50 | revealParents(part.parentNode) 51 | } 52 | }; 53 | 54 | /* 55 | This is a work-around for safari being IE of our times. 56 | It doesn't fire a DOMContentLoaded, presumabely because eventListener is added after it wants to do it 57 | */ 58 | if (document.readyState == 'loading') { 59 | window.addEventListener('DOMContentLoaded', () => { 60 | displayNavigationFromPage() 61 | }) 62 | } else { 63 | displayNavigationFromPage() 64 | } -------------------------------------------------------------------------------- /Document/qplayer2-ext/html/scripts/sourceset_dependencies.js: -------------------------------------------------------------------------------- 1 | sourceset_dependencies='{":qplayer2-ext:dokkaHtml/androidTestRelease":[],":qplayer2-ext:dokkaHtml/debug":[],":qplayer2-ext:dokkaHtml/main":[],":qplayer2-ext:dokkaHtml/release":[],":qplayer2-ext:dokkaHtml/testFixtures":[],":qplayer2-ext:dokkaHtml/testFixturesDebug":[],":qplayer2-ext:dokkaHtml/testFixturesRelease":[]}' 2 | -------------------------------------------------------------------------------- /Document/qplayer2-ext/html/styles/jetbrains-mono.css: -------------------------------------------------------------------------------- 1 | @font-face{ 2 | font-family: 'JetBrains Mono'; 3 | src: url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/web/JetBrainsMono-Regular.eot') format('embedded-opentype'), 4 | url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/webfonts/JetBrainsMono-Regular.woff2') format('woff2'), 5 | url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/ttf/JetBrainsMono-Regular.ttf') format('truetype'); 6 | font-weight: normal; 7 | font-style: normal; 8 | } 9 | 10 | @font-face{ 11 | font-family: 'JetBrains Mono'; 12 | src: url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/web/JetBrainsMono-Bold.eot') format('embedded-opentype'), 13 | url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/webfonts/JetBrainsMono-Bold.woff2') format('woff2'), 14 | url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/ttf/JetBrainsMono-Bold.ttf') format('truetype'); 15 | font-weight: bold; 16 | font-style: bold; 17 | } -------------------------------------------------------------------------------- /Document/qplayer2-ext/html/styles/logo-styles.css: -------------------------------------------------------------------------------- 1 | .library-name a { 2 | position: relative; 3 | margin-left: 55px; 4 | } 5 | 6 | .library-name a::before { 7 | content: ''; 8 | background: url("../images/logo-icon.svg") center no-repeat; 9 | background-size: contain; 10 | position: absolute; 11 | width: 50px; 12 | height: 50px; 13 | top: -18px; 14 | left: -55px; 15 | } -------------------------------------------------------------------------------- /Document/qplayer2-ext/html/styles/prism.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --keyword-color: #07a; 3 | --property-color: #905; 4 | --function-color: #DD4A68; 5 | } 6 | 7 | :root.theme-dark { 8 | --keyword-color: #cc7832; 9 | --property-color: #9876aa; 10 | --function-color: #ffc66d; 11 | } 12 | 13 | code .token { 14 | white-space: pre; 15 | } 16 | 17 | /* PrismJS 1.24.1 18 | https://prismjs.com/download.html#themes=prism&languages=clike+java+javadoclike+kotlin&plugins=keep-markup */ 19 | /** 20 | * prism.js default theme for JavaScript, CSS and HTML 21 | * Based on dabblet (http://dabblet.com) 22 | * @author Lea Verou 23 | */ 24 | 25 | .token.comment, 26 | .token.prolog, 27 | .token.doctype, 28 | .token.cdata { 29 | color: slategray; 30 | } 31 | 32 | .token.punctuation { 33 | color: #999; 34 | } 35 | 36 | .token.namespace { 37 | opacity: .7; 38 | } 39 | 40 | .token.property, 41 | .token.tag, 42 | .token.boolean, 43 | .token.number, 44 | .token.constant, 45 | .token.symbol, 46 | .token.deleted { 47 | color: var(--property-color); 48 | } 49 | 50 | .token.selector, 51 | .token.attr-name, 52 | .token.string, 53 | .token.char, 54 | .token.builtin, 55 | .token.annotation, 56 | .token.inserted { 57 | color: #690; 58 | } 59 | 60 | .token.operator, 61 | .token.entity, 62 | .token.url, 63 | .language-css .token.string, 64 | .style .token.string { 65 | color: #9a6e3a; 66 | /* This background color was intended by the author of this theme. */ 67 | /*background: hsla(0, 0%, 100%, .5);*/ 68 | } 69 | 70 | .token.atrule, 71 | .token.attr-value, 72 | .token.keyword { 73 | color: var(--keyword-color); 74 | font-size: inherit; /* to override .keyword */ 75 | } 76 | 77 | .token.function, 78 | .token.class-name { 79 | color: var(--function-color); 80 | } 81 | 82 | .token.regex, 83 | .token.important, 84 | .token.variable { 85 | color: #e90; 86 | } 87 | 88 | .token.important, 89 | .token.bold { 90 | font-weight: bold; 91 | } 92 | .token.italic { 93 | font-style: italic; 94 | } 95 | 96 | .token.entity { 97 | cursor: help; 98 | } 99 | 100 | .annotation,.control,.field,.filename,.keyword,.menupath,.property,.string,.value { 101 | color: #27282c; 102 | font-weight: 700; 103 | } -------------------------------------------------------------------------------- /Qplayer2Demo/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | /.idea/caches 6 | /.idea/libraries 7 | /.idea/modules.xml 8 | /.idea/workspace.xml 9 | /.idea/navEditor.xml 10 | /.idea/assetWizardSettings.xml 11 | .DS_Store 12 | /build 13 | /captures 14 | .externalNativeBuild 15 | .cxx 16 | local.properties 17 | 18 | /app/debug 19 | /app/release 20 | /app/build 21 | -------------------------------------------------------------------------------- /Qplayer2Demo/.idea/.name: -------------------------------------------------------------------------------- 1 | qplayer2demo -------------------------------------------------------------------------------- /Qplayer2Demo/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Qplayer2Demo/.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /Qplayer2Demo/.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /Qplayer2Demo/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Qplayer2Demo/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /Qplayer2Demo/app/libs/qndroid-miku-delivery-v1.1.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pili-engineering/QPlayer2-Android/75eaeade6e54a1e24d8d4c0c8125de2fa272215b/Qplayer2Demo/app/libs/qndroid-miku-delivery-v1.1.2.jar -------------------------------------------------------------------------------- /Qplayer2Demo/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 21 | 29 | 30 | 31 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/TODO.md: -------------------------------------------------------------------------------- 1 | 1.播放器单例 2 | 全局只有一个播放器,类似Youtube,支持小窗 后台播放 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/ic_qplayer2_launcher2-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pili-engineering/QPlayer2-Android/75eaeade6e54a1e24d8d4c0c8125de2fa272215b/Qplayer2Demo/app/src/main/ic_qplayer2_launcher2-playstore.png -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/application/QPlayerApplication.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.application 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import androidx.multidex.MultiDex 6 | import com.tencent.bugly.crashreport.CrashReport 7 | 8 | class QPlayerApplication: Application() { 9 | 10 | override fun onCreate() { 11 | super.onCreate() 12 | QPlayerApplicationContext.applicationContext = applicationContext 13 | CrashReport.initCrashReport(applicationContext, "adadee00c2", false); 14 | } 15 | 16 | override fun attachBaseContext(base: Context?) { 17 | super.attachBaseContext(base) 18 | MultiDex.install(this) 19 | 20 | } 21 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/application/QPlayerApplicationContext.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.application 2 | 3 | import android.content.Context 4 | 5 | object QPlayerApplicationContext { 6 | 7 | lateinit var applicationContext: Context 8 | 9 | 10 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/common/system/FileUtils.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.common.system 2 | 3 | import android.content.Context 4 | import androidx.annotation.RawRes 5 | import java.io.File 6 | import java.io.FileOutputStream 7 | import java.io.IOException 8 | import java.io.InputStream 9 | import java.io.OutputStream 10 | 11 | object FileUtils { 12 | fun copyFromResToFile(context: Context, @RawRes resId: Int, fileName: String): String? { 13 | 14 | // 获取 raw 资源中的 InputStream 15 | var inputStream: InputStream? = null 16 | var outputStream: OutputStream? = null 17 | 18 | try { 19 | // 打开 res/raw 中的文件 20 | inputStream = context.resources.openRawResource(resId) 21 | 22 | // 获取 files 目录 23 | val filesDir: File = context.filesDir 24 | val outFile = File(filesDir, fileName) 25 | 26 | // 创建输出流,准备写入文件 27 | outputStream = FileOutputStream(outFile) 28 | 29 | // 复制文件内容 30 | val buffer = ByteArray(1024) 31 | var length: Int 32 | while ((inputStream.read(buffer).also { length = it }) > 0) { 33 | outputStream.write(buffer, 0, length) 34 | } 35 | 36 | outputStream.flush() // 确保所有数据都写入文件 37 | return outFile.absolutePath 38 | } catch (e: IOException) { 39 | e.printStackTrace() 40 | } finally { 41 | // 关闭流 42 | try { 43 | inputStream?.close() 44 | outputStream?.close() 45 | } catch (e: IOException) { 46 | e.printStackTrace() 47 | } 48 | } 49 | return null 50 | } 51 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/common/system/PermissionHelper.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.common.system 2 | 3 | import android.Manifest 4 | import android.app.Activity 5 | import android.content.Context 6 | import android.content.pm.PackageManager 7 | import androidx.core.app.ActivityCompat 8 | import androidx.core.content.PackageManagerCompat 9 | 10 | object PermissionHelper { 11 | fun checkPhotoAlbumPermission(activity: Activity): Boolean { 12 | 13 | val permissions = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE) 14 | 15 | var result = ActivityCompat.checkSelfPermission(activity, permissions[0]) 16 | if (result != PackageManager.PERMISSION_GRANTED) { 17 | ActivityCompat.requestPermissions(activity, permissions, 0) 18 | return false 19 | } 20 | return true 21 | } 22 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/common/system/SystemProperties.java: -------------------------------------------------------------------------------- 1 | 2 | package com.qiniu.qplayer2.common.system; 3 | 4 | import androidx.annotation.NonNull; 5 | 6 | 7 | import com.qiniu.qplayer2.common.type.StringUtils; 8 | 9 | import java.lang.reflect.Method; 10 | 11 | /** 12 | * Helper for {@code android.os.SystemProperties} 13 | * 14 | * @author yrom 15 | */ 16 | public class SystemProperties { 17 | private static final Method getStringProperty = getMethod(getClass("android.os.SystemProperties")); 18 | 19 | private static Class getClass(String name) { 20 | try { 21 | Class cls = Class.forName(name); 22 | if (cls == null) { 23 | throw new ClassNotFoundException(); 24 | } 25 | return cls; 26 | } catch (ClassNotFoundException e) { 27 | try { 28 | return ClassLoader.getSystemClassLoader().loadClass(name); 29 | } catch (ClassNotFoundException e1) { 30 | return null; 31 | } 32 | } 33 | } 34 | 35 | private static Method getMethod(Class clz) { 36 | if (clz == null) return null; 37 | try { 38 | return clz.getMethod("get", String.class); 39 | } catch (Exception e) { 40 | return null; 41 | } 42 | } 43 | 44 | @NonNull 45 | public static String get(String key) { 46 | if (getStringProperty != null) { 47 | try { 48 | Object value = getStringProperty.invoke(null, key); 49 | if (value == null) { 50 | return StringUtils.EMPTY; 51 | } 52 | return StringUtils.trimToEmpty(value.toString()); 53 | } catch (Exception ignored) { 54 | } 55 | } 56 | return StringUtils.EMPTY; 57 | } 58 | 59 | public static String get(String key, String def) { 60 | if (getStringProperty != null) { 61 | try { 62 | String value = (String) getStringProperty.invoke(null, key); 63 | return StringUtils.defaultString(StringUtils.trimToNull(value), def); 64 | } catch (Exception ignored) { 65 | } 66 | } 67 | return def; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/logic/BasePlayerControlVM.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.logic 2 | 3 | import com.qiniu.qmedia.component.player.QPlayerControlHandler 4 | 5 | abstract class BasePlayerControlVM { 6 | 7 | var playerControlHandler: QPlayerControlHandler? = null 8 | set(value) { 9 | if (value == null) { 10 | onClearPlayerListeners() 11 | } else { 12 | field = value 13 | onInstallPlayerControlHandler(field) 14 | } 15 | } 16 | 17 | abstract fun onInstallPlayerControlHandler(controlHandler: QPlayerControlHandler?) 18 | 19 | abstract fun onClearPlayerListeners() 20 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/logic/BasePlayerRenderVM.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.logic 2 | 3 | import com.qiniu.qmedia.component.player.QPlayerControlHandler 4 | import com.qiniu.qmedia.component.player.QPlayerRenderHandler 5 | 6 | abstract class BasePlayerRenderVM { 7 | 8 | var playerRenderHandler: QPlayerRenderHandler? = null 9 | set(value) { 10 | if (value == null) { 11 | onClearPlayerListeners() 12 | } else { 13 | field = value 14 | onInstallPlayerRenderHandler(field) 15 | } 16 | } 17 | 18 | abstract fun onInstallPlayerRenderHandler(renderHandler: QPlayerRenderHandler?) 19 | 20 | abstract fun onClearPlayerListeners() 21 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/logic/PlayerBiteRateVM.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.logic 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import com.qiniu.qmedia.component.player.QIPlayerBiteRateListener 5 | import com.qiniu.qmedia.component.player.QPlayerControlHandler 6 | 7 | class PlayerBiteRateVM: QIPlayerBiteRateListener, BasePlayerControlVM() { 8 | 9 | val playerBiteRateLiveData = MutableLiveData() 10 | 11 | val bitRate: Long 12 | public get() = playerControlHandler?.biteRate ?: 0L 13 | 14 | 15 | override fun onBiteRateChanged(biteRate: Long) { 16 | playerBiteRateLiveData.value = biteRate 17 | } 18 | 19 | override fun onInstallPlayerControlHandler(controlHandler: QPlayerControlHandler?) { 20 | controlHandler?.addPlayerBiteRateChangeListener(this) 21 | } 22 | 23 | override fun onClearPlayerListeners() { 24 | playerControlHandler?.removePlayerBiteRateChangeListener(this) 25 | 26 | } 27 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/logic/PlayerBufferingVM.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.logic 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import com.qiniu.qmedia.component.player.QIPlayerBufferingListener 5 | import com.qiniu.qmedia.component.player.QPlayerControlHandler 6 | 7 | class PlayerBufferingVM: QIPlayerBufferingListener, BasePlayerControlVM() { 8 | 9 | val playerBufferingLiveData = MutableLiveData() 10 | 11 | override fun onBufferingStart() { 12 | playerBufferingLiveData.value = true 13 | } 14 | 15 | override fun onBufferingEnd() { 16 | playerBufferingLiveData.value = false 17 | } 18 | 19 | override fun onInstallPlayerControlHandler(controlHandler: QPlayerControlHandler?) { 20 | controlHandler?.addPlayerBufferingChangeListener(this) 21 | } 22 | 23 | override fun onClearPlayerListeners() { 24 | playerControlHandler?.removePlayerBufferingChangeListener(this) 25 | 26 | } 27 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/logic/PlayerDownloadVM.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.logic 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import com.qiniu.qmedia.component.player.QIPlayerDownloadListener 5 | import com.qiniu.qmedia.component.player.QPlayerControlHandler 6 | 7 | class PlayerDownloadVM: QIPlayerDownloadListener, BasePlayerControlVM() { 8 | val playerDownloadSpeedLiveData = MutableLiveData() 9 | 10 | val downloadSpeed: Long 11 | public get() = playerControlHandler?.downloadSpeed ?: 0L 12 | 13 | override fun onDownloadChanged(speed: Long, bufferProgress: Long) { 14 | playerDownloadSpeedLiveData.value = speed 15 | } 16 | 17 | override fun onInstallPlayerControlHandler(controlHandler: QPlayerControlHandler?) { 18 | controlHandler?.addPlayerDownloadChangeListener(this) 19 | } 20 | 21 | override fun onClearPlayerListeners() { 22 | playerControlHandler?.removePlayerDownloadChangeListener(this) 23 | } 24 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/logic/PlayerFPSVM.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.logic 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import com.qiniu.qmedia.component.player.QIPlayerFPSListener 5 | import com.qiniu.qmedia.component.player.QPlayerControlHandler 6 | 7 | class PlayerFPSVM:QIPlayerFPSListener, BasePlayerControlVM() { 8 | val playerFPSLiveData = MutableLiveData() 9 | 10 | val fps: Int 11 | public get() = playerControlHandler?.fps ?: 0 12 | 13 | override fun onFPSChanged(fps: Int) { 14 | playerFPSLiveData.value = fps 15 | } 16 | 17 | override fun onInstallPlayerControlHandler(controlHandler: QPlayerControlHandler?) { 18 | controlHandler?.addPlayerFPSChangeListener(this) 19 | } 20 | 21 | override fun onClearPlayerListeners() { 22 | playerControlHandler?.removePlayerFPSChangeListener(this) 23 | 24 | } 25 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/logic/PlayerFirstFrameVM.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.logic 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import com.qiniu.qmedia.component.player.QIPlayerRenderListener 5 | import com.qiniu.qmedia.component.player.QPlayerRenderHandler 6 | 7 | class PlayerFirstFrameVM : QIPlayerRenderListener, BasePlayerRenderVM() { 8 | val playerFirstFrameElapsedTimeLiveData = MutableLiveData() 9 | 10 | override fun onFirstFrameRendered(elapsedTime: Long) { 11 | playerFirstFrameElapsedTimeLiveData.value = elapsedTime 12 | } 13 | 14 | override fun onInstallPlayerRenderHandler(renderHandler: QPlayerRenderHandler?) { 15 | playerRenderHandler?.addPlayerRenderListener(this) 16 | } 17 | 18 | override fun onClearPlayerListeners() { 19 | playerRenderHandler?.removePlayerRenderListener(this) 20 | } 21 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/logic/PlayerPausePlayVM.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.logic 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import com.qiniu.qmedia.component.player.QIPlayerStateChangeListener 5 | import com.qiniu.qmedia.component.player.QPlayerControlHandler 6 | import com.qiniu.qmedia.component.player.QPlayerState 7 | 8 | class PlayerPausePlayVM: QIPlayerStateChangeListener, BasePlayerControlVM() { 9 | 10 | val playerStateLiveData = MutableLiveData() 11 | 12 | 13 | 14 | override fun onStateChanged(state: QPlayerState) { 15 | 16 | playerStateLiveData.value = state 17 | } 18 | 19 | public fun getCurrentPlayerState(): QPlayerState { 20 | return playerControlHandler?.currentPlayerState ?: QPlayerState.NONE 21 | } 22 | 23 | public fun resume() { 24 | playerControlHandler?.resumeRender() 25 | } 26 | 27 | public fun pause() { 28 | playerControlHandler?.pauseRender() 29 | } 30 | 31 | override fun onInstallPlayerControlHandler(controlHandler: QPlayerControlHandler?) { 32 | controlHandler?.addPlayerStateChangeListener(this) 33 | } 34 | 35 | override fun onClearPlayerListeners() { 36 | playerControlHandler?.removePlayerStateChangeListener(this) 37 | } 38 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/logic/PlayerProgressVM.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.logic 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import com.qiniu.qmedia.component.player.QIPlayerDownloadListener 5 | import com.qiniu.qmedia.component.player.QIPlayerProgressListener 6 | import com.qiniu.qmedia.component.player.QPlayerControlHandler 7 | 8 | class PlayerProgressVM : QIPlayerProgressListener, QIPlayerDownloadListener, BasePlayerControlVM() { 9 | val playerProgressLiveData = MutableLiveData() 10 | val playBufferProgressLiveData = MutableLiveData() 11 | 12 | 13 | public fun getDuration(): Long { 14 | return playerControlHandler?.duration ?: 0L 15 | } 16 | 17 | override fun onProgressChanged(duration: Long, progress: Long) { 18 | playerProgressLiveData.value = progress 19 | } 20 | 21 | override fun onInstallPlayerControlHandler(controlHandler: QPlayerControlHandler?) { 22 | controlHandler?.addPlayerProgressChangeListener(this) 23 | controlHandler?.addPlayerDownloadChangeListener(this) 24 | } 25 | 26 | override fun onClearPlayerListeners() { 27 | playerControlHandler?.removePlayerProgressChangeListener(this) 28 | playerControlHandler?.removePlayerDownloadChangeListener(this) 29 | } 30 | 31 | public fun seek(position: Long) { 32 | playerControlHandler?.seek(position) 33 | } 34 | 35 | override fun onDownloadChanged(speed: Long, bufferProgress: Long) { 36 | playBufferProgressLiveData.value = bufferProgress; 37 | } 38 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/repository/shortvideo/ShortVideoApiService.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.repository.shortvideo 2 | 3 | import io.reactivex.rxjava3.core.Single 4 | 5 | 6 | interface ShortVideoApiService { 7 | 8 | // fun getShortVideoList():Single<> 9 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/repository/shortvideo/UpgradeInfo.java: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.repository.shortvideo; 2 | 3 | 4 | public class UpgradeInfo { 5 | private String mAppID; 6 | private String mVersion; 7 | private String mDescription; 8 | private String mDownloadURL; 9 | private String mCreateTime; 10 | 11 | public void setAppID(String appID) { 12 | this.mAppID = appID; 13 | } 14 | 15 | public void setVersion(String version) { 16 | this.mVersion = version; 17 | } 18 | 19 | public void setDescription(String description) { 20 | this.mDescription = description; 21 | } 22 | 23 | public void setDownloadURL(String downloadURL) { 24 | this.mDownloadURL = downloadURL; 25 | } 26 | 27 | public void setCreateTime(String createTime) { 28 | this.mCreateTime = createTime; 29 | } 30 | 31 | public String getAppID() { 32 | return mAppID; 33 | } 34 | 35 | public String getVersion() { 36 | return mVersion; 37 | } 38 | 39 | public String getDescription() { 40 | return mDescription; 41 | } 42 | 43 | public String getDownloadURL() { 44 | return mDownloadURL; 45 | } 46 | 47 | public String getCreateTime() { 48 | return mCreateTime; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/repository/shortvideo/VideoItem.java: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.repository.shortvideo; 2 | 3 | import java.io.Serializable; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | 7 | 8 | 9 | public class VideoItem implements Serializable { 10 | private String mName; 11 | private String mSize; 12 | private String mTime; 13 | private String mVideoPath; 14 | 15 | private String mProxyVideoPath; 16 | private String mCoverPath; 17 | 18 | public static final String VIDEO_PATH_PREFIX = "http://demo-videos.qnsdk.com/"; 19 | public static final String COVER_PATH_PREFIX = "http://demo-videos.qnsdk.com/snapshoot/"; 20 | public static final String COVER_PATH_SUFFIX = ".jpg"; 21 | 22 | 23 | public void setName(String name) { 24 | this.mVideoPath = VIDEO_PATH_PREFIX + name; 25 | this.mName = getVideoName(name); 26 | this.mCoverPath = COVER_PATH_PREFIX + mName + COVER_PATH_SUFFIX; 27 | } 28 | 29 | public void setSize(String size) { 30 | this.mSize = size; 31 | } 32 | 33 | public void setTime(String time) { 34 | time = time.substring(0, 13); 35 | mTime = stampToDate(time); 36 | } 37 | 38 | public void setVideoPath(String name) { 39 | this.mVideoPath = VIDEO_PATH_PREFIX + name; 40 | this.mName = getVideoName(name); 41 | } 42 | 43 | public String getName() { 44 | return mName; 45 | } 46 | 47 | public String getSize() { 48 | return mSize; 49 | } 50 | 51 | public String getTime() { 52 | return mTime; 53 | } 54 | 55 | public String getVideoPath() { 56 | return mVideoPath; 57 | } 58 | 59 | public String getCoverPath() { 60 | return mCoverPath; 61 | } 62 | 63 | private static String stampToDate(String s) { 64 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 65 | long lt = new Long(s); 66 | Date date = new Date(lt); 67 | return simpleDateFormat.format(date); 68 | } 69 | 70 | private static String getVideoName(String name) { 71 | int start = name.lastIndexOf("/"); 72 | if (start != -1) { 73 | String subString = name.substring(start + 1); 74 | subString = subString.replace(".mp4", ""); 75 | return subString; 76 | } else { 77 | return null; 78 | } 79 | } 80 | 81 | 82 | } 83 | -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/tools/AudioFrame.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.tools 2 | 3 | import com.qiniu.qmedia.component.player.QIPlayerAudioDataListener 4 | 5 | class AudioFrame( 6 | val sampleRate: Int, 7 | val channelCount: Int, 8 | val audioFormat: QIPlayerAudioDataListener.QSampleFormat, 9 | val channelLayout: QIPlayerAudioDataListener.QChannelLayout, 10 | 11 | data: ByteArray, 12 | presentationTimeUs: Long 13 | ) : BaseFrame(data, presentationTimeUs) -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/tools/BaseFrame.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.tools 2 | 3 | open class BaseFrame( 4 | val data: ByteArray, 5 | val presentationTimeUs: Long 6 | ) { 7 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/tools/MediaMuxerWrapper.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.tools 2 | 3 | import android.media.MediaCodec 4 | import android.media.MediaMuxer 5 | import android.util.Log 6 | import java.io.IOException 7 | import java.nio.ByteBuffer 8 | 9 | class MediaMuxerWrapper( 10 | private val mAudioEnable: Boolean, 11 | private val mVideoEnable: Boolean, 12 | private val mPath: String 13 | ) { 14 | companion object { 15 | const val INVALID_TRACK_INDEX = -1 16 | const val TAG = "MediaMuxerWrapper" 17 | } 18 | 19 | 20 | private var mIsVideoTrackAdded = false 21 | private var mIsAudioTrackAdded = false 22 | 23 | private var mMediaMuxer: MediaMuxer? = null 24 | private var mIsStart = false 25 | fun init(): Boolean { 26 | Log.d(TAG, "init") 27 | mIsStart = false 28 | try { 29 | mMediaMuxer = MediaMuxer(mPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) 30 | 31 | } catch (e: IOException) { 32 | return false 33 | } 34 | return true 35 | } 36 | 37 | fun unint() { 38 | Log.d(TAG, "unint") 39 | if (mIsStart) { 40 | mIsStart = false 41 | mMediaMuxer?.stop() 42 | mMediaMuxer?.release() 43 | } 44 | 45 | } 46 | 47 | @Synchronized 48 | fun addTrackToMediaMuxer(mediaCodec: MediaCodec, type: MediaType): Int { 49 | if (type == MediaType.AUDIO && !mIsAudioTrackAdded) { 50 | mIsAudioTrackAdded = true 51 | Log.d(TAG, "addTrackToMediaMuxer audio") 52 | return mMediaMuxer?.addTrack(mediaCodec.outputFormat) ?: INVALID_TRACK_INDEX 53 | } else if (type == MediaType.VIDEO && !mIsVideoTrackAdded) { 54 | mIsVideoTrackAdded = true 55 | Log.d(TAG, "addTrackToMediaMuxer video") 56 | return mMediaMuxer?.addTrack(mediaCodec.outputFormat) ?: INVALID_TRACK_INDEX 57 | } 58 | return INVALID_TRACK_INDEX 59 | } 60 | 61 | fun writeSampleData(trackIndex: Int, byteBuf: ByteBuffer, bufferInfo: MediaCodec.BufferInfo) { 62 | Log.d(TAG, "writeSampleData index=$trackIndex") 63 | mMediaMuxer?.writeSampleData(trackIndex, byteBuf, bufferInfo) 64 | } 65 | 66 | @Synchronized 67 | fun startIfReady(): Boolean { 68 | val isReady = mAudioEnable == mIsAudioTrackAdded && mVideoEnable && mIsVideoTrackAdded 69 | if (isReady) { 70 | Log.d(TAG, "media muxer start ready") 71 | mIsStart = true 72 | mMediaMuxer?.start() 73 | return true 74 | } else { 75 | Log.d(TAG, "media muxer start but not ready") 76 | } 77 | return false 78 | } 79 | 80 | @Synchronized 81 | fun isStart(): Boolean { 82 | return mIsStart 83 | } 84 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/tools/MediaType.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.tools 2 | 3 | enum class MediaType(val type: Int) { 4 | NONE(0), 5 | VIDEO(1), 6 | AUDIO(2), 7 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/tools/VideoFrame.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.tools 2 | 3 | import com.qiniu.qmedia.component.player.QIPlayerVideoDataListener 4 | 5 | class VideoFrame(val width: Int, 6 | val height: Int, 7 | val videoDataType: QIPlayerVideoDataListener.QVideoDataType, 8 | data: ByteArray, 9 | presentationTimeUs: Long): BaseFrame(data, presentationTimeUs) -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/common/notch/DefaultNotchScreenSupport.java: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.common.notch; 2 | 3 | import android.graphics.Rect; 4 | import android.view.Window; 5 | 6 | import androidx.annotation.NonNull; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | /** 12 | * Created by feifan on 2018/6/15. 13 | * Contacts me:404619986@qq.com 14 | */ 15 | class DefaultNotchScreenSupport implements INotchScreenSupport { 16 | @Override 17 | public boolean hasNotchInScreen(@NonNull Window window) { 18 | return false; 19 | } 20 | 21 | @Override 22 | public boolean hasNotchInScreenHardware(@NonNull Window window) { 23 | return hasNotchInScreen(window); 24 | } 25 | 26 | @NonNull 27 | @Override 28 | public List getNotchSize(@NonNull Window window) { 29 | return new ArrayList<>(); 30 | } 31 | 32 | @Override 33 | public List getNotchSizeHardware(@NonNull Window window) { 34 | return getNotchSize(window); 35 | } 36 | 37 | @Override 38 | public void setWindowLayoutAroundNotch(@NonNull Window window) { 39 | } 40 | 41 | @Override 42 | public void setWindowLayoutBlockNotch(@NonNull Window window) { 43 | } 44 | 45 | @Override 46 | public void setWindowLayoutNotchDefault(@NonNull Window window) { 47 | 48 | } 49 | 50 | /** 51 | * 折叠屏 52 | * @param window 53 | */ 54 | @Override 55 | public void onWindowConfigChanged(@NonNull Window window) { 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/common/notch/INotchScreenSupport.java: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.common.notch; 2 | 3 | import android.graphics.Rect; 4 | import android.view.Window; 5 | 6 | import androidx.annotation.NonNull; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Created by feifan on 2018/6/15. 12 | * Contacts me:404619986@qq.com 13 | */ 14 | interface INotchScreenSupport { 15 | boolean hasNotchInScreen(@NonNull Window window); 16 | 17 | /** 18 | * 硬件上屏幕是否存在凹口,{@link #hasNotchInScreen(Window)}用判断当前状态是否存在凹口, 19 | * Android p在调用了{@link #setWindowLayoutBlockNotch(Window)}认为当前状态不存在凹口 20 | * 21 | * @param window window 22 | * @return false, 不存在凹口,true,存在凹口 23 | */ 24 | boolean hasNotchInScreenHardware(@NonNull Window window); 25 | 26 | @NonNull 27 | List getNotchSize(@NonNull Window window); 28 | 29 | /** 30 | * 获取硬件上屏幕凹口size,{@link #getNotchSize(Window)},获取当前状态凹口size 31 | * Android p在调用了{@link #setWindowLayoutBlockNotch(Window)}认为当前状态不存在凹口 32 | * 所以获取不到size 33 | * 34 | * @param window window 35 | * @return Rect 36 | */ 37 | List getNotchSizeHardware(@NonNull Window window); 38 | 39 | void setWindowLayoutAroundNotch(@NonNull Window window); 40 | 41 | void setWindowLayoutBlockNotch(@NonNull Window window); 42 | 43 | /** 44 | * 重置刘海屏 flag 45 | */ 46 | void setWindowLayoutNotchDefault(@NonNull Window window); 47 | 48 | /** 49 | * 折叠屏 config change 50 | * @param window 51 | */ 52 | void onWindowConfigChanged(@NonNull Window window); 53 | } 54 | -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/common/notch/MiNotchScreenSupport.java: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.common.notch; 2 | 3 | import android.content.Context; 4 | import android.graphics.Rect; 5 | import android.os.Build; 6 | import android.view.Window; 7 | 8 | import androidx.annotation.NonNull; 9 | import androidx.annotation.RequiresApi; 10 | 11 | import com.qiniu.qplayer2.common.system.SystemProperties; 12 | import com.qiniu.qplayer2.ui.common.statusbar.StatusBarCompat; 13 | 14 | import java.lang.reflect.Method; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | /** 19 | * Created by feifan on 2018/6/12. 20 | * Contacts me:404619986@qq.com 21 | * https://dev.mi.com/console/doc/detail?pId=1293 22 | */ 23 | final class MiNotchScreenSupport extends DefaultNotchScreenSupport { 24 | //绘制到刘海区域 25 | private static final int FLAG_NOTCH_IMMERSIVE = 0x00000100; 26 | //竖屏绘制到刘海区域 27 | private static final int FLAG_NOTCH_PORTRAIT = 0x00000200; 28 | //横屏绘制刘海区域 29 | private static final int FLAG_NOTCH_LANDSCAPE = 0x00000400; 30 | 31 | @RequiresApi(api = Build.VERSION_CODES.O) 32 | @Override 33 | public boolean hasNotchInScreen(@NonNull Window window) { 34 | try { 35 | return "1".equals(SystemProperties.get("ro.miui.notch", null)); 36 | } catch (Exception ignored) { 37 | return false; 38 | } 39 | } 40 | 41 | //小米的状态栏高度会略高于刘海屏的高度,因此通过获取状态栏的高度来间接避开刘海屏,宽度未知,直接返回了屏幕宽度 42 | @NonNull 43 | @RequiresApi(api = Build.VERSION_CODES.O) 44 | @Override 45 | public List getNotchSize(@NonNull Window window) { 46 | List result = new ArrayList<>(); 47 | 48 | Context context = window.getContext(); 49 | Rect rect = new Rect(); 50 | rect.top = 0; 51 | rect.bottom = StatusBarCompat.getStatusBarHeight(context); 52 | rect.left = 0; 53 | rect.right = context.getResources().getDisplayMetrics().widthPixels; 54 | result.add(rect); 55 | 56 | return result; 57 | } 58 | 59 | @RequiresApi(api = Build.VERSION_CODES.O) 60 | @Override 61 | public void setWindowLayoutAroundNotch(@NonNull Window window) { 62 | final int flag = FLAG_NOTCH_IMMERSIVE | FLAG_NOTCH_PORTRAIT | FLAG_NOTCH_LANDSCAPE; 63 | try { 64 | Method method = Window.class.getMethod("addExtraFlags", int.class); 65 | method.invoke(window, flag); 66 | } catch (Exception ignored) { 67 | } 68 | } 69 | 70 | @RequiresApi(api = Build.VERSION_CODES.O) 71 | @Override 72 | public void setWindowLayoutBlockNotch(@NonNull Window window) { 73 | final int flag = FLAG_NOTCH_IMMERSIVE | FLAG_NOTCH_PORTRAIT | FLAG_NOTCH_LANDSCAPE; 74 | try { 75 | Method method = Window.class.getMethod("clearExtraFlags", int.class); 76 | method.invoke(window, flag); 77 | } catch (Exception ignored) { 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/common/notch/OnePLusNotchScreenSupport.java: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.common.notch; 2 | 3 | import android.graphics.Rect; 4 | import android.os.Build; 5 | import android.view.Window; 6 | 7 | import androidx.annotation.NonNull; 8 | 9 | 10 | import com.qiniu.qplayer2.ui.common.statusbar.StatusBarCompat; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | /** 16 | * @author nero 17 | * 一加的当前只有oneplus A6000是刘海屏的,根据型号判断的刘海屏,获取状态栏的高度 18 | */ 19 | final class OnePLusNotchScreenSupport extends DefaultNotchScreenSupport { 20 | 21 | private static final String ONE_PLUS_6 = "ONEPLUS A6000"; 22 | 23 | @Override 24 | public boolean hasNotchInScreen(@NonNull Window window) { 25 | return ONE_PLUS_6.equals(Build.MODEL); 26 | } 27 | 28 | // 刘海宽度未知,高度以实际状态栏为准 29 | @NonNull 30 | @Override 31 | public List getNotchSize(@NonNull Window window) { 32 | Rect rect = new Rect(); 33 | rect.left = 0; 34 | rect.right = 0; 35 | rect.top = 0; 36 | rect.bottom = StatusBarCompat.getStatusBarHeight(window.getContext()); 37 | 38 | List result = new ArrayList<>(); 39 | result.add(rect); 40 | return result; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/common/notch/OppoNotchScreenSupport.java: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.common.notch; 2 | 3 | import android.content.Context; 4 | import android.graphics.Rect; 5 | import android.os.Build; 6 | import android.util.DisplayMetrics; 7 | import android.view.Window; 8 | 9 | import androidx.annotation.NonNull; 10 | import androidx.annotation.RequiresApi; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | /** 16 | * Created by feifan on 2018/5/15. 17 | * Contacts me:404619986@qq.com 18 | * https://open.oppomobile.com/wiki/doc#id=10159 19 | */ 20 | final class OppoNotchScreenSupport extends DefaultNotchScreenSupport { 21 | 22 | @RequiresApi(api = Build.VERSION_CODES.O) 23 | @Override 24 | public boolean hasNotchInScreen(@NonNull Window window) { 25 | try { 26 | return window.getContext().getPackageManager() 27 | .hasSystemFeature("com.oppo.feature.screen.heteromorphism"); 28 | } catch (Exception ignored) { 29 | return false; 30 | } 31 | } 32 | 33 | //目前Oppo刘海屏机型尺寸规格都是统一的,显示屏宽度为1080px,高度为2280px,刘海区域宽度为324px, 高度为80px 34 | @NonNull 35 | @RequiresApi(api = Build.VERSION_CODES.O) 36 | @Override 37 | public List getNotchSize(@NonNull Window window) { 38 | List result = new ArrayList<>(); 39 | Context context = window.getContext(); 40 | Rect rect = new Rect(); 41 | DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); 42 | final int notchWidth = 324; 43 | final int notchHeight = 80; 44 | rect.left = (displayMetrics.widthPixels - notchWidth) / 2; 45 | rect.right = rect.left + notchWidth; 46 | rect.top = 0; 47 | rect.bottom = notchHeight; 48 | result.add(rect); 49 | return result; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/common/notch/VivoNotchScreenSupport.java: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.common.notch; 2 | 3 | import android.graphics.Rect; 4 | import android.os.Build; 5 | import android.util.DisplayMetrics; 6 | import android.util.TypedValue; 7 | import android.view.Window; 8 | 9 | import androidx.annotation.NonNull; 10 | import androidx.annotation.RequiresApi; 11 | 12 | import java.lang.reflect.Method; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | /** 17 | * Created by feifan on 2018/5/15. 18 | * Contacts me:404619986@qq.com 19 | * https://dev.vivo.com.cn/documentCenter/doc/103 20 | */ 21 | final class VivoNotchScreenSupport extends DefaultNotchScreenSupport { 22 | private static Class vivoFtFeature = null; 23 | //表示是否有凹槽 24 | private static final int VIVO_HAS_NOTCH_DISPLAY = 0x00000020; 25 | //表示是否有圆角 26 | private static final int VIVO_HAS_ROUND_DISPLAY = 0x00000008; 27 | 28 | @RequiresApi(api = Build.VERSION_CODES.O) 29 | @Override 30 | public boolean hasNotchInScreen(@NonNull Window window) { 31 | try { 32 | if (vivoFtFeature == null) { 33 | ClassLoader cl = window.getContext().getClassLoader(); 34 | vivoFtFeature = cl.loadClass("android.util.FtFeature"); 35 | } 36 | Method get = vivoFtFeature.getMethod("isFeatureSupport", int.class); 37 | return (boolean) get.invoke(vivoFtFeature, VIVO_HAS_NOTCH_DISPLAY); 38 | } catch (Exception e) { 39 | return false; 40 | } 41 | } 42 | 43 | //vivo刘海大小固定 44 | @NonNull 45 | @RequiresApi(api = Build.VERSION_CODES.O) 46 | @Override 47 | public List getNotchSize(@NonNull Window window) { 48 | List result = new ArrayList<>(); 49 | Rect rect = new Rect(); 50 | DisplayMetrics displayMetrics = window.getContext().getResources().getDisplayMetrics(); 51 | final int notchWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100f, displayMetrics); 52 | final int notchHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 27f, displayMetrics); 53 | rect.left = (displayMetrics.widthPixels - notchWidth) / 2; 54 | rect.right = rect.left + notchWidth; 55 | rect.top = 0; 56 | rect.bottom = notchHeight; 57 | result.add(rect); 58 | return result; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/common/statusbar/StatusBarCompat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 BiliBili Inc. 3 | */ 4 | 5 | package com.qiniu.qplayer2.ui.common.statusbar; 6 | 7 | import android.annotation.TargetApi; 8 | import android.app.Activity; 9 | import android.content.Context; 10 | import android.content.res.Resources; 11 | import android.content.res.TypedArray; 12 | import android.graphics.Color; 13 | import android.graphics.Point; 14 | import android.os.Build; 15 | import android.view.Display; 16 | import android.view.View; 17 | import android.view.ViewGroup; 18 | import android.view.Window; 19 | import android.view.WindowManager; 20 | import android.widget.FrameLayout; 21 | 22 | import androidx.annotation.ColorInt; 23 | import androidx.annotation.IntDef; 24 | import androidx.core.content.ContextCompat; 25 | import androidx.core.view.ViewCompat; 26 | import androidx.drawerlayout.widget.DrawerLayout; 27 | 28 | import java.lang.annotation.ElementType; 29 | import java.lang.annotation.Retention; 30 | import java.lang.annotation.RetentionPolicy; 31 | import java.lang.annotation.Target; 32 | import java.lang.reflect.Method; 33 | import java.util.regex.Pattern; 34 | 35 | /** 36 | * 状态栏工具类 37 | * 状态栏两种模式(Android 4.4以上) 38 | * 1.沉浸式全屏模式 39 | * 2.状态栏着色模式 40 | */ 41 | public class StatusBarCompat { 42 | 43 | /** 44 | * 获取状态栏高度 45 | */ 46 | public static int getStatusBarHeight(Context context) { 47 | int result = 0; 48 | int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); 49 | if (resId > 0) { 50 | result = context.getResources().getDimensionPixelSize(resId); 51 | } 52 | return result; 53 | } 54 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/LongControlPanelType.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo 2 | 3 | enum class LongControlPanelType(val type: String) { 4 | Normal("normal") 5 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/LongEnviromentType.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo 2 | 3 | enum class LongEnviromentType(val type: String) { 4 | LONG("Long") 5 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/LongLogicProvider.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo 2 | 3 | import com.qiniu.qplayer2.common.system.PermissionHelper 4 | import com.qiniu.qplayer2ext.commonplayer.ILogicProvider 5 | 6 | class LongLogicProvider(private val mActivity: LongVideoActivity): ILogicProvider { 7 | fun checkPhotoAlbumPermission(): Boolean { 8 | return PermissionHelper.checkPhotoAlbumPermission(mActivity) 9 | } 10 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/LongPlayableParams.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo 2 | 3 | import com.qiniu.qmedia.component.player.QMediaModel 4 | import com.qiniu.qplayer2ext.commonplayer.data.DisplayOrientation 5 | import com.qiniu.qplayer2ext.commonplayer.data.CommonPlayableParams 6 | 7 | class LongPlayableParams( 8 | mediaModel: QMediaModel, 9 | controlPanelType: String, 10 | displayOrientation: DisplayOrientation, 11 | environmentType: String, 12 | startPos: Long 13 | ): CommonPlayableParams(mediaModel, controlPanelType, displayOrientation, environmentType, startPos) { 14 | 15 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/LongVideoParams.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo 2 | 3 | import com.qiniu.qplayer2ext.commonplayer.data.CommonVideoParams 4 | 5 | class LongVideoParams( 6 | val title: String, 7 | id: Long): CommonVideoParams(id) { 8 | 9 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/ServiceOwnerType.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service 2 | 3 | enum class ServiceOwnerType(val type: String) { 4 | PLAYER_CONTROL_PANEL_CONTATINER_VISIBLE_SERVICE("PlayerControlPanelContainerVisibleService"), 5 | PLAYER_TOAST_SERVICE("PlayerToastService"), 6 | PLAYER_BUFFERING_SERVICE("PlayerBufferingService"), 7 | PLAYER_NETWORK_SERVICE("PlayerNetworkService"), 8 | PLAYER_PANORAMA_TOUCH_SERVICE("PlayerPanoramaTouchSerivice"), 9 | PLAYER_CAPTURE_SERVICE("PlayerCaptureSerivice"), 10 | PLAYER_VOLUME_SERVICE("PlayerVolumeSerivice"), 11 | PLAYER_SUBTITLE_SERVICE("PlayerSubtitleService") 12 | 13 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/buffering/IPlayerBufferingService.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.buffering 2 | 3 | interface IPlayerBufferingService { 4 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/buffering/PlayerBufferingServiceOwner.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.buffering 2 | 3 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceOwner 4 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceManager 5 | import com.qiniu.qplayer2ext.commonplayer.service.PlayerServiceManager 6 | import com.qiniu.qplayer2.ui.page.longvideo.LongLogicProvider 7 | import com.qiniu.qplayer2.ui.page.longvideo.LongPlayableParams 8 | import com.qiniu.qplayer2.ui.page.longvideo.LongVideoParams 9 | import com.qiniu.qplayer2.ui.page.longvideo.service.ServiceOwnerType 10 | 11 | class PlayerBufferingServiceOwner : 12 | IPlayerServiceOwner { 13 | 14 | 15 | override val name: String 16 | get() = ServiceOwnerType.PLAYER_BUFFERING_SERVICE.type 17 | 18 | private val mPlayerBufferingServiceClient: PlayerServiceManager.Client = 19 | PlayerServiceManager.Client() 20 | 21 | override fun start(serviceManager: IPlayerServiceManager) { 22 | serviceManager.bindService( 23 | PlayerServiceManager.ServiceDescriptor.obtain( 24 | PlayerBufferingService::class.java 25 | ), mPlayerBufferingServiceClient 26 | ) 27 | } 28 | 29 | override fun stop(serviceManager: IPlayerServiceManager) { 30 | serviceManager.unbindService( 31 | PlayerServiceManager.ServiceDescriptor.obtain( 32 | PlayerBufferingService::class.java 33 | ), mPlayerBufferingServiceClient 34 | ) 35 | } 36 | 37 | override fun service(): T { 38 | return mPlayerBufferingServiceClient.service as T 39 | } 40 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/controlpanelcontainervisible/IPlayerControlPanelContainerVisibleService.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.controlpanelcontainervisible 2 | 3 | interface IPlayerControlPanelContainerVisibleService { 4 | 5 | fun setAutoHideEnable(enable: Boolean) 6 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/controlpanelcontainervisible/PlayerControlPanelContainerVisibleServiceOwner.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.controlpanelcontainervisible 2 | 3 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceOwner 4 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceManager 5 | import com.qiniu.qplayer2ext.commonplayer.service.PlayerServiceManager 6 | import com.qiniu.qplayer2.ui.page.longvideo.LongLogicProvider 7 | import com.qiniu.qplayer2.ui.page.longvideo.LongPlayableParams 8 | import com.qiniu.qplayer2.ui.page.longvideo.LongVideoParams 9 | import com.qiniu.qplayer2.ui.page.longvideo.service.ServiceOwnerType 10 | 11 | class PlayerControlPanelContainerVisibleServiceOwner 12 | : IPlayerServiceOwner { 13 | override val name: String 14 | get() = ServiceOwnerType.PLAYER_CONTROL_PANEL_CONTATINER_VISIBLE_SERVICE.type 15 | 16 | private val mPlayerControlPanelContainerVisibleServiceClient: PlayerServiceManager.Client = 17 | PlayerServiceManager.Client() 18 | 19 | override fun start(serviceManager: IPlayerServiceManager) { 20 | serviceManager.bindService(PlayerServiceManager.ServiceDescriptor.obtain( 21 | PlayerControlPanelContainerVisibleService::class.java), mPlayerControlPanelContainerVisibleServiceClient) 22 | } 23 | 24 | override fun stop(serviceManager: IPlayerServiceManager) { 25 | serviceManager.unbindService(PlayerServiceManager.ServiceDescriptor.obtain( 26 | PlayerControlPanelContainerVisibleService::class.java), mPlayerControlPanelContainerVisibleServiceClient) 27 | } 28 | 29 | override fun service(): T { 30 | return mPlayerControlPanelContainerVisibleServiceClient.service as T 31 | } 32 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/network/IPlayerNetworkService.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.network 2 | 3 | interface IPlayerNetworkService { 4 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/network/PlayerNetworkServiceOwner.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.network 2 | 3 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceOwner 4 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceManager 5 | import com.qiniu.qplayer2ext.commonplayer.service.PlayerServiceManager 6 | import com.qiniu.qplayer2.ui.page.longvideo.LongLogicProvider 7 | import com.qiniu.qplayer2.ui.page.longvideo.LongPlayableParams 8 | import com.qiniu.qplayer2.ui.page.longvideo.LongVideoParams 9 | import com.qiniu.qplayer2.ui.page.longvideo.service.ServiceOwnerType 10 | 11 | class PlayerNetworkServiceOwner: 12 | IPlayerServiceOwner { 13 | 14 | 15 | override val name: String 16 | get() = ServiceOwnerType.PLAYER_NETWORK_SERVICE.type 17 | 18 | private val mPlayerReconnectServiceClient: PlayerServiceManager.Client = 19 | PlayerServiceManager.Client() 20 | 21 | override fun start(serviceManager: IPlayerServiceManager) { 22 | serviceManager.bindService( 23 | PlayerServiceManager.ServiceDescriptor.obtain( 24 | PlayerNetworkService::class.java 25 | ), mPlayerReconnectServiceClient 26 | ) 27 | } 28 | 29 | override fun stop(serviceManager: IPlayerServiceManager) { 30 | serviceManager.unbindService( 31 | PlayerServiceManager.ServiceDescriptor.obtain( 32 | PlayerNetworkService::class.java 33 | ), mPlayerReconnectServiceClient 34 | ) 35 | } 36 | 37 | override fun service(): T { 38 | return mPlayerReconnectServiceClient.service as T 39 | } 40 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/panorama/IPlayerPanoramaTouchSerivice.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.panorama 2 | 3 | interface IPlayerPanoramaTouchSerivice { 4 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/panorama/PlayerPanoramaTouchSeriviceOwner.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.panorama 2 | 3 | import com.qiniu.qplayer2.ui.page.longvideo.LongLogicProvider 4 | import com.qiniu.qplayer2.ui.page.longvideo.LongPlayableParams 5 | import com.qiniu.qplayer2.ui.page.longvideo.LongVideoParams 6 | import com.qiniu.qplayer2.ui.page.longvideo.service.ServiceOwnerType 7 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceOwner 8 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceManager 9 | import com.qiniu.qplayer2ext.commonplayer.service.PlayerServiceManager 10 | 11 | class PlayerPanoramaTouchSeriviceOwner : 12 | IPlayerServiceOwner { 13 | 14 | 15 | override val name: String 16 | get() = ServiceOwnerType.PLAYER_PANORAMA_TOUCH_SERVICE.type 17 | 18 | private val mPlayerPanoramaTouchServiceClient: PlayerServiceManager.Client = 19 | PlayerServiceManager.Client() 20 | 21 | override fun start(serviceManager: IPlayerServiceManager) { 22 | serviceManager.bindService( 23 | PlayerServiceManager.ServiceDescriptor.obtain( 24 | PlayerPanoramaTouchSerivice::class.java 25 | ), mPlayerPanoramaTouchServiceClient 26 | ) 27 | } 28 | 29 | override fun stop(serviceManager: IPlayerServiceManager) { 30 | serviceManager.unbindService( 31 | PlayerServiceManager.ServiceDescriptor.obtain( 32 | PlayerPanoramaTouchSerivice::class.java 33 | ), mPlayerPanoramaTouchServiceClient 34 | ) 35 | } 36 | 37 | override fun service(): T { 38 | return mPlayerPanoramaTouchServiceClient.service as T 39 | } 40 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/shoot/IPlayerCaptureService.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.shoot 2 | 3 | interface IPlayerCaptureService { 4 | 5 | fun shootVideo() 6 | 7 | fun startRecord() 8 | 9 | fun stopRecord(): Boolean 10 | 11 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/shoot/PlayerShootVideoServiceOwner.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.shoot 2 | 3 | import com.qiniu.qplayer2.ui.page.longvideo.LongLogicProvider 4 | import com.qiniu.qplayer2.ui.page.longvideo.LongPlayableParams 5 | import com.qiniu.qplayer2.ui.page.longvideo.LongVideoParams 6 | import com.qiniu.qplayer2.ui.page.longvideo.service.ServiceOwnerType 7 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceManager 8 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceOwner 9 | import com.qiniu.qplayer2ext.commonplayer.service.PlayerServiceManager 10 | 11 | class PlayerShootVideoServiceOwner 12 | : IPlayerServiceOwner { 13 | 14 | 15 | override val name: String 16 | get() = ServiceOwnerType.PLAYER_CAPTURE_SERVICE.type 17 | 18 | private val mPlayerShootVideoServiceClient: PlayerServiceManager.Client = 19 | PlayerServiceManager.Client() 20 | 21 | override fun start(serviceManager: IPlayerServiceManager) { 22 | serviceManager.bindService( 23 | PlayerServiceManager.ServiceDescriptor.obtain( 24 | PlayerCaptureService::class.java 25 | ), mPlayerShootVideoServiceClient 26 | ) 27 | } 28 | 29 | override fun stop(serviceManager: IPlayerServiceManager) { 30 | serviceManager.unbindService( 31 | PlayerServiceManager.ServiceDescriptor.obtain( 32 | PlayerCaptureService::class.java 33 | ), mPlayerShootVideoServiceClient 34 | ) 35 | } 36 | 37 | override fun service(): T { 38 | return mPlayerShootVideoServiceClient.service as T 39 | } 40 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/subtitle/IPlayerSubtitleService.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.subtitle 2 | 3 | interface IPlayerSubtitleService { 4 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/subtitle/PlayerSubtitleServiceOwner.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.subtitle 2 | 3 | import com.qiniu.qplayer2.ui.page.longvideo.LongLogicProvider 4 | import com.qiniu.qplayer2.ui.page.longvideo.LongPlayableParams 5 | import com.qiniu.qplayer2.ui.page.longvideo.LongVideoParams 6 | import com.qiniu.qplayer2.ui.page.longvideo.service.ServiceOwnerType 7 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceManager 8 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceOwner 9 | import com.qiniu.qplayer2ext.commonplayer.service.PlayerServiceManager 10 | 11 | class PlayerSubtitleServiceOwner : 12 | IPlayerServiceOwner { 13 | 14 | 15 | override val name: String 16 | get() = ServiceOwnerType.PLAYER_SUBTITLE_SERVICE.type 17 | 18 | private val mPlayerSubtitleServiceClient: PlayerServiceManager.Client = 19 | PlayerServiceManager.Client() 20 | 21 | override fun start(serviceManager: IPlayerServiceManager) { 22 | serviceManager.bindService( 23 | PlayerServiceManager.ServiceDescriptor.obtain( 24 | PlayerSubtitleService::class.java 25 | ), mPlayerSubtitleServiceClient 26 | ) 27 | } 28 | 29 | override fun stop(serviceManager: IPlayerServiceManager) { 30 | serviceManager.unbindService( 31 | PlayerServiceManager.ServiceDescriptor.obtain( 32 | PlayerSubtitleService::class.java 33 | ), mPlayerSubtitleServiceClient 34 | ) 35 | } 36 | 37 | override fun service(): T { 38 | return mPlayerSubtitleServiceClient.service as T 39 | } 40 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/toast/IPlayerToastService.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.toast 2 | 3 | interface IPlayerToastService { 4 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/toast/PlayerToastServiceOwner.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.toast 2 | 3 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceOwner 4 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceManager 5 | import com.qiniu.qplayer2ext.commonplayer.service.PlayerServiceManager 6 | import com.qiniu.qplayer2.ui.page.longvideo.LongLogicProvider 7 | import com.qiniu.qplayer2.ui.page.longvideo.LongPlayableParams 8 | import com.qiniu.qplayer2.ui.page.longvideo.LongVideoParams 9 | import com.qiniu.qplayer2.ui.page.longvideo.service.ServiceOwnerType 10 | 11 | class PlayerToastServiceOwner : 12 | IPlayerServiceOwner { 13 | 14 | override val name: String 15 | get() = ServiceOwnerType.PLAYER_TOAST_SERVICE.type 16 | 17 | private val mPlayerToastServiceClient: PlayerServiceManager.Client = 18 | PlayerServiceManager.Client() 19 | 20 | override fun start(serviceManager: IPlayerServiceManager) { 21 | serviceManager.bindService( 22 | PlayerServiceManager.ServiceDescriptor.obtain( 23 | PlayerToastService::class.java 24 | ), mPlayerToastServiceClient 25 | ) 26 | } 27 | 28 | override fun stop(serviceManager: IPlayerServiceManager) { 29 | serviceManager.unbindService( 30 | PlayerServiceManager.ServiceDescriptor.obtain( 31 | PlayerToastService::class.java 32 | ), mPlayerToastServiceClient 33 | ) 34 | } 35 | 36 | override fun service(): T { 37 | return mPlayerToastServiceClient.service as T 38 | } 39 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/videoquality/IPlayerVideoQualityService.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.videoquality 2 | 3 | interface IPlayerVideoQualityService { 4 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/videoquality/PlayerVideoQualityService.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.videoquality 2 | 3 | import com.qiniu.qplayer2ext.commonplayer.CommonPlayerCore 4 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerService 5 | import com.qiniu.qplayer2.ui.page.longvideo.LongLogicProvider 6 | import com.qiniu.qplayer2.ui.page.longvideo.LongPlayableParams 7 | import com.qiniu.qplayer2.ui.page.longvideo.LongVideoParams 8 | 9 | class PlayerVideoQualityService 10 | : IPlayerService{ 11 | override fun onStart() { 12 | TODO("Not yet implemented") 13 | } 14 | 15 | override fun onStop() { 16 | TODO("Not yet implemented") 17 | } 18 | 19 | override fun bindPlayerCore(playerCore: CommonPlayerCore) { 20 | TODO("Not yet implemented") 21 | } 22 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/volume/IPlayerVolumeService.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.volume 2 | 3 | interface IPlayerVolumeService { 4 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/longvideo/service/volume/PlayerVolumeServiceOwner.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.longvideo.service.volume 2 | 3 | import com.qiniu.qplayer2.ui.page.longvideo.LongLogicProvider 4 | import com.qiniu.qplayer2.ui.page.longvideo.LongPlayableParams 5 | import com.qiniu.qplayer2.ui.page.longvideo.LongVideoParams 6 | import com.qiniu.qplayer2.ui.page.longvideo.service.ServiceOwnerType 7 | import com.qiniu.qplayer2.ui.page.longvideo.service.shoot.PlayerCaptureService 8 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceManager 9 | import com.qiniu.qplayer2ext.commonplayer.service.IPlayerServiceOwner 10 | import com.qiniu.qplayer2ext.commonplayer.service.PlayerServiceManager 11 | 12 | class PlayerVolumeServiceOwner 13 | : IPlayerServiceOwner { 14 | 15 | 16 | override val name: String 17 | get() = ServiceOwnerType.PLAYER_VOLUME_SERVICE.type 18 | 19 | private val mPlayerVolumeServiceClient: PlayerServiceManager.Client = 20 | PlayerServiceManager.Client() 21 | 22 | override fun start(serviceManager: IPlayerServiceManager) { 23 | serviceManager.bindService( 24 | PlayerServiceManager.ServiceDescriptor.obtain( 25 | PlayerVolumeService::class.java 26 | ), mPlayerVolumeServiceClient 27 | ) 28 | } 29 | 30 | override fun stop(serviceManager: IPlayerServiceManager) { 31 | serviceManager.unbindService( 32 | PlayerServiceManager.ServiceDescriptor.obtain( 33 | PlayerCaptureService::class.java 34 | ), mPlayerVolumeServiceClient 35 | ) 36 | } 37 | 38 | override fun service(): T { 39 | return mPlayerVolumeServiceClient.service as T 40 | } 41 | } -------------------------------------------------------------------------------- /Qplayer2Demo/app/src/main/java/com/qiniu/qplayer2/ui/page/main/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.qiniu.qplayer2.ui.page.main 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import android.widget.Button 7 | import android.widget.TextView 8 | import androidx.appcompat.app.AppCompatActivity 9 | import com.qiniu.qplayer2.BuildConfig 10 | import com.qiniu.qplayer2.R 11 | import com.qiniu.qplayer2.ui.page.doubleplayer.DoublePlayerActivity 12 | import com.qiniu.qplayer2.ui.page.longvideo.LongVideoActivity 13 | import com.qiniu.qplayer2.ui.page.simplelongvideo.SimpleLongVideoActivity 14 | import com.qiniu.qplayer2.ui.page.setting.SettingActivity 15 | import com.qiniu.qplayer2.ui.page.shortvideoV2.ShortVideoActivityV2 16 | 17 | class MainActivity : AppCompatActivity() { 18 | @SuppressLint("SetTextI18n") 19 | override fun onCreate(savedInstanceState: Bundle?) { 20 | super.onCreate(savedInstanceState) 21 | setContentView(R.layout.activity_main) 22 | 23 | findViewById