Commit dffd5cf28f9d86fe7135af3c32dae16ecbc2a3dd

Authored by 韩亚云
2 parents c125f4f5 14ed85cd

Merge branch 'master' of bj.gitlab.cnlive.com:cnlive-team/newModuleStrike

app/strike/src/main/java/com/cnlive/strike/demo/activity/ExoPlayerActivity.java
... ... @@ -20,8 +20,11 @@ import com.google.android.exoplayer2.Player;
20 20 import com.google.android.exoplayer2.SimpleExoPlayer;
21 21 import com.google.android.exoplayer2.Timeline;
22 22 import com.google.android.exoplayer2.source.TrackGroupArray;
  23 +import com.google.android.exoplayer2.source.hls.HlsMediaSource;
23 24 import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
24 25 import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
  26 +import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
  27 +import com.google.android.exoplayer2.util.Util;
25 28 import com.google.android.exoplayer2.video.VideoListener;
26 29 import com.libs.video.video.exoplayer.CNLiveBaseVideoControlView;
27 30 import com.libs.video.video.exoplayer.MyTestControlView;
... ... @@ -51,12 +54,12 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl
51 54 // Produces DataSource instances through which media data is loaded.
52 55 // DataSource dataSource =new DefaultDataSource(context,Util.getUserAgent(context, "yourApplicationName"),true);
53 56 // Create a data source factory.
54   -// DataSource.Factory dataSourceFactory =
55   -// new DefaultHttpDataSourceFactory(Util.getUserAgent(context, "app-name"));
56   -//
  57 + DefaultHttpDataSourceFactory dataSourceFactory =
  58 + new DefaultHttpDataSourceFactory(Util.getUserAgent(context, "app-name"));
  59 +
57 60 Uri mp4VideoUri = Uri.parse("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8");
58   -//// HlsMediaSource hlsMediaSource =
59   -//// new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(mp4VideoUri);
  61 + HlsMediaSource hlsMediaSource =
  62 + new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(mp4VideoUri);
60 63 // Uri dashUri = Uri.parse("rtmp://tyzg.rtmps2.cnlive.com/live-tyzg-577/577_999");
61 64 //
62 65 // RtmpDataSourceFactory rtmpDataSourceFactory=new RtmpDataSourceFactory();
... ... @@ -68,14 +71,14 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl
68 71 // SsMediaSource ssMediaSource = new SsMediaSource.Factory(dataSourceFactory).createMediaSource(dashUri);
69 72 //
70 73 // //step2. 创建播放器
71   -// player = new SimpleExoPlayer.Builder(context).build();
  74 + SimpleExoPlayer player = new SimpleExoPlayer.Builder(context).build();
72 75 // player.addVideoListener(this);
73 76 // player.addListener(this);
74 77 // // Prepare the player with the source.
75   -// player.prepare(hlsMediaSource);
  78 + player.prepare(hlsMediaSource);
76 79 // //绑定视图
77 80 // binding.playerView.setPlayer(player);
78   -
  81 +// player.setPlayWhenReady(true);
79 82 //全屏
80 83 // player.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
81 84 //按比例放大
... ... @@ -116,6 +119,7 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl
116 119 }
117 120  
118 121 private void initVideoPlayer() {
  122 + binding.playerView.setCustomControllView(new MyTestControlView(context));
119 123 // Uri dashUri = Uri.parse("rtmp://tyzg.rtmps2.cnlive.com/live-tyzg-577/577_999");
120 124  
121 125 // Uri mp4VideoUri = Uri.parse("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8");
... ... @@ -125,7 +129,6 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl
125 129 // videoPlayer.prepare(true);
126 130 // MyTestControlView myTestControlView = new MyTestControlView(context);
127 131 // myTestControlView.setPlayer(videoPlayer.player);
128   - binding.playerView.setCustomControllView(new MyTestControlView(context));
129 132 // binding.playerView.setOnClickListener(new View.OnClickListener() {
130 133 // @Override
131 134 // public void onClick(View v) {
... ... @@ -135,6 +138,11 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl
135 138 }
136 139  
137 140 @Override
  141 + public void onBackPressed() {
  142 + binding.playerView.onBackPress();
  143 + }
  144 +
  145 + @Override
138 146 public void onTimelineChanged(Timeline timeline, int reason) {
139 147  
140 148 }
... ...
app/strike/src/main/res/layout/activity_explayer.xml
... ... @@ -4,12 +4,17 @@
4 4 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
5 5 android:layout_width="match_parent"
6 6 android:layout_height="match_parent"
  7 + android:background="@color/black"
7 8 android:orientation="vertical">
8 9  
9 10 <com.libs.video.video.exoplayer.CNLiveVideoView
10 11 android:id="@+id/playerView"
11 12 android:layout_width="match_parent"
12   - android:layout_height="match_parent"
13   - />
  13 + android:layout_height="@dimen/dp_200" />
  14 +
  15 +<!-- <com.google.android.exoplayer2.ui.PlayerView-->
  16 +<!-- android:layout_width="match_parent"-->
  17 +<!-- android:id="@+id/playerView"-->
  18 +<!-- android:layout_height="match_parent" />-->
14 19 </LinearLayout>
15 20 </layout>
16 21 \ No newline at end of file
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/CNLiveBaseVideoControlView.java
... ... @@ -5,52 +5,57 @@ import android.app.Activity;
5 5 import android.content.Context;
6 6 import android.content.pm.ActivityInfo;
7 7 import android.content.res.Configuration;
8   -import android.content.res.Resources;
9 8 import android.content.res.TypedArray;
10   -import android.graphics.drawable.Drawable;
11 9 import android.os.Looper;
12   -import android.os.SystemClock;
13 10 import android.util.AttributeSet;
  11 +import android.util.Log;
14 12 import android.view.KeyEvent;
15 13 import android.view.LayoutInflater;
16   -import android.view.MotionEvent;
  14 +import android.view.Surface;
17 15 import android.view.View;
18   -import android.view.ViewGroup;
19 16 import android.view.WindowManager;
20 17 import android.widget.FrameLayout;
21   -import android.widget.ImageView;
22 18 import android.widget.TextView;
23 19  
24   -import androidx.annotation.ColorInt;
25 20 import androidx.annotation.Nullable;
26 21  
27 22 import com.cnlive.cloud.video.R;
28 23 import com.google.android.exoplayer2.C;
  24 +import com.google.android.exoplayer2.ExoPlaybackException;
29 25 import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
  26 +import com.google.android.exoplayer2.Format;
  27 +import com.google.android.exoplayer2.PlaybackParameters;
30 28 import com.google.android.exoplayer2.PlaybackPreparer;
31 29 import com.google.android.exoplayer2.Player;
32 30 import com.google.android.exoplayer2.Timeline;
33   -import com.google.android.exoplayer2.ui.TimeBar;
  31 +import com.google.android.exoplayer2.analytics.AnalyticsListener;
  32 +import com.google.android.exoplayer2.audio.AudioAttributes;
  33 +import com.google.android.exoplayer2.decoder.DecoderCounters;
  34 +import com.google.android.exoplayer2.metadata.Metadata;
  35 +import com.google.android.exoplayer2.source.MediaSourceEventListener;
  36 +import com.google.android.exoplayer2.source.TrackGroupArray;
  37 +import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
34 38 import com.google.android.exoplayer2.util.Assertions;
35 39 import com.google.android.exoplayer2.util.RepeatModeUtil;
36 40 import com.google.android.exoplayer2.util.Util;
37 41  
38   -import java.util.Arrays;
  42 +import java.io.IOException;
39 43 import java.util.Formatter;
40 44 import java.util.Locale;
41 45 import java.util.concurrent.CopyOnWriteArrayList;
42 46  
43   -public abstract class CNLiveBaseVideoControlView extends FrameLayout {
  47 +public abstract class CNLiveBaseVideoControlView extends FrameLayout implements AnalyticsListener {
44 48  
45 49 static {
46 50 ExoPlayerLibraryInfo.registerModule("goog.exo.ui");
47 51 }
48 52  
  53 + private String TAG = getClass().getName();
  54 +
49 55 /**
50 56 * Listener to be notified about changes of the visibility of the UI control.
51 57 */
52 58 public interface VisibilityListener {
53   -
54 59 /**
55 60 * Called when the visibility changes.
56 61 *
... ... @@ -102,98 +107,47 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
102 107  
103 108 private static final long MAX_POSITION_FOR_SEEK_TO_PREVIOUS = 3000;
104 109 /**
105   - * The maximum interval between time bar position updates.
  110 + * 默认更新视频进度条时间
106 111 */
107 112 private static final int MAX_UPDATE_INTERVAL_MS = 1000;
108 113  
109 114 private CNLiveBaseVideoControlView.ComponentListener componentListener;
110 115 private CopyOnWriteArrayList<CNLiveBaseVideoControlView.VisibilityListener> visibilityListeners;
111   - @Nullable
112   - private View previousButton;
113   - @Nullable
114   - private View nextButton;
115   - @Nullable
116   - private View playButton;
117   - @Nullable
118   - private View pauseButton;
119   - @Nullable
120   - private View fastForwardButton;
121   - @Nullable
122   - private View rewindButton;
123   - @Nullable
124   - private ImageView repeatToggleButton;
125   - @Nullable
126   - private ImageView shuffleButton;
127   - @Nullable
128   - private View vrButton;
129   - @Nullable
130   - private TextView durationView;
131   - @Nullable
132   - private TextView positionView;
133   - @Nullable
134   - private TimeBar timeBar;
135 116 private StringBuilder formatBuilder;
136 117 private Formatter formatter;
137 118 private Timeline.Period period;
138 119 private Timeline.Window window;
139   - private Runnable updateProgressAction;
140   - private Runnable hideAction;
  120 + private Runnable updateProgressAction;//进度条更新
  121 + // private Runnable hideAction;
141 122 private int controllerLayoutId;
142   - private Drawable repeatOffButtonDrawable;
143   - private Drawable repeatOneButtonDrawable;
144   - private Drawable repeatAllButtonDrawable;
145   - private String repeatOffButtonContentDescription;
146   - private String repeatOneButtonContentDescription;
147   - private String repeatAllButtonContentDescription;
148   - private Drawable shuffleOnButtonDrawable;
149   - private Drawable shuffleOffButtonDrawable;
150   - private float buttonAlphaEnabled;
151   - private float buttonAlphaDisabled;
152   - private String shuffleOnContentDescription;
153   - private String shuffleOffContentDescription;
154 123 //当前屏幕朝向
155 124 private final int PORTRAIT_SCREEN = 0;//竖屏
156 125 @Nullable
157   - private VideoPlayer player;
158   - // private CNLiveControlDispatcher controlDispatcher;
159   -// @Nullable
160   -// private CNLiveBaseVideoControlView.ProgressUpdateListener progressUpdateListener;
161   -// @Nullable
162   - private PlaybackPreparer playbackPreparer;
163   -
164   - private boolean isAttachedToWindow;
165   - private boolean showMultiWindowTimeBar;
166   - private boolean multiWindowTimeBar;
167   - private boolean scrubbing;
168   - private int rewindMs;
169   - private int fastForwardMs;
170   - private int showTimeoutMs;
171   - private int timeBarMinUpdateIntervalMs;
172   - private @RepeatModeUtil.RepeatToggleModes
173   - int repeatToggleModes;
174   - private boolean showShuffleButton;
175   - private long hideAtMs;
176   - private long[] adGroupTimesMs;
177   - private boolean[] playedAdGroups;
178   - private long[] extraAdGroupTimesMs;
179   - private boolean[] extraPlayedAdGroups;
180   - private long currentWindowOffset;
  126 + public VideoPlayer player;
  127 + private boolean isAttachedToWindow;//是否附加到窗口上
181 128 private Activity activity;
182   - private TextView tvTopViewTitle;//顶部标题视图
183   - //横竖屏
184 129 @Nullable
185   - private View switchScreenButton;
186 130 public View basePortraitView;
187 131 public View baseLandscapeView;
188   -
  132 + @Nullable
  133 + private View baseRootView;
  134 + @Nullable
  135 + private FrameLayout fl_root;//根布局
  136 + @Nullable
189 137 public Context context;
  138 + private Configuration newConfig;
190 139  
191 140 public CNLiveBaseVideoControlView(Context context) {
192 141 this(context, /* attrs= */ null, 0, null);
193 142 this.context = context;
  143 + visibilityListeners = new CopyOnWriteArrayList<>();
  144 + }
  145 +
  146 + protected int getPortraitControllViewId() {
  147 + return -1;
194 148 }
195 149  
196   - protected int getControllViewId() {
  150 + protected int getLandscapeControllViewId() {
197 151 return -1;
198 152 }
199 153  
... ... @@ -214,161 +168,254 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
214 168 if (context instanceof Activity) {
215 169 this.activity = (Activity) context;
216 170 }
  171 + formatBuilder = new StringBuilder();
  172 + formatter = new Formatter(formatBuilder, Locale.getDefault());
  173 + period = new Timeline.Period();
  174 + window = new Timeline.Window();
  175 + //初始化相关监听器
  176 + visibilityListeners = new CopyOnWriteArrayList<>();
217 177 componentListener = new CNLiveBaseVideoControlView.ComponentListener();
218 178 // controlDispatcher = new CNLiveDefaultControlDispatcher();
219   -
220 179 controllerLayoutId = R.layout.layout_cnlive_control_view;
221   - if (null != playbackAttrs) {
222   - rewindMs = DEFAULT_REWIND_MS;
223   - fastForwardMs = DEFAULT_FAST_FORWARD_MS;
224   - showTimeoutMs = DEFAULT_SHOW_TIMEOUT_MS;
225   - repeatToggleModes = DEFAULT_REPEAT_TOGGLE_MODES;
226   - timeBarMinUpdateIntervalMs = DEFAULT_TIME_BAR_MIN_UPDATE_INTERVAL_MS;
227   - hideAtMs = C.TIME_UNSET;
228   - showShuffleButton = false;
229   - if (playbackAttrs != null) {
230   - TypedArray a =
231   - context
232   - .getTheme()
233   - .obtainStyledAttributes(playbackAttrs, R.styleable.PlayerControlView, 0, 0);
234   - try {
235   - rewindMs = a.getInt(R.styleable.PlayerControlView_rewind_increment, rewindMs);
236   - fastForwardMs =
237   - a.getInt(R.styleable.PlayerControlView_fastforward_increment, fastForwardMs);
238   - showTimeoutMs = a.getInt(R.styleable.PlayerControlView_show_timeout, showTimeoutMs);
239   - controllerLayoutId =
240   - a.getResourceId(R.styleable.PlayerControlView_controller_layout_id, controllerLayoutId);
241   - repeatToggleModes = getRepeatToggleModes(a, repeatToggleModes);
242   - showShuffleButton =
243   - a.getBoolean(R.styleable.PlayerControlView_show_shuffle_button, showShuffleButton);
244   - setTimeBarMinUpdateInterval(
245   - a.getInt(
246   - R.styleable.PlayerControlView_time_bar_min_update_interval,
247   - timeBarMinUpdateIntervalMs));
248   - } finally {
249   - a.recycle();
  180 +// if (null != playbackAttrs && -1 != getPortraitControllViewId()) {
  181 +// rewindMs = DEFAULT_REWIND_MS;
  182 +// fastForwardMs = DEFAULT_FAST_FORWARD_MS;
  183 +// showTimeoutMs = DEFAULT_SHOW_TIMEOUT_MS;
  184 +// repeatToggleModes = DEFAULT_REPEAT_TOGGLE_MODES;
  185 +// timeBarMinUpdateIntervalMs = DEFAULT_TIME_BAR_MIN_UPDATE_INTERVAL_MS;
  186 +// hideAtMs = C.TIME_UNSET;
  187 +// showShuffleButton = false;
  188 +// if (playbackAttrs != null) {
  189 +// TypedArray a =
  190 +// context
  191 +// .getTheme()
  192 +// .obtainStyledAttributes(playbackAttrs, R.styleable.PlayerControlView, 0, 0);
  193 +// try {
  194 +// rewindMs = a.getInt(R.styleable.PlayerControlView_rewind_increment, rewindMs);
  195 +// fastForwardMs =
  196 +// a.getInt(R.styleable.PlayerControlView_fastforward_increment, fastForwardMs);
  197 +// showTimeoutMs = a.getInt(R.styleable.PlayerControlView_show_timeout, showTimeoutMs);
  198 +// controllerLayoutId =
  199 +// a.getResourceId(R.styleable.PlayerControlView_controller_layout_id, controllerLayoutId);
  200 +// repeatToggleModes = getRepeatToggleModes(a, repeatToggleModes);
  201 +// showShuffleButton =
  202 +// a.getBoolean(R.styleable.PlayerControlView_show_shuffle_button, showShuffleButton);
  203 +// setTimeBarMinUpdateInterval(
  204 +// a.getInt(
  205 +// R.styleable.PlayerControlView_time_bar_min_update_interval,
  206 +// timeBarMinUpdateIntervalMs));
  207 +// } finally {
  208 +// a.recycle();
  209 +// }
  210 +// }
  211 +//
  212 +
  213 +//
  214 +// adGroupTimesMs = new long[0];
  215 +// playedAdGroups = new boolean[0];
  216 +// extraAdGroupTimesMs = new long[0];
  217 +// extraPlayedAdGroups = new boolean[0];
  218 + updateProgressAction = this::updateProgress;
  219 +// hideAction = this::hide;
  220 +//
  221 +// basePortraitView = LayoutInflater.from(context).inflate(controllerLayoutId, /* root= */ this);
  222 +// setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
  223 +//
  224 +// TimeBar customTimeBar = findViewById(R.id.cnlive_progress);
  225 +// View timeBarPlaceholder = findViewById(R.id.cnlive_progress_placeholder);
  226 +// if (customTimeBar != null) {
  227 +// timeBar = customTimeBar;
  228 +// } else if (timeBarPlaceholder != null) {
  229 +// // Propagate attrs as timebarAttrs so that DefaultTimeBar's custom attributes are transferred,
  230 +// // but standard attributes (e.g. background) are not.
  231 +// BaseTimerBar defaultTimeBar = new BaseTimerBar(context, null, 0, playbackAttrs);
  232 +// //todo 设置播放的颜色
  233 +//// defaultTimeBar.setPlayedColor(ContextCompat.getColor(context,R.color.qmui_config_color_red));
  234 +// //todo 设置缓冲颜色
  235 +//// defaultTimeBar.setBufferedColor(ContextCompat.getColor(context,R.color.qmui_config_color_red));
  236 +// defaultTimeBar.setId(R.id.cnlive_progress);
  237 +// defaultTimeBar.setLayoutParams(timeBarPlaceholder.getLayoutParams());
  238 +// ViewGroup parent = ((ViewGroup) timeBarPlaceholder.getParent());
  239 +// int timeBarIndex = parent.indexOfChild(timeBarPlaceholder);
  240 +// parent.removeView(timeBarPlaceholder);
  241 +// parent.addView(defaultTimeBar, timeBarIndex);
  242 +// timeBar = defaultTimeBar;
  243 +// } else {
  244 +// timeBar = null;
  245 +// }
  246 +// durationView = findViewById(R.id.cnlive_duration);
  247 +// positionView = findViewById(R.id.cnlive_position);
  248 +// //初始化顶部视图
  249 +// //顶部标题
  250 +// tvTopViewTitle = findViewById(R.id.cnlive_top_title);
  251 +// //设置标题名称
  252 +// if (null != tvTopViewTitle) {
  253 +// tvTopViewTitle.setText("测试");
  254 +// }
  255 +// if (timeBar != null) {
  256 +// timeBar.addListener(componentListener);
  257 +// }
  258 +// playButton = findViewById(R.id.cnlive_play);
  259 +// if (playButton != null) {
  260 +// playButton.setOnClickListener(componentListener);
  261 +// }
  262 +// pauseButton = findViewById(R.id.cnlive_pause);
  263 +// if (pauseButton != null) {
  264 +// pauseButton.setOnClickListener(componentListener);
  265 +// }
  266 +// previousButton = findViewById(R.id.cnlive_prev);
  267 +// if (previousButton != null) {
  268 +// previousButton.setOnClickListener(componentListener);
  269 +// }
  270 +// nextButton = findViewById(R.id.cnlive_next);
  271 +// if (nextButton != null) {
  272 +// nextButton.setOnClickListener(componentListener);
  273 +// }
  274 +// rewindButton = findViewById(R.id.cnlive_rew);
  275 +// if (rewindButton != null) {
  276 +// rewindButton.setOnClickListener(componentListener);
  277 +// }
  278 +// fastForwardButton = findViewById(R.id.cnlive_ffwd);
  279 +// if (fastForwardButton != null) {
  280 +// fastForwardButton.setOnClickListener(componentListener);
  281 +// }
  282 +// repeatToggleButton = findViewById(R.id.cnlive_repeat_toggle);
  283 +// if (repeatToggleButton != null) {
  284 +// repeatToggleButton.setOnClickListener(componentListener);
  285 +// }
  286 +// repeatToggleButton.setVisibility(GONE);
  287 +// shuffleButton = findViewById(R.id.cnlive_shuffle);
  288 +// if (shuffleButton != null) {
  289 +// shuffleButton.setOnClickListener(componentListener);
  290 +// }
  291 +// //初始化横竖屏切换
  292 +// switchScreenButton = findViewById(R.id.cnlive_switch_screen);
  293 +// if (switchScreenButton != null) {
  294 +// switchScreenButton.setOnClickListener(componentListener);
  295 +// }
  296 +// vrButton = findViewById(R.id.cnlive_vr);
  297 +// setShowVrButton(false);
  298 +//
  299 +// Resources resources = context.getResources();
  300 +//
  301 +// buttonAlphaEnabled =
  302 +// (float) resources.getInteger(R.integer.exo_media_button_opacity_percentage_enabled) / 100;
  303 +// buttonAlphaDisabled =
  304 +// (float) resources.getInteger(R.integer.exo_media_button_opacity_percentage_disabled) / 100;
  305 +//
  306 +// repeatOffButtonDrawable = resources.getDrawable(R.drawable.exo_controls_repeat_off);
  307 +// repeatOneButtonDrawable = resources.getDrawable(R.drawable.exo_controls_repeat_one);
  308 +// repeatAllButtonDrawable = resources.getDrawable(R.drawable.exo_controls_repeat_all);
  309 +// shuffleOnButtonDrawable = resources.getDrawable(R.drawable.exo_controls_shuffle_on);
  310 +// shuffleOffButtonDrawable = resources.getDrawable(R.drawable.exo_controls_shuffle_off);
  311 +// repeatOffButtonContentDescription =
  312 +// resources.getString(R.string.exo_controls_repeat_off_description);
  313 +// repeatOneButtonContentDescription =
  314 +// resources.getString(R.string.exo_controls_repeat_one_description);
  315 +// repeatAllButtonContentDescription =
  316 +// resources.getString(R.string.exo_controls_repeat_all_description);
  317 +// shuffleOnContentDescription = resources.getString(R.string.exo_controls_shuffle_on_description);
  318 +// shuffleOffContentDescription =
  319 +// resources.getString(R.string.exo_controls_shuffle_off_description);
  320 +// } else {
  321 + //设置底层视图
  322 + baseRootView = LayoutInflater.from(context).inflate(R.layout.layout_cnlive_control_view, /* root= */ this);
  323 + if (null != baseRootView) {
  324 + fl_root = baseRootView.findViewById(R.id.fl_root);
  325 + }
  326 + baseRootView.post(new Runnable() {
  327 + @Override
  328 + public void run() {
  329 + if (-1 != getPortraitControllViewId()) {
  330 + basePortraitView = LayoutInflater.from(context).inflate(getPortraitControllViewId(), /* root= */ null);
  331 + if (null != fl_root && null != basePortraitView) {
  332 + fl_root.addView(basePortraitView);
  333 + }
250 334 }
  335 + if (-1 != getLandscapeControllViewId()) {
  336 + baseLandscapeView = LayoutInflater.from(context).inflate(getLandscapeControllViewId(), /* root= */ null);
  337 + if (null != fl_root && null != baseLandscapeView) {
  338 + fl_root.addView(baseLandscapeView);
  339 + }
  340 + }
  341 + basePortraitView.setVisibility(VISIBLE);
  342 + baseLandscapeView.setVisibility(GONE);
  343 +
  344 + if (null != componentListener && null != basePortraitView) {
  345 + initPortraitView(basePortraitView, componentListener);
  346 + }
  347 +
  348 + baseRootView.setOnClickListener(new OnClickListener() {
  349 + @Override
  350 + public void onClick(View v) {
  351 + //获取当前屏幕朝向
  352 + if (null == newConfig) {
  353 + showPortraitView();
  354 + } else {
  355 + if (null != basePortraitView && null != baseLandscapeView) {
  356 + //当前是竖屏
  357 + if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
  358 + showPortraitView();
  359 + } else {
  360 + showLandscapeView();
  361 + }
  362 + } else {
  363 + showPortraitView();
  364 + }
  365 + }
  366 + }
  367 + });
251 368 }
252   - visibilityListeners = new CopyOnWriteArrayList<>();
253   - period = new Timeline.Period();
254   - window = new Timeline.Window();
255   - formatBuilder = new StringBuilder();
256   - formatter = new Formatter(formatBuilder, Locale.getDefault());
257   - adGroupTimesMs = new long[0];
258   - playedAdGroups = new boolean[0];
259   - extraAdGroupTimesMs = new long[0];
260   - extraPlayedAdGroups = new boolean[0];
261   - updateProgressAction = this::updateProgress;
262   - hideAction = this::hide;
263   -
264   - basePortraitView = LayoutInflater.from(context).inflate(controllerLayoutId, /* root= */ this);
265   - setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
266   -
267   - TimeBar customTimeBar = findViewById(R.id.cnlive_progress);
268   - View timeBarPlaceholder = findViewById(R.id.cnlive_progress_placeholder);
269   - if (customTimeBar != null) {
270   - timeBar = customTimeBar;
271   - } else if (timeBarPlaceholder != null) {
272   - // Propagate attrs as timebarAttrs so that DefaultTimeBar's custom attributes are transferred,
273   - // but standard attributes (e.g. background) are not.
274   - BaseTimerBar defaultTimeBar = new BaseTimerBar(context, null, 0, playbackAttrs);
275   - //todo 设置播放的颜色
276   -// defaultTimeBar.setPlayedColor(ContextCompat.getColor(context,R.color.qmui_config_color_red));
277   - //todo 设置缓冲颜色
278   -// defaultTimeBar.setBufferedColor(ContextCompat.getColor(context,R.color.qmui_config_color_red));
279   - defaultTimeBar.setId(R.id.cnlive_progress);
280   - defaultTimeBar.setLayoutParams(timeBarPlaceholder.getLayoutParams());
281   - ViewGroup parent = ((ViewGroup) timeBarPlaceholder.getParent());
282   - int timeBarIndex = parent.indexOfChild(timeBarPlaceholder);
283   - parent.removeView(timeBarPlaceholder);
284   - parent.addView(defaultTimeBar, timeBarIndex);
285   - timeBar = defaultTimeBar;
286   - } else {
287   - timeBar = null;
288   - }
289   - durationView = findViewById(R.id.cnlive_duration);
290   - positionView = findViewById(R.id.cnlive_position);
291   - //初始化顶部视图
292   - //顶部标题
293   - tvTopViewTitle = findViewById(R.id.cnlive_top_title);
294   - //设置标题名称
295   - if (null != tvTopViewTitle) {
296   - tvTopViewTitle.setText("测试");
297   - }
298   - if (timeBar != null) {
299   - timeBar.addListener(componentListener);
300   - }
301   - playButton = findViewById(R.id.cnlive_play);
302   - if (playButton != null) {
303   - playButton.setOnClickListener(componentListener);
304   - }
305   - pauseButton = findViewById(R.id.cnlive_pause);
306   - if (pauseButton != null) {
307   - pauseButton.setOnClickListener(componentListener);
308   - }
309   - previousButton = findViewById(R.id.cnlive_prev);
310   - if (previousButton != null) {
311   - previousButton.setOnClickListener(componentListener);
312   - }
313   - nextButton = findViewById(R.id.cnlive_next);
314   - if (nextButton != null) {
315   - nextButton.setOnClickListener(componentListener);
316   - }
317   - rewindButton = findViewById(R.id.cnlive_rew);
318   - if (rewindButton != null) {
319   - rewindButton.setOnClickListener(componentListener);
320   - }
321   - fastForwardButton = findViewById(R.id.cnlive_ffwd);
322   - if (fastForwardButton != null) {
323   - fastForwardButton.setOnClickListener(componentListener);
324   - }
325   - repeatToggleButton = findViewById(R.id.cnlive_repeat_toggle);
326   - if (repeatToggleButton != null) {
327   - repeatToggleButton.setOnClickListener(componentListener);
328   - }
329   - repeatToggleButton.setVisibility(GONE);
330   - shuffleButton = findViewById(R.id.cnlive_shuffle);
331   - if (shuffleButton != null) {
332   - shuffleButton.setOnClickListener(componentListener);
333   - }
334   - //初始化横竖屏切换
335   - switchScreenButton = findViewById(R.id.cnlive_switch_screen);
336   - if (switchScreenButton != null) {
337   - switchScreenButton.setOnClickListener(componentListener);
338   - }
339   - vrButton = findViewById(R.id.cnlive_vr);
340   - setShowVrButton(false);
341   -
342   - Resources resources = context.getResources();
343   -
344   - buttonAlphaEnabled =
345   - (float) resources.getInteger(R.integer.exo_media_button_opacity_percentage_enabled) / 100;
346   - buttonAlphaDisabled =
347   - (float) resources.getInteger(R.integer.exo_media_button_opacity_percentage_disabled) / 100;
348   -
349   - repeatOffButtonDrawable = resources.getDrawable(R.drawable.exo_controls_repeat_off);
350   - repeatOneButtonDrawable = resources.getDrawable(R.drawable.exo_controls_repeat_one);
351   - repeatAllButtonDrawable = resources.getDrawable(R.drawable.exo_controls_repeat_all);
352   - shuffleOnButtonDrawable = resources.getDrawable(R.drawable.exo_controls_shuffle_on);
353   - shuffleOffButtonDrawable = resources.getDrawable(R.drawable.exo_controls_shuffle_off);
354   - repeatOffButtonContentDescription =
355   - resources.getString(R.string.exo_controls_repeat_off_description);
356   - repeatOneButtonContentDescription =
357   - resources.getString(R.string.exo_controls_repeat_one_description);
358   - repeatAllButtonContentDescription =
359   - resources.getString(R.string.exo_controls_repeat_all_description);
360   - shuffleOnContentDescription = resources.getString(R.string.exo_controls_shuffle_on_description);
361   - shuffleOffContentDescription =
362   - resources.getString(R.string.exo_controls_shuffle_off_description);
  369 +
  370 + });
  371 +
  372 + }
  373 +
  374 + /**
  375 + * 获取初始化时间
  376 + *
  377 + * @return
  378 + */
  379 + public String getInitTime() {
  380 + long durationMs = C.usToMs(0);
  381 + return Util.getStringForTime(formatBuilder, formatter, durationMs);
  382 + }
  383 +
  384 + /**
  385 + * 显示横屏
  386 + */
  387 + private void showLandscapeView() {
  388 + if (null == baseLandscapeView) {
  389 + return;
  390 + }
  391 + if (baseLandscapeView.getVisibility() == View.VISIBLE) {
  392 + baseLandscapeView.setVisibility(View.GONE);
363 393 } else {
364   - basePortraitView = LayoutInflater.from(context).inflate(getControllViewId(), /* root= */ this);
  394 + baseLandscapeView.setVisibility(View.VISIBLE);
365 395 }
366 396  
367   - if (null != componentListener && null != basePortraitView) {
368   - initPortraitView(basePortraitView, componentListener);
  397 + if (null != basePortraitView) {
  398 + basePortraitView.setVisibility(View.GONE);
369 399 }
  400 +
370 401 }
371 402  
  403 + /**
  404 + * 显示竖屏
  405 + */
  406 + private void showPortraitView() {
  407 + if (null == basePortraitView) {
  408 + return;
  409 + }
  410 + if (basePortraitView.getVisibility() == View.VISIBLE) {
  411 + basePortraitView.setVisibility(View.GONE);
  412 + } else {
  413 + basePortraitView.setVisibility(View.VISIBLE);
  414 + }
  415 + if (null != baseLandscapeView) {
  416 + baseLandscapeView.setVisibility(GONE);
  417 + }
  418 + }
372 419  
373 420 protected abstract void initPortraitView(View basePortraitView, CNLiveBaseVideoControlView.ComponentListener onClickListener);
374 421  
... ... @@ -402,29 +449,17 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
402 449 if (this.player == player) {
403 450 return;
404 451 }
405   - if (this.player != null && null != componentListener) {
406   - this.player.removeListener(componentListener);
407   - }
408 452 this.player = player;
409   - if (player != null && null != componentListener) {
410   - player.addListener(componentListener);
  453 + if (null == player) {
  454 + return;
411 455 }
412   - updateAll();
413   - }
  456 + player.removeAnalyticsListener(this);
  457 + player.addAnalyticsListener(this);
414 458  
415   - /**
416   - * Sets whether the time bar should show all windows, as opposed to just the current one. If the
417   - * timeline has a period with unknown duration or more than {@link
418   - * #MAX_WINDOWS_FOR_MULTI_WINDOW_TIME_BAR} windows the time bar will fall back to showing a single
419   - * window.
420   - *
421   - * @param showMultiWindowTimeBar Whether the time bar should show all windows.
422   - */
423   - public void setShowMultiWindowTimeBar(boolean showMultiWindowTimeBar) {
424   - this.showMultiWindowTimeBar = showMultiWindowTimeBar;
425   - updateTimeline();
  459 +// updateAll();
426 460 }
427 461  
  462 +
428 463 /**
429 464 * Sets the millisecond positions of extra ad markers relative to the start of the window (or
430 465 * timeline, if in multi-window mode) and whether each extra ad has been played or not. The
... ... @@ -437,16 +472,15 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
437 472 */
438 473 public void setExtraAdGroupMarkers(
439 474 @Nullable long[] extraAdGroupTimesMs, @Nullable boolean[] extraPlayedAdGroups) {
440   - if (extraAdGroupTimesMs == null) {
441   - this.extraAdGroupTimesMs = new long[0];
442   - this.extraPlayedAdGroups = new boolean[0];
443   - } else {
444   - extraPlayedAdGroups = Assertions.checkNotNull(extraPlayedAdGroups);
445   - Assertions.checkArgument(extraAdGroupTimesMs.length == extraPlayedAdGroups.length);
446   - this.extraAdGroupTimesMs = extraAdGroupTimesMs;
447   - this.extraPlayedAdGroups = extraPlayedAdGroups;
448   - }
449   - updateTimeline();
  475 +// if (extraAdGroupTimesMs == null) {
  476 +// this.extraAdGroupTimesMs = new long[0];
  477 +// this.extraPlayedAdGroups = new boolean[0];
  478 +// } else {
  479 +// extraPlayedAdGroups = Assertions.checkNotNull(extraPlayedAdGroups);
  480 +// Assertions.checkArgument(extraAdGroupTimesMs.length == extraPlayedAdGroups.length);
  481 +// this.extraAdGroupTimesMs = extraAdGroupTimesMs;
  482 +// this.extraPlayedAdGroups = extraPlayedAdGroups;
  483 +// }
450 484 }
451 485  
452 486 /**
... ... @@ -455,7 +489,9 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
455 489 * @param listener The listener to be notified about visibility changes.
456 490 */
457 491 public void addVisibilityListener(CNLiveBaseVideoControlView.VisibilityListener listener) {
458   - visibilityListeners.add(listener);
  492 + if (null != listener) {
  493 + visibilityListeners.add(listener);
  494 + }
459 495 }
460 496  
461 497 /**
... ... @@ -477,172 +513,76 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
477 513  
478 514 }
479 515  
480   - /**
481   - * Sets the {@link PlaybackPreparer}.
482   - *
483   - * @param playbackPreparer The {@link PlaybackPreparer}, or null to remove the current playback
484   - * preparer.
485   - */
486   - public void setPlaybackPreparer(@Nullable PlaybackPreparer playbackPreparer) {
487   - this.playbackPreparer = playbackPreparer;
488   - }
489   -
490   -// /**
491   -// * Sets the {@link com.google.android.exoplayer2.ControlDispatcher}.
492   -// *
493   -// * @param controlDispatcher The {@link com.google.android.exoplayer2.ControlDispatcher}, or null
494   -// * to use {@link com.google.android.exoplayer2.DefaultControlDispatcher}.
495   -// */
496   -// public void setControlDispatcher(
497   -// @Nullable CNLiveControlDispatcher controlDispatcher) {
498   -// this.controlDispatcher =
499   -// controlDispatcher == null
500   -// ? new CNLiveDefaultControlDispatcher()
501   -// : controlDispatcher;
502   -// }
503   -
504   - /**
505   - * Sets the rewind increment in milliseconds.
506   - *
507   - * @param rewindMs The rewind increment in milliseconds. A non-positive value will cause the
508   - * rewind button to be disabled.
509   - */
510   - public void setRewindIncrementMs(int rewindMs) {
511   - this.rewindMs = rewindMs;
512   - updateNavigation();
513   - }
514   -
515   - /**
516   - * Sets the fast forward increment in milliseconds.
517   - *
518   - * @param fastForwardMs The fast forward increment in milliseconds. A non-positive value will
519   - * cause the fast forward button to be disabled.
520   - */
521   - public void setFastForwardIncrementMs(int fastForwardMs) {
522   - this.fastForwardMs = fastForwardMs;
523   - updateNavigation();
524   - }
525   -
526   - /**
527   - * Returns the playback controls timeout. The playback controls are automatically hidden after
528   - * this duration of time has elapsed without user input.
529   - *
530   - * @return The duration in milliseconds. A non-positive value indicates that the controls will
531   - * remain visible indefinitely.
532   - */
533   - public int getShowTimeoutMs() {
534   - return showTimeoutMs;
535   - }
536   -
537   - /**
538   - * Sets the playback controls timeout. The playback controls are automatically hidden after this
539   - * duration of time has elapsed without user input.
540   - *
541   - * @param showTimeoutMs The duration in milliseconds. A non-positive value will cause the controls
542   - * to remain visible indefinitely.
543   - */
544   - public void setShowTimeoutMs(int showTimeoutMs) {
545   - this.showTimeoutMs = showTimeoutMs;
546   - if (isVisible()) {
547   - // Reset the timeout.
548   - hideAfterTimeout();
549   - }
550   - }
551   -
552   - /**
553   - * Returns which repeat toggle modes are enabled.
554   - *
555   - * @return The currently enabled {@link RepeatModeUtil.RepeatToggleModes}.
556   - */
557   - public @RepeatModeUtil.RepeatToggleModes
558   - int getRepeatToggleModes() {
559   - return repeatToggleModes;
560   - }
561 516  
562 517 /**
563 518 * Sets which repeat toggle modes are enabled.
564 519 *
565 520 * @param repeatToggleModes A set of {@link RepeatModeUtil.RepeatToggleModes}.
566 521 */
567   - public void setRepeatToggleModes(@RepeatModeUtil.RepeatToggleModes int repeatToggleModes) {
568   - this.repeatToggleModes = repeatToggleModes;
569   - if (player != null) {
570   - @Player.RepeatMode int currentMode = player.getRepeatMode();
571   - if (repeatToggleModes == RepeatModeUtil.REPEAT_TOGGLE_MODE_NONE
572   - && currentMode != Player.REPEAT_MODE_OFF) {
573   - setPlayerRepeatMode(Player.REPEAT_MODE_OFF);
574   - } else if (repeatToggleModes == RepeatModeUtil.REPEAT_TOGGLE_MODE_ONE
575   - && currentMode == Player.REPEAT_MODE_ALL) {
576   - setPlayerRepeatMode(Player.REPEAT_MODE_ONE);
577   - } else if (repeatToggleModes == RepeatModeUtil.REPEAT_TOGGLE_MODE_ALL
578   - && currentMode == Player.REPEAT_MODE_ONE) {
579   - setPlayerRepeatMode(Player.REPEAT_MODE_ALL);
580   - }
581   - }
582   -// updateRepeatModeButton();
583   - }
  522 +// public void setRepeatToggleModes(@RepeatModeUtil.RepeatToggleModes int repeatToggleModes) {
  523 +// this.repeatToggleModes = repeatToggleModes;
  524 +// if (player != null) {
  525 +// @Player.RepeatMode int currentMode = player.getRepeatMode();
  526 +// if (repeatToggleModes == RepeatModeUtil.REPEAT_TOGGLE_MODE_NONE
  527 +// && currentMode != Player.REPEAT_MODE_OFF) {
  528 +// setPlayerRepeatMode(Player.REPEAT_MODE_OFF);
  529 +// } else if (repeatToggleModes == RepeatModeUtil.REPEAT_TOGGLE_MODE_ONE
  530 +// && currentMode == Player.REPEAT_MODE_ALL) {
  531 +// setPlayerRepeatMode(Player.REPEAT_MODE_ONE);
  532 +// } else if (repeatToggleModes == RepeatModeUtil.REPEAT_TOGGLE_MODE_ALL
  533 +// && currentMode == Player.REPEAT_MODE_ONE) {
  534 +// setPlayerRepeatMode(Player.REPEAT_MODE_ALL);
  535 +// }
  536 +// }
  537 +//// updateRepeatModeButton();
  538 +// }
584 539  
585 540 /**
586 541 * Returns whether the shuffle button is shown.
587 542 */
588   - public boolean getShowShuffleButton() {
589   - return showShuffleButton;
590   - }
  543 +// public boolean getShowShuffleButton() {
  544 +// return showShuffleButton;
  545 +// }
591 546  
592 547 /**
593 548 * Sets whether the shuffle button is shown.
594 549 *
595 550 * @param showShuffleButton Whether the shuffle button is shown.
596 551 */
597   - public void setShowShuffleButton(boolean showShuffleButton) {
598   - this.showShuffleButton = showShuffleButton;
599   - updateShuffleButton();
600   - }
  552 +// public void setShowShuffleButton(boolean showShuffleButton) {
  553 +// this.showShuffleButton = showShuffleButton;
  554 +// updateShuffleButton();
  555 +// }
601 556  
602 557 /**
603 558 * Returns whether the VR button is shown.
604 559 */
605   - public boolean getShowVrButton() {
606   - return vrButton != null && vrButton.getVisibility() == VISIBLE;
607   - }
  560 +// public boolean getShowVrButton() {
  561 +// return vrButton != null && vrButton.getVisibility() == VISIBLE;
  562 +// }
608 563  
609 564 /**
610 565 * Sets whether the VR button is shown.
611 566 *
612 567 * @param showVrButton Whether the VR button is shown.
613 568 */
614   - public void setShowVrButton(boolean showVrButton) {
615   - if (vrButton != null) {
616   - vrButton.setVisibility(showVrButton ? VISIBLE : GONE);
617   - }
618   - }
  569 +// public void setShowVrButton(boolean showVrButton) {
  570 +// if (vrButton != null) {
  571 +// vrButton.setVisibility(showVrButton ? VISIBLE : GONE);
  572 +// }
  573 +// }
619 574  
620 575 /**
621 576 * Sets listener for the VR button.
622 577 *
623 578 * @param onClickListener Listener for the VR button, or null to clear the listener.
624 579 */
625   - public void setVrButtonListener(@Nullable OnClickListener onClickListener) {
626   - if (vrButton != null) {
627   - vrButton.setOnClickListener(onClickListener);
628   - }
629   - }
  580 +// public void setVrButtonListener(@Nullable OnClickListener onClickListener) {
  581 +// if (vrButton != null) {
  582 +// vrButton.setOnClickListener(onClickListener);
  583 +// }
  584 +// }
630 585  
631   - /**
632   - * Sets the minimum interval between time bar position updates.
633   - *
634   - * <p>Note that smaller intervals, e.g. 33ms, will result in a smooth movement but will use more
635   - * CPU resources while the time bar is visible, whereas larger intervals, e.g. 200ms, will result
636   - * in a step-wise update with less CPU usage.
637   - *
638   - * @param minUpdateIntervalMs The minimum interval between time bar position updates, in
639   - * milliseconds.
640   - */
641   - public void setTimeBarMinUpdateInterval(int minUpdateIntervalMs) {
642   - // Do not accept values below 16ms (60fps) and larger than the maximum update interval.
643   - timeBarMinUpdateIntervalMs =
644   - Util.constrainValue(minUpdateIntervalMs, 16, MAX_UPDATE_INTERVAL_MS);
645   - }
646 586  
647 587 /**
648 588 * Shows the playback controls. If {@link #getShowTimeoutMs()} is positive then the controls will
... ... @@ -651,22 +591,23 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
651 591 public void show() {
652 592 if (!isVisible()) {
653 593 // setVisibility(VISIBLE);
654   - if (null != basePortraitView) {
655   - basePortraitView.setVisibility(VISIBLE);
656   - }
  594 +
657 595 if (null != baseLandscapeView) {
658 596 baseLandscapeView.setVisibility(GONE);
659 597 }
  598 + if (null != basePortraitView) {
  599 + basePortraitView.setVisibility(VISIBLE);
  600 + }
660 601 if (null != visibilityListeners && visibilityListeners.size() > 0) {
661 602 for (CNLiveBaseVideoControlView.VisibilityListener visibilityListener : visibilityListeners) {
662 603 visibilityListener.onVisibilityChange(getVisibility());
663 604 }
664 605 }
665   - updateAll();
666   - requestPlayPauseFocus();
  606 +// updateAll();
  607 +// requestPlayPauseFocus();
667 608 }
668 609 // Call hideAfterTimeout even if already visible to reset the timeout.
669   - hideAfterTimeout();
  610 +// hideAfterTimeout();
670 611 }
671 612  
672 613 /**
... ... @@ -684,8 +625,8 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
684 625 }
685 626 }
686 627 removeCallbacks(updateProgressAction);
687   - removeCallbacks(hideAction);
688   - hideAtMs = C.TIME_UNSET;
  628 +// removeCallbacks(hideAction);
  629 +// hideAtMs = C.TIME_UNSET;
689 630 }
690 631 }
691 632  
... ... @@ -696,77 +637,77 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
696 637 return getVisibility() == VISIBLE;
697 638 }
698 639  
699   - private void hideAfterTimeout() {
700   - removeCallbacks(hideAction);
701   - if (showTimeoutMs > 0) {
702   - hideAtMs = SystemClock.uptimeMillis() + showTimeoutMs;
703   - if (isAttachedToWindow) {
704   - postDelayed(hideAction, showTimeoutMs);
705   - }
706   - } else {
707   - hideAtMs = C.TIME_UNSET;
708   - }
709   - }
710   -
711   - private void updateAll() {
712   - updatePlayPauseButton();
713   - updateNavigation();
714   -// updateRepeatModeButton();
715   - updateShuffleButton();
716   - updateTimeline();
717   - }
718   -
719   - private void updatePlayPauseButton() {
720   - if (!isVisible() || !isAttachedToWindow) {
721   - return;
722   - }
723   - boolean requestPlayPauseFocus = false;
724   - boolean shouldShowPauseButton = shouldShowPauseButton();
725   - if (playButton != null) {
726   - requestPlayPauseFocus |= shouldShowPauseButton && playButton.isFocused();
727   - playButton.setVisibility(shouldShowPauseButton ? GONE : VISIBLE);
728   - }
729   - if (pauseButton != null) {
730   - requestPlayPauseFocus |= !shouldShowPauseButton && pauseButton.isFocused();
731   - pauseButton.setVisibility(shouldShowPauseButton ? VISIBLE : GONE);
732   - }
733   - if (requestPlayPauseFocus) {
734   - requestPlayPauseFocus();
735   - }
736   - }
  640 +// private void hideAfterTimeout() {
  641 +// removeCallbacks(hideAction);
  642 +// if (showTimeoutMs > 0) {
  643 +// hideAtMs = SystemClock.uptimeMillis() + showTimeoutMs;
  644 +// if (isAttachedToWindow) {
  645 +// postDelayed(hideAction, showTimeoutMs);
  646 +// }
  647 +// } else {
  648 +// hideAtMs = C.TIME_UNSET;
  649 +// }
  650 +// }
737 651  
738   - private void updateNavigation() {
739   - if (!isVisible() || !isAttachedToWindow) {
740   - return;
741   - }
  652 +// private void updateAll() {
  653 +// updatePlayPauseButton();
  654 +// updateNavigation();
  655 +//// updateRepeatModeButton();
  656 +// updateShuffleButton();
  657 +// updateTimeline();
  658 +// }
742 659  
743   - @Nullable VideoPlayer player = this.player;
744   - boolean enableSeeking = false;
745   - boolean enablePrevious = false;
746   - boolean enableRewind = false;
747   - boolean enableFastForward = false;
748   - boolean enableNext = false;
749   - if (player != null) {
750   - Timeline timeline = player.getCurrentTimeline();
751   - if (!timeline.isEmpty() && !player.isPlayingAd()) {
752   - timeline.getWindow(player.getCurrentWindowIndex(), window);
753   - boolean isSeekable = window.isSeekable;
754   - enableSeeking = isSeekable;
755   - enablePrevious = isSeekable || !window.isDynamic || player.hasPrevious();
756   - enableRewind = isSeekable && rewindMs > 0;
757   - enableFastForward = isSeekable && fastForwardMs > 0;
758   - enableNext = window.isDynamic || player.hasNext();
759   - }
760   - }
  660 +// private void updatePlayPauseButton() {
  661 +// if (!isVisible() || !isAttachedToWindow) {
  662 +// return;
  663 +// }
  664 +// boolean requestPlayPauseFocus = false;
  665 +// boolean shouldShowPauseButton = shouldShowPauseButton();
  666 +// if (playButton != null) {
  667 +// requestPlayPauseFocus |= shouldShowPauseButton && playButton.isFocused();
  668 +// playButton.setVisibility(shouldShowPauseButton ? GONE : VISIBLE);
  669 +// }
  670 +// if (pauseButton != null) {
  671 +// requestPlayPauseFocus |= !shouldShowPauseButton && pauseButton.isFocused();
  672 +// pauseButton.setVisibility(shouldShowPauseButton ? VISIBLE : GONE);
  673 +// }
  674 +// if (requestPlayPauseFocus) {
  675 +// requestPlayPauseFocus();
  676 +// }
  677 +// }
761 678  
762   - setButtonEnabled(enablePrevious, previousButton);
763   - setButtonEnabled(enableRewind, rewindButton);
764   - setButtonEnabled(enableFastForward, fastForwardButton);
765   - setButtonEnabled(enableNext, nextButton);
766   - if (timeBar != null) {
767   - timeBar.setEnabled(enableSeeking);
768   - }
769   - }
  679 +// private void updateNavigation() {
  680 +// if (!isVisible() || !isAttachedToWindow) {
  681 +// return;
  682 +// }
  683 +//
  684 +// @Nullable VideoPlayer player = this.player;
  685 +// boolean enableSeeking = false;
  686 +// boolean enablePrevious = false;
  687 +// boolean enableRewind = false;
  688 +// boolean enableFastForward = false;
  689 +// boolean enableNext = false;
  690 +// if (player != null) {
  691 +// Timeline timeline = player.getCurrentTimeline();
  692 +// if (!timeline.isEmpty() && !player.isPlayingAd()) {
  693 +// timeline.getWindow(player.getCurrentWindowIndex(), window);
  694 +// boolean isSeekable = window.isSeekable;
  695 +// enableSeeking = isSeekable;
  696 +// enablePrevious = isSeekable || !window.isDynamic || player.hasPrevious();
  697 +// enableRewind = isSeekable && rewindMs > 0;
  698 +// enableFastForward = isSeekable && fastForwardMs > 0;
  699 +// enableNext = window.isDynamic || player.hasNext();
  700 +// }
  701 +// }
  702 +//
  703 +// setButtonEnabled(enablePrevious, previousButton);
  704 +// setButtonEnabled(enableRewind, rewindButton);
  705 +// setButtonEnabled(enableFastForward, fastForwardButton);
  706 +// setButtonEnabled(enableNext, nextButton);
  707 +// if (timeBar != null) {
  708 +// timeBar.setEnabled(enableSeeking);
  709 +// }
  710 +// }
770 711 //
771 712 // private void updateRepeatModeButton() {
772 713 // if (!isVisible() || !isAttachedToWindow || repeatToggleButton == null) {
... ... @@ -806,167 +747,76 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
806 747 // repeatToggleButton.setVisibility(VISIBLE);
807 748 // }
808 749  
809   - private void updateShuffleButton() {
810   - if (!isVisible() || !isAttachedToWindow || shuffleButton == null) {
811   - return;
812   - }
813   -
814   - @Nullable VideoPlayer player = this.player;
815   - if (!showShuffleButton) {
816   - shuffleButton.setVisibility(GONE);
817   - } else if (player == null) {
818   - setButtonEnabled(false, shuffleButton);
819   - shuffleButton.setImageDrawable(shuffleOffButtonDrawable);
820   - shuffleButton.setContentDescription(shuffleOffContentDescription);
821   - } else {
822   - setButtonEnabled(true, shuffleButton);
823   - shuffleButton.setImageDrawable(
824   - player.getShuffleModeEnabled() ? shuffleOnButtonDrawable : shuffleOffButtonDrawable);
825   - shuffleButton.setContentDescription(
826   - player.getShuffleModeEnabled()
827   - ? shuffleOnContentDescription
828   - : shuffleOffContentDescription);
829   - }
830   - }
  750 +// private void updateShuffleButton() {
  751 +// if (!isVisible() || !isAttachedToWindow || shuffleButton == null) {
  752 +// return;
  753 +// }
  754 +//
  755 +// @Nullable VideoPlayer player = this.player;
  756 +// if (!showShuffleButton) {
  757 +// shuffleButton.setVisibility(GONE);
  758 +// } else if (player == null) {
  759 +// setButtonEnabled(false, shuffleButton);
  760 +// shuffleButton.setImageDrawable(shuffleOffButtonDrawable);
  761 +// shuffleButton.setContentDescription(shuffleOffContentDescription);
  762 +// } else {
  763 +// setButtonEnabled(true, shuffleButton);
  764 +// shuffleButton.setImageDrawable(
  765 +// player.getShuffleModeEnabled() ? shuffleOnButtonDrawable : shuffleOffButtonDrawable);
  766 +// shuffleButton.setContentDescription(
  767 +// player.getShuffleModeEnabled()
  768 +// ? shuffleOnContentDescription
  769 +// : shuffleOffContentDescription);
  770 +// }
  771 +// }
831 772  
832   - private void updateTimeline() {
833   - @Nullable VideoPlayer player = this.player;
834   - if (player == null) {
835   - return;
836   - }
837   - if (null == adGroupTimesMs || null == playedAdGroups) {
838   - return;
839   - }
840   - multiWindowTimeBar =
841   - showMultiWindowTimeBar && canShowMultiWindowTimeBar(player.getCurrentTimeline(), window);
842   - currentWindowOffset = 0;
843   - long durationUs = 0;
844   - int adGroupCount = 0;
845   - Timeline timeline = player.getCurrentTimeline();
846   - if (!timeline.isEmpty()) {
847   - int currentWindowIndex = player.getCurrentWindowIndex();
848   - int firstWindowIndex = multiWindowTimeBar ? 0 : currentWindowIndex;
849   - int lastWindowIndex = multiWindowTimeBar ? timeline.getWindowCount() - 1 : currentWindowIndex;
850   - for (int i = firstWindowIndex; i <= lastWindowIndex; i++) {
851   - if (i == currentWindowIndex) {
852   - currentWindowOffset = C.usToMs(durationUs);
853   - }
854   - timeline.getWindow(i, window);
855   - if (window.durationUs == C.TIME_UNSET) {
856   - Assertions.checkState(!multiWindowTimeBar);
857   - break;
858   - }
859   - for (int j = window.firstPeriodIndex; j <= window.lastPeriodIndex; j++) {
860   - timeline.getPeriod(j, period);
861   - int periodAdGroupCount = period.getAdGroupCount();
862   - for (int adGroupIndex = 0; adGroupIndex < periodAdGroupCount; adGroupIndex++) {
863   - long adGroupTimeInPeriodUs = period.getAdGroupTimeUs(adGroupIndex);
864   - if (adGroupTimeInPeriodUs == C.TIME_END_OF_SOURCE) {
865   - if (period.durationUs == C.TIME_UNSET) {
866   - // Don't show ad markers for postrolls in periods with unknown duration.
867   - continue;
868   - }
869   - adGroupTimeInPeriodUs = period.durationUs;
870   - }
871   - long adGroupTimeInWindowUs = adGroupTimeInPeriodUs + period.getPositionInWindowUs();
872   - if (adGroupTimeInWindowUs >= 0 && adGroupTimeInWindowUs <= window.durationUs) {
873   - if (adGroupCount == adGroupTimesMs.length) {
874   - int newLength = adGroupTimesMs.length == 0 ? 1 : adGroupTimesMs.length * 2;
875   - adGroupTimesMs = Arrays.copyOf(adGroupTimesMs, newLength);
876   - playedAdGroups = Arrays.copyOf(playedAdGroups, newLength);
877   - }
878   - adGroupTimesMs[adGroupCount] = C.usToMs(durationUs + adGroupTimeInWindowUs);
879   - playedAdGroups[adGroupCount] = period.hasPlayedAdGroup(adGroupIndex);
880   - adGroupCount++;
881   - }
882   - }
883   - }
884   - durationUs += window.durationUs;
885   - }
886   - }
887   - long durationMs = C.usToMs(durationUs);
888   - if (durationView != null) {
889   - durationView.setText(Util.getStringForTime(formatBuilder, formatter, durationMs));
890   - }
891   - if (timeBar != null) {
892   - timeBar.setDuration(durationMs);
893   - int extraAdGroupCount = extraAdGroupTimesMs.length;
894   - int totalAdGroupCount = adGroupCount + extraAdGroupCount;
895   - if (totalAdGroupCount > adGroupTimesMs.length) {
896   - adGroupTimesMs = Arrays.copyOf(adGroupTimesMs, totalAdGroupCount);
897   - playedAdGroups = Arrays.copyOf(playedAdGroups, totalAdGroupCount);
898   - }
899   - System.arraycopy(extraAdGroupTimesMs, 0, adGroupTimesMs, adGroupCount, extraAdGroupCount);
900   - System.arraycopy(extraPlayedAdGroups, 0, playedAdGroups, adGroupCount, extraAdGroupCount);
901   - timeBar.setAdGroupTimesMs(adGroupTimesMs, playedAdGroups, totalAdGroupCount);
902   - }
903   - updateProgress();
904   - }
905 773  
  774 + /**
  775 + * 更新进度条
  776 + */
906 777 private void updateProgress() {
907 778 if (!isVisible() || !isAttachedToWindow) {
908 779 return;
909 780 }
910   -
911   - @Nullable VideoPlayer player = this.player;
912 781 long position = 0;
913   - long bufferedPosition = 0;
914 782 if (player != null) {
915   - position = currentWindowOffset + player.getContentPosition();
916   - bufferedPosition = currentWindowOffset + player.getContentBufferedPosition();
917   - }
918   - if (positionView != null && !scrubbing) {
919   - positionView.setText(Util.getStringForTime(formatBuilder, formatter, position));
920   - }
921   - if (timeBar != null) {
922   - timeBar.setPosition(position);
923   - timeBar.setBufferedPosition(bufferedPosition);
  783 + position = player.getContentPosition();
924 784 }
  785 + Log.e(TAG, "updateProgress: " + position);
  786 +// if (positionView != null && !scrubbing) {
  787 +// positionView.setText(Util.getStringForTime(formatBuilder, formatter, position));
  788 +// }
925 789 // if (progressUpdateListener != null) {
926 790 // progressUpdateListener.onProgressUpdate(position, bufferedPosition);
927 791 // }
928   -
929   - // Cancel any pending updates and schedule a new one if necessary.
  792 + //先移除之前的动作
930 793 removeCallbacks(updateProgressAction);
931 794 int playbackState = player == null ? Player.STATE_IDLE : player.getPlaybackState();
  795 + onProgressChange(position, Util.getStringForTime(formatBuilder, formatter, position));
932 796 if (player != null && player.isPlaying()) {
933   - long mediaTimeDelayMs =
934   - timeBar != null ? timeBar.getPreferredUpdateDelay() : MAX_UPDATE_INTERVAL_MS;
935   -
936   - // Limit delay to the start of the next full second to ensure position display is smooth.
937   - long mediaTimeUntilNextFullSecondMs = 1000 - position % 1000;
938   - mediaTimeDelayMs = Math.min(mediaTimeDelayMs, mediaTimeUntilNextFullSecondMs);
939   -
940   - // Calculate the delay until the next update in real time, taking playbackSpeed into account.
941   - float playbackSpeed = player.getPlaybackParameters().speed;
942   - long delayMs =
943   - playbackSpeed > 0 ? (long) (mediaTimeDelayMs / playbackSpeed) : MAX_UPDATE_INTERVAL_MS;
944   -
945   - // Constrain the delay to avoid too frequent / infrequent updates.
946   - delayMs = Util.constrainValue(delayMs, timeBarMinUpdateIntervalMs, MAX_UPDATE_INTERVAL_MS);
947   - postDelayed(updateProgressAction, delayMs);
  797 + postDelayed(updateProgressAction, MAX_UPDATE_INTERVAL_MS);
948 798 } else if (playbackState != Player.STATE_ENDED && playbackState != Player.STATE_IDLE) {
949 799 postDelayed(updateProgressAction, MAX_UPDATE_INTERVAL_MS);
950 800 }
951 801 }
952 802  
953   - private void requestPlayPauseFocus() {
954   - boolean shouldShowPauseButton = shouldShowPauseButton();
955   - if (!shouldShowPauseButton && playButton != null) {
956   - playButton.requestFocus();
957   - } else if (shouldShowPauseButton && pauseButton != null) {
958   - pauseButton.requestFocus();
959   - }
960   - }
961   -
962   - private void setButtonEnabled(boolean enabled, @Nullable View view) {
963   - if (view == null) {
964   - return;
965   - }
966   - view.setEnabled(enabled);
967   - view.setAlpha(enabled ? buttonAlphaEnabled : buttonAlphaDisabled);
968   - view.setVisibility(VISIBLE);
969   - }
  803 +// private void requestPlayPauseFocus() {
  804 +// boolean shouldShowPauseButton = shouldShowPauseButton();
  805 +// if (!shouldShowPauseButton && playButton != null) {
  806 +// playButton.requestFocus();
  807 +// } else if (shouldShowPauseButton && pauseButton != null) {
  808 +// pauseButton.requestFocus();
  809 +// }
  810 +// }
  811 +
  812 +// private void setButtonEnabled(boolean enabled, @Nullable View view) {
  813 +// if (view == null) {
  814 +// return;
  815 +// }
  816 +// view.setEnabled(enabled);
  817 +// view.setAlpha(enabled ? buttonAlphaEnabled : buttonAlphaDisabled);
  818 +// view.setVisibility(VISIBLE);
  819 +// }
970 820  
971 821 private void previous(VideoPlayer player) {
972 822 Timeline timeline = player.getCurrentTimeline();
... ... @@ -1004,14 +854,24 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
1004 854 }
1005 855 }
1006 856  
1007   - public void rewind(VideoPlayer player) {
1008   - if (player.isCurrentWindowSeekable() && rewindMs > 0) {
1009   - seekToOffset(player, -rewindMs);
1010   - }
  857 +// public void rewind(VideoPlayer player) {
  858 +// if (player.isCurrentWindowSeekable() && rewindMs > 0) {
  859 +// seekToOffset(player, -rewindMs);
  860 +// }
  861 +// }
  862 +
  863 +
  864 + /**
  865 + * 移动到指定位置画面
  866 + *
  867 + * @param duration
  868 + */
  869 + public void seekToDuration(long duration) {
  870 + seekTo(player, player.getCurrentWindowIndex(), duration);
1011 871 }
1012 872  
1013 873  
1014   - private void seekToOffset(VideoPlayer player, long offsetMs) {
  874 + private void seekToOffset(long offsetMs) {
1015 875 long positionMs = player.getCurrentPosition() + offsetMs;
1016 876 long durationMs = player.getDuration();
1017 877 if (durationMs != C.TIME_UNSET) {
... ... @@ -1027,35 +887,34 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
1027 887 * @param player
1028 888 * @param positionMs
1029 889 */
1030   - public void seekToTimeBarPosition(VideoPlayer player, long positionMs) {
1031   - int windowIndex;
1032   - Timeline timeline = player.getCurrentTimeline();
1033   - if (multiWindowTimeBar && !timeline.isEmpty()) {
1034   - int windowCount = timeline.getWindowCount();
1035   - windowIndex = 0;
1036   - while (true) {
1037   - long windowDurationMs = timeline.getWindow(windowIndex, window).getDurationMs();
1038   - if (positionMs < windowDurationMs) {
1039   - break;
1040   - } else if (windowIndex == windowCount - 1) {
1041   - // Seeking past the end of the last window should seek to the end of the timeline.
1042   - positionMs = windowDurationMs;
1043   - break;
1044   - }
1045   - positionMs -= windowDurationMs;
1046   - windowIndex++;
1047   - }
1048   - } else {
1049   - windowIndex = player.getCurrentWindowIndex();
1050   - }
1051   - boolean dispatched = seekTo(player, windowIndex, positionMs);
1052   - if (!dispatched) {
1053   - // The seek wasn't dispatched then the progress bar scrubber will be in the wrong position.
1054   - // Trigger a progress update to snap it back.
1055   - updateProgress();
1056   - }
1057   - }
1058   -
  890 +// public void seekToTimeBarPosition(VideoPlayer player, long positionMs) {
  891 +// int windowIndex;
  892 +// Timeline timeline = player.getCurrentTimeline();
  893 +// if (multiWindowTimeBar && !timeline.isEmpty()) {
  894 +// int windowCount = timeline.getWindowCount();
  895 +// windowIndex = 0;
  896 +// while (true) {
  897 +// long windowDurationMs = timeline.getWindow(windowIndex, window).getDurationMs();
  898 +// if (positionMs < windowDurationMs) {
  899 +// break;
  900 +// } else if (windowIndex == windowCount - 1) {
  901 +// // Seeking past the end of the last window should seek to the end of the timeline.
  902 +// positionMs = windowDurationMs;
  903 +// break;
  904 +// }
  905 +// positionMs -= windowDurationMs;
  906 +// windowIndex++;
  907 +// }
  908 +// } else {
  909 +// windowIndex = player.getCurrentWindowIndex();
  910 +// }
  911 +// boolean dispatched = seekTo(player, windowIndex, positionMs);
  912 +// if (!dispatched) {
  913 +// // The seek wasn't dispatched then the progress bar scrubber will be in the wrong position.
  914 +// // Trigger a progress update to snap it back.
  915 +// updateProgress();
  916 +// }
  917 +// }
1059 918 private boolean seekTo(VideoPlayer player, int windowIndex, long positionMs) {
1060 919 player.seekTo(windowIndex, positionMs);
1061 920 return true;
... ... @@ -1065,7 +924,7 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
1065 924 @Override
1066 925 public void onAttachedToWindow() {
1067 926 super.onAttachedToWindow();
1068   -// isAttachedToWindow = true;
  927 + isAttachedToWindow = true;
1069 928 // if (hideAtMs != C.TIME_UNSET) {
1070 929 // long delayMs = hideAtMs - SystemClock.uptimeMillis();
1071 930 // if (delayMs <= 0) {
... ... @@ -1084,18 +943,18 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
1084 943 super.onDetachedFromWindow();
1085 944 isAttachedToWindow = false;
1086 945 removeCallbacks(updateProgressAction);
1087   - removeCallbacks(hideAction);
  946 +// removeCallbacks(hideAction);
1088 947 }
1089 948  
1090   - @Override
1091   - public final boolean dispatchTouchEvent(MotionEvent ev) {
1092   - if (ev.getAction() == MotionEvent.ACTION_DOWN) {
1093   - removeCallbacks(hideAction);
1094   - } else if (ev.getAction() == MotionEvent.ACTION_UP) {
1095   - hideAfterTimeout();
1096   - }
1097   - return super.dispatchTouchEvent(ev);
1098   - }
  949 +// @Override
  950 +// public final boolean dispatchTouchEvent(MotionEvent ev) {
  951 +// if (ev.getAction() == MotionEvent.ACTION_DOWN) {
  952 +// removeCallbacks(hideAction);
  953 +// } else if (ev.getAction() == MotionEvent.ACTION_UP) {
  954 +// hideAfterTimeout();
  955 +// }
  956 +// return super.dispatchTouchEvent(ev);
  957 +// }
1099 958  
1100 959 @Override
1101 960 public boolean dispatchKeyEvent(KeyEvent event) {
... ... @@ -1117,9 +976,9 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
1117 976 }
1118 977 if (event.getAction() == KeyEvent.ACTION_DOWN) {
1119 978 if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
1120   - fastForward(player);
  979 +// fastForward(player);
1121 980 } else if (keyCode == KeyEvent.KEYCODE_MEDIA_REWIND) {
1122   - rewind(player);
  981 +// rewind(player);
1123 982 } else if (event.getRepeatCount() == 0) {
1124 983 switch (keyCode) {
1125 984 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
... ... @@ -1187,103 +1046,44 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
1187 1046 }
1188 1047  
1189 1048 public final class ComponentListener
1190   - implements Player.EventListener, TimeBar.OnScrubListener, OnClickListener {
1191   -
1192   - @Override
1193   - public void onScrubStart(TimeBar timeBar, long position) {
1194   - scrubbing = true;
1195   - if (positionView != null) {
1196   - positionView.setText(Util.getStringForTime(formatBuilder, formatter, position));
1197   - }
1198   - }
1199   -
1200   - @Override
1201   - public void onScrubMove(TimeBar timeBar, long position) {
1202   - if (positionView != null) {
1203   - positionView.setText(Util.getStringForTime(formatBuilder, formatter, position));
1204   - }
1205   - }
1206   -
1207   - @Override
1208   - public void onScrubStop(TimeBar timeBar, long position, boolean canceled) {
1209   - scrubbing = false;
1210   - if (!canceled && player != null) {
1211   - seekToTimeBarPosition(player, position);
1212   - }
1213   - }
1214   -
1215   - @Override
1216   - public void onPlayerStateChanged(boolean playWhenReady, @Player.State int playbackState) {
1217   - updatePlayPauseButton();
1218   - updateProgress();
1219   - }
1220   -
1221   - @Override
1222   - public void onIsPlayingChanged(boolean isPlaying) {
1223   - updateProgress();
1224   - }
1225   -
1226   - @Override
1227   - public void onRepeatModeChanged(int repeatMode) {
1228   -// updateRepeatModeButton();
1229   - updateNavigation();
1230   - }
1231   -
1232   - @Override
1233   - public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
1234   - updateShuffleButton();
1235   - updateNavigation();
1236   - }
1237   -
1238   - @Override
1239   - public void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) {
1240   - updateNavigation();
1241   - updateTimeline();
1242   - }
1243   -
1244   - @Override
1245   - public void onTimelineChanged(Timeline timeline, @Player.TimelineChangeReason int reason) {
1246   - updateNavigation();
1247   - updateTimeline();
1248   - }
1249   -
  1049 + implements OnClickListener {
1250 1050 @Override
1251 1051 public void onClick(View view) {
1252 1052 onViewClick(view);
1253   - VideoPlayer player = CNLiveBaseVideoControlView.this.player;
1254   - if (player == null) {
1255   - return;
1256   - }
1257   - if (nextButton == view) {
1258   - next(player);
1259   - } else if (previousButton == view) {
1260   - previous(player);
1261   - } else if (fastForwardButton == view) {
1262   - fastForward(player);
1263   - } else if (rewindButton == view) {
1264   - rewind(player);
1265   - } else if (playButton == view) {
1266   - if (player.getPlaybackState() == Player.STATE_IDLE) {
1267   - if (playbackPreparer != null) {
1268   - playbackPreparer.preparePlayback();
1269   - }
1270   - } else if (player.getPlaybackState() == Player.STATE_ENDED) {
1271   - seekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET);
1272   - }
1273   - playVideo();
1274   - } else if (pauseButton == view) {
1275   - pauseVideo();
1276   - } else if (repeatToggleButton == view) {
1277   - setPlayerRepeatMode(Player.REPEAT_MODE_ONE);
1278   -
1279   -// setRepeatToggleModes(RepeatModeUtil.REPEAT_TOGGLE_MODE_ONE);
1280   - } else if (shuffleButton == view) {
1281   - setShuffleModeEnabled(!player.getShuffleModeEnabled());
1282   - }
1283   - //横竖屏切换
1284   - else if (switchScreenButton == view) {
1285   - switchScreenDirection();
1286   - }
  1053 +// VideoPlayer player = CNLiveBaseVideoControlView.this.player;
  1054 +// if (player == null) {
  1055 +// return;
  1056 +// }
  1057 +// if (nextButton == view) {
  1058 +// next(player);
  1059 +// } else if (previousButton == view) {
  1060 +// previous(player);
  1061 +// } else if (fastForwardButton == view) {
  1062 +// fastForward(player);
  1063 +// } else if (rewindButton == view) {
  1064 +// rewind(player);
  1065 +// } else if (playButton == view) {
  1066 +// if (player.getPlaybackState() == Player.STATE_IDLE) {
  1067 +// if (playbackPreparer != null) {
  1068 +// playbackPreparer.preparePlayback();
  1069 +// }
  1070 +// } else if (player.getPlaybackState() == Player.STATE_ENDED) {
  1071 +// seekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET);
  1072 +// }
  1073 +// playVideo();
  1074 +// } else if (pauseButton == view) {
  1075 +// pauseVideo();
  1076 +// } else if (repeatToggleButton == view) {
  1077 +// setPlayerRepeatMode(Player.REPEAT_MODE_ONE);
  1078 +//
  1079 +//// setRepeatToggleModes(RepeatModeUtil.REPEAT_TOGGLE_MODE_ONE);
  1080 +// } else if (shuffleButton == view) {
  1081 +// setShuffleModeEnabled(!player.getShuffleModeEnabled());
  1082 +// }
  1083 +// //横竖屏切换
  1084 +// else if (switchScreenButton == view) {
  1085 +// switchScreenDirection();
  1086 +// }
1287 1087 }
1288 1088 }
1289 1089  
... ... @@ -1318,64 +1118,58 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
1318 1118 Configuration mConfiguration = activity.getResources().getConfiguration(); //获取设置的配置信息
1319 1119 int ori = mConfiguration.orientation; //获取屏幕方向
1320 1120 if (ori == mConfiguration.ORIENTATION_LANDSCAPE) {
1321   - if (null != baseLandscapeView) {
1322   - baseLandscapeView.setVisibility(GONE);
1323   - }
1324   - if (null != basePortraitView) {
1325   - basePortraitView.setVisibility(VISIBLE);
1326   - }
1327 1121 //强制为竖屏
1328 1122 activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
1329   - //显示状态栏
1330   - WindowManager.LayoutParams attr = activity.getWindow().getAttributes();
1331   - attr.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN);
1332   - activity.getWindow().setAttributes(attr);
1333   - activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
1334   -
1335 1123 } else if (ori == mConfiguration.ORIENTATION_PORTRAIT) {
1336   - if (null == baseLandscapeView) {
1337   - //切换布局
1338   - baseLandscapeView = LayoutInflater.from(context).inflate(controllerLayoutId, /* root= */ null);
1339   - }
1340   - if (null != basePortraitView) {
1341   - basePortraitView.setVisibility(GONE);
1342   - }
1343   - if (null != baseLandscapeView) {
1344   - baseLandscapeView.setVisibility(VISIBLE);
1345   - }
1346   - //竖屏
1347   - activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//强制为横屏
1348   - //隐藏状态栏
1349   - WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
1350   - lp.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
1351   - activity.getWindow().setAttributes(lp);
1352   - activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
  1124 + //强制为横屏
  1125 + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
1353 1126 }
1354 1127 }
1355 1128 }
1356 1129  
  1130 + @Override
  1131 + protected void onConfigurationChanged(Configuration newConfig) {
  1132 + super.onConfigurationChanged(newConfig);
  1133 + this.newConfig = newConfig;
  1134 + //竖屏
  1135 + if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
  1136 + showPortraitView();
  1137 +// if (null != baseLandscapeView) {
  1138 +// baseLandscapeView.setVisibility(GONE);
  1139 +// }
  1140 +// if (null != basePortraitView) {
  1141 +// basePortraitView.setVisibility(VISIBLE);
  1142 +// }
  1143 + }
  1144 + //横屏
  1145 + else {
  1146 + //隐藏状态栏
  1147 + showLandscapeView();
  1148 + }
  1149 + }
  1150 +
1357 1151 /**
1358 1152 * 设置播放进度条的颜色
1359 1153 *
1360 1154 * @param color
1361 1155 */
1362   - public void setPlayedColor(@ColorInt int color) {
1363   - if (null != timeBar && timeBar instanceof BaseTimerBar) {
1364   - BaseTimerBar baseTimerBar = (BaseTimerBar) timeBar;
1365   - baseTimerBar.setPlayedColor(color);
1366   - }
1367   - }
  1156 +// public void setPlayedColor(@ColorInt int color) {
  1157 +// if (null != timeBar && timeBar instanceof BaseTimerBar) {
  1158 +// BaseTimerBar baseTimerBar = (BaseTimerBar) timeBar;
  1159 +// baseTimerBar.setPlayedColor(color);
  1160 +// }
  1161 +// }
1368 1162  
1369 1163 /**
1370 1164 * 快进视频
1371 1165 *
1372 1166 * @param player
1373 1167 */
1374   - public void fastForward(VideoPlayer player) {
1375   - if (player.isCurrentWindowSeekable() && fastForwardMs > 0) {
1376   - seekToOffset(player, fastForwardMs);
1377   - }
1378   - }
  1168 +// public void fastForward(VideoPlayer player) {
  1169 +// if (player.isCurrentWindowSeekable() && fastForwardMs > 0) {
  1170 +// seekToOffset(player, fastForwardMs);
  1171 +// }
  1172 +// }
1379 1173  
1380 1174 /**
1381 1175 * 播放视频
... ... @@ -1384,6 +1178,7 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
1384 1178 if (null == player) {
1385 1179 return;
1386 1180 }
  1181 +
1387 1182 player.play();
1388 1183 // if (null == controlDispatcher || null == player) {
1389 1184 // return;
... ... @@ -1408,4 +1203,302 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout {
1408 1203 public boolean isPlaying() {
1409 1204 return player == null ? false : player.isPlaying();
1410 1205 }
  1206 +
  1207 +
  1208 + /**
  1209 + * 按下返回键
  1210 + */
  1211 + public void onBackPress() {
  1212 + if (null != newConfig) {
  1213 + if (null != basePortraitView && null != baseLandscapeView) {
  1214 + //当前是横屏
  1215 + if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
  1216 + //切换至竖屏
  1217 + switchScreenDirection();
  1218 + } else {
  1219 + if (null != activity) {
  1220 + activity.finish();
  1221 + }
  1222 + }
  1223 + } else {
  1224 + if (null != activity) {
  1225 + activity.finish();
  1226 + }
  1227 + }
  1228 + } else if (null != activity) {
  1229 + activity.finish();
  1230 + }
  1231 + }
  1232 +
  1233 + /**
  1234 + * 获取播放时间
  1235 + *
  1236 + * @return
  1237 + */
  1238 + public long getDuration() {
  1239 + if (null != player) {
  1240 + return player.getDuration();
  1241 + } else {
  1242 + return 0;
  1243 + }
  1244 + }
  1245 +
  1246 + /**获取格式化后的时间
  1247 + * @param duration
  1248 + * @return
  1249 + */
  1250 + public final String getFormatDuration(long duration) {
  1251 + return Util.getStringForTime(formatBuilder, formatter, duration);
  1252 + }
  1253 +
  1254 + /**
  1255 + * 进度条改变
  1256 + *
  1257 + * @param position
  1258 + * @param durationStr
  1259 + */
  1260 + public abstract void onProgressChange(long position, String durationStr);
  1261 +
  1262 + /**
  1263 + * 视频缓冲改变
  1264 + *
  1265 + * @param buffer
  1266 + */
  1267 + public abstract void onVideoBufferChange(long buffer);
  1268 +
  1269 + /**
  1270 + * 获取当前播放时长
  1271 + *
  1272 + * @param durationStr
  1273 + */
  1274 + public abstract void onDurationFinish(long duration, String durationStr);
  1275 +
  1276 + /**************************************详细监听*************************************/
  1277 + @Override
  1278 + public void onPlayerStateChanged(EventTime eventTime, boolean playWhenReady, int playbackState) {
  1279 + updateProgress();
  1280 + }
  1281 +
  1282 + @Override
  1283 + public void onPlaybackSuppressionReasonChanged(EventTime eventTime, int playbackSuppressionReason) {
  1284 + Log.e(TAG, "onPlaybackSuppressionReasonChanged");
  1285 + }
  1286 +
  1287 + @Override
  1288 + public void onIsPlayingChanged(EventTime eventTime, boolean isPlaying) {
  1289 + Log.e(TAG, "onIsPlayingChanged");
  1290 + //更新进度条
  1291 + updateProgress();
  1292 + }
  1293 +
  1294 + @Override
  1295 + public void onTimelineChanged(EventTime eventTime, int reason) {
  1296 + Log.e(TAG, "onTimelineChanged: 已更改的时间");
  1297 + }
  1298 +
  1299 + @Override
  1300 + public void onPositionDiscontinuity(EventTime eventTime, int reason) {
  1301 + Log.e(TAG, "onPositionDiscontinuity:非定位连续性 ");
  1302 + }
  1303 +
  1304 + @Override
  1305 + public void onSeekStarted(EventTime eventTime) {
  1306 + Log.e(TAG, "onSeekStarted:开始seek ");
  1307 + }
  1308 +
  1309 + @Override
  1310 + public void onSeekProcessed(EventTime eventTime) {
  1311 + Log.e(TAG, "onSeekProcessed: seek 处理");
  1312 + }
  1313 +
  1314 + @Override
  1315 + public void onPlaybackParametersChanged(EventTime eventTime, PlaybackParameters playbackParameters) {
  1316 + Log.e(TAG, "onPlaybackParametersChanged: 播放参数更改时");
  1317 + }
  1318 +
  1319 + @Override
  1320 + public void onRepeatModeChanged(EventTime eventTime, int repeatMode) {
  1321 + Log.e(TAG, "onRepeatModeChanged: 重复模式更改时");
  1322 + }
  1323 +
  1324 + @Override
  1325 + public void onShuffleModeChanged(EventTime eventTime, boolean shuffleModeEnabled) {
  1326 + Log.e(TAG, "onShuffleModeChanged:论分流模式的改变 ");
  1327 + }
  1328 +
  1329 + @Override
  1330 + public void onLoadingChanged(EventTime eventTime, boolean isLoading) {
  1331 + Log.e(TAG, "onLoadingChanged: 加载时更改");
  1332 + }
  1333 +
  1334 + @Override
  1335 + public void onPlayerError(EventTime eventTime, ExoPlaybackException error) {
  1336 + Log.e(TAG, "onPlayerError: ");
  1337 + }
  1338 +
  1339 + @Override
  1340 + public void onTracksChanged(EventTime eventTime, TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
  1341 + Log.e(TAG, "onTracksChanged: 在更改的轨道上");
  1342 + }
  1343 +
  1344 + @Override
  1345 + public void onLoadStarted(EventTime eventTime, MediaSourceEventListener.LoadEventInfo loadEventInfo, MediaSourceEventListener.MediaLoadData mediaLoadData) {
  1346 + Log.e(TAG, "onLoadStarted: 加载启动");
  1347 + }
  1348 +
  1349 + @Override
  1350 + public void onLoadCompleted(EventTime eventTime, MediaSourceEventListener.LoadEventInfo loadEventInfo, MediaSourceEventListener.MediaLoadData mediaLoadData) {
  1351 + if (null == player) {
  1352 + return;
  1353 + }
  1354 + //设置当前视频总长度
  1355 + long realDurationMillis = player.getDuration();
  1356 + if (realDurationMillis >= 0) {
  1357 + onDurationFinish(realDurationMillis, Util.getStringForTime(formatBuilder, formatter, realDurationMillis));
  1358 + //设置缓冲进度
  1359 + if (player.getContentBufferedPosition() >= 0 && player.getContentBufferedPosition() <= player.getDuration()) {
  1360 + onVideoBufferChange(player.getContentBufferedPosition());
  1361 + }
  1362 + }
  1363 + }
  1364 +
  1365 + @Override
  1366 + public void onLoadCanceled(EventTime eventTime, MediaSourceEventListener.LoadEventInfo loadEventInfo, MediaSourceEventListener.MediaLoadData mediaLoadData) {
  1367 + Log.e(TAG, "onLoadCanceled:已取消加载 ");
  1368 + }
  1369 +
  1370 + @Override
  1371 + public void onLoadError(EventTime eventTime, MediaSourceEventListener.LoadEventInfo loadEventInfo, MediaSourceEventListener.MediaLoadData mediaLoadData, IOException error, boolean wasCanceled) {
  1372 + Log.e(TAG, "onLoadError: ");
  1373 + }
  1374 +
  1375 + @Override
  1376 + public void onDownstreamFormatChanged(EventTime eventTime, MediaSourceEventListener.MediaLoadData mediaLoadData) {
  1377 + Log.e(TAG, "onDownstreamFormatChanged: 下游格式更改时");
  1378 + }
  1379 +
  1380 + @Override
  1381 + public void onUpstreamDiscarded(EventTime eventTime, MediaSourceEventListener.MediaLoadData mediaLoadData) {
  1382 + Log.e(TAG, "onUpstreamDiscarded: \n" +
  1383 + "上游废弃");
  1384 + }
  1385 +
  1386 + @Override
  1387 + public void onMediaPeriodCreated(EventTime eventTime) {
  1388 + Log.e(TAG, "onMediaPeriodCreated: 创建的媒体时段");
  1389 + }
  1390 +
  1391 + @Override
  1392 + public void onMediaPeriodReleased(EventTime eventTime) {
  1393 + Log.e(TAG, "onMediaPeriodReleased: 关于媒体发布期");
  1394 + }
  1395 +
  1396 + @Override
  1397 + public void onReadingStarted(EventTime eventTime) {
  1398 + Log.e(TAG, "onReadingStarted");
  1399 +
  1400 + }
  1401 +
  1402 + @Override
  1403 + public void onBandwidthEstimate(EventTime eventTime, int totalLoadTimeMs, long totalBytesLoaded, long bitrateEstimate) {
  1404 + Log.e(TAG, "onBandwidthEstimate: 带宽估计 总加载时间" + totalLoadTimeMs + " 已加载的字节总数" + totalBytesLoaded + "应该是网速" + bitrateEstimate / (1024 * 1024));
  1405 +
  1406 + }
  1407 +
  1408 + @Override
  1409 + public void onSurfaceSizeChanged(EventTime eventTime, int width, int height) {
  1410 + Log.e(TAG, "onSurfaceSizeChanged: " + width + "------" + height);
  1411 + }
  1412 +
  1413 + @Override
  1414 + public void onMetadata(EventTime eventTime, Metadata metadata) {
  1415 + Log.e(TAG, "onMetadata: 元数据");
  1416 + }
  1417 +
  1418 + @Override
  1419 + public void onDecoderEnabled(EventTime eventTime, int trackType, DecoderCounters decoderCounters) {
  1420 + Log.e(TAG, "onDecoderEnabled:启用解码器时 ");
  1421 + }
  1422 +
  1423 + @Override
  1424 + public void onDecoderInitialized(EventTime eventTime, int trackType, String decoderName, long initializationDurationMs) {
  1425 + Log.e(TAG, "onDecoderInitialized: 解码器初始化时");
  1426 + }
  1427 +
  1428 + @Override
  1429 + public void onDecoderInputFormatChanged(EventTime eventTime, int trackType, Format format) {
  1430 + Log.e(TAG, "onDecoderInputFormatChanged:解码器输入格式更改时 ");
  1431 + }
  1432 +
  1433 + @Override
  1434 + public void onDecoderDisabled(EventTime eventTime, int trackType, DecoderCounters decoderCounters) {
  1435 + Log.e(TAG, "onDecoderDisabled:已禁用解码器 ");
  1436 + }
  1437 +
  1438 + @Override
  1439 + public void onAudioSessionId(EventTime eventTime, int audioSessionId) {
  1440 + Log.e(TAG, "onAudioSessionId: 在音频会话ID上");
  1441 + }
  1442 +
  1443 + @Override
  1444 + public void onAudioAttributesChanged(EventTime eventTime, AudioAttributes audioAttributes) {
  1445 + Log.e(TAG, "onAudioAttributesChanged: 音频属性改变");
  1446 + }
  1447 +
  1448 + @Override
  1449 + public void onVolumeChanged(EventTime eventTime, float volume) {
  1450 + Log.e(TAG, "onVolumeChanged: 音量改变时");
  1451 + }
  1452 +
  1453 + @Override
  1454 + public void onAudioUnderrun(EventTime eventTime, int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
  1455 + Log.e(TAG, "onAudioUnderrun: 在音频欠载运行时");
  1456 + }
  1457 +
  1458 + @Override
  1459 + public void onDroppedVideoFrames(EventTime eventTime, int droppedFrames, long elapsedMs) {
  1460 + Log.e(TAG, "onDroppedVideoFrames:在丢弃的视频帧上 ");
  1461 + }
  1462 +
  1463 + @Override
  1464 + public void onVideoSizeChanged(EventTime eventTime, int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
  1465 +
  1466 + }
  1467 +
  1468 + @Override
  1469 + public void onRenderedFirstFrame(EventTime eventTime, @Nullable Surface surface) {
  1470 + Log.e(TAG, "onRenderedFirstFrame: 在渲染的第一帧上");
  1471 + }
  1472 +
  1473 + @Override
  1474 + public void onDrmSessionAcquired(EventTime eventTime) {
  1475 + Log.e(TAG, "onDrmSessionAcquired:在获得DRM会话时 ");
  1476 + }
  1477 +
  1478 + @Override
  1479 + public void onDrmKeysLoaded(EventTime eventTime) {
  1480 + Log.e(TAG, "onDrmKeysLoaded: 在已加载的DRM密钥上");
  1481 + }
  1482 +
  1483 + @Override
  1484 + public void onDrmSessionManagerError(EventTime eventTime, Exception error) {
  1485 + Log.e(TAG, "onDrmSessionManagerError: 在DRM会话管理器错误时");
  1486 + }
  1487 +
  1488 + @Override
  1489 + public void onDrmKeysRestored(EventTime eventTime) {
  1490 + Log.e(TAG, "onDrmKeysRestored:" +
  1491 + "在DRM密钥恢复时");
  1492 + }
  1493 +
  1494 + @Override
  1495 + public void onDrmKeysRemoved(EventTime eventTime) {
  1496 + Log.e(TAG, "onDrmKeysRemoved:在已删除的DRM密钥上 ");
  1497 + }
  1498 +
  1499 + @Override
  1500 + public void onDrmSessionReleased(EventTime eventTime) {
  1501 + Log.e(TAG, "onDrmSessionReleased: 会话已释放");
  1502 + }
  1503 +
1411 1504 }
1412 1505 \ No newline at end of file
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/CNLiveVideoView.java
... ... @@ -2,7 +2,9 @@ package com.libs.video.video.exoplayer;
2 2  
3 3 import android.annotation.SuppressLint;
4 4 import android.annotation.TargetApi;
  5 +import android.app.Activity;
5 6 import android.content.Context;
  7 +import android.content.res.Configuration;
6 8 import android.content.res.Resources;
7 9 import android.content.res.TypedArray;
8 10 import android.graphics.Bitmap;
... ... @@ -14,6 +16,7 @@ import android.graphics.drawable.Drawable;
14 16 import android.net.Uri;
15 17 import android.os.Looper;
16 18 import android.util.AttributeSet;
  19 +import android.util.Log;
17 20 import android.view.KeyEvent;
18 21 import android.view.LayoutInflater;
19 22 import android.view.MotionEvent;
... ... @@ -21,8 +24,10 @@ import android.view.SurfaceView;
21 24 import android.view.TextureView;
22 25 import android.view.View;
23 26 import android.view.ViewGroup;
  27 +import android.view.WindowManager;
24 28 import android.widget.FrameLayout;
25 29 import android.widget.ImageView;
  30 +import android.widget.LinearLayout;
26 31 import android.widget.TextView;
27 32  
28 33 import androidx.annotation.ColorInt;
... ... @@ -99,7 +104,7 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
99 104 private static final int SURFACE_TYPE_VIDEO_DECODER_GL_SURFACE_VIEW = 4;
100 105 // LINT.ThenChange(../../../../../../res/values/attrs.xml)
101 106  
102   - private final CNLiveVideoView.ComponentListener componentListener;
  107 + private CNLiveVideoView.ComponentListener componentListener;
103 108 @Nullable
104 109 private final AspectRatioFrameLayout contentFrame;
105 110 @Nullable
... ... @@ -143,18 +148,32 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
143 148 private static final int PICTURE_TYPE_NOT_SET = -1;
144 149 private View controllerPlaceholder;
145 150 private VideoPlayer player;
  151 + private Activity activity;
  152 + private LinearLayout.LayoutParams rootParams;
146 153  
147 154 public CNLiveVideoView(Context context) {
148 155 this(context, /* attrs= */ null);
  156 + componentListener = new CNLiveVideoView.ComponentListener();
  157 + if (context instanceof Activity) {
  158 + this.activity = (Activity) context;
  159 + }
149 160 }
150 161  
151 162 public CNLiveVideoView(Context context, @Nullable AttributeSet attrs) {
152 163 this(context, attrs, /* defStyleAttr= */ 0);
  164 + componentListener = new CNLiveVideoView.ComponentListener();
  165 + if (context instanceof Activity) {
  166 + this.activity = (Activity) context;
  167 + }
153 168 }
154 169  
155 170 @SuppressWarnings({"nullness:argument.type.incompatible", "nullness:method.invocation.invalid"})
156 171 public CNLiveVideoView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
157 172 super(context, attrs, defStyleAttr);
  173 + if (context instanceof Activity) {
  174 + this.activity = (Activity) context;
  175 + }
  176 +
158 177 componentListener = new CNLiveVideoView.ComponentListener();
159 178 //初始化videoplayer
160 179 player = new VideoPlayer(context);
... ... @@ -181,7 +200,7 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
181 200  
182 201 boolean shutterColorSet = false;
183 202 int shutterColor = 0;
184   - int playerLayoutId = R.layout.layout_base_viedo_view;
  203 + int playerLayoutId = R.layout.layout_base_video_view;
185 204 boolean useArtwork = true;
186 205 int defaultArtworkId = 0;
187 206 boolean useController = true;
... ... @@ -303,62 +322,92 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
303 322 } else if (controllerPlaceholder != null) {
304 323 // Propagate attrs as playbackAttrs so that PlayerControlView's custom attributes are
305 324 // transferred, but standard attributes (e.g. background) are not.
306   - if (null == controller) {
307   - this.controller = new CNLiveBaseVideoControlView(context, null, 0, attrs) {
308   - @Override
309   - protected void onViewClick(View view) {
310   -
311   - }
312   -
313   - @Override
314   - protected void initPortraitView(View basePortraitView, ComponentListener onClickListener) {
315   -
316   - }
317   -
318   - };
319   - controller.setId(R.id.cnlive_controller);
320   - controller.setLayoutParams(controllerPlaceholder.getLayoutParams());
321   - ViewGroup parent = ((ViewGroup) controllerPlaceholder.getParent());
322   - int controllerIndex = parent.indexOfChild(controllerPlaceholder);
323   -// parent.removeView(controllerPlaceholder);
324   - parent.addView(controller, controllerIndex);
325   - }
  325 +// if (null == controller) {
  326 +// this.controller = new CNLiveBaseVideoControlView(context, null, 0, attrs) {
  327 +// @Override
  328 +// protected int getPortraitControllViewId() {
  329 +// return -1;
  330 +// }
  331 +//
  332 +// @Override
  333 +// protected void onViewClick(View view) {
  334 +//
  335 +// }
  336 +//
  337 +// @Override
  338 +// protected void initPortraitView(View basePortraitView, ComponentListener onClickListener) {
  339 +//
  340 +// }
  341 +//
  342 +// };
  343 +// controller.setId(R.id.cnlive_controller);
  344 +// controller.setLayoutParams(controllerPlaceholder.getLayoutParams());
  345 +// ViewGroup parent = ((ViewGroup) controllerPlaceholder.getParent());
  346 +// int controllerIndex = parent.indexOfChild(controllerPlaceholder);
  347 +//// parent.removeView(controllerPlaceholder);
  348 +// parent.addView(controller, controllerIndex);
  349 +// }
326 350 } else {
327 351 this.controller = null;
328 352 }
329   - this.controllerShowTimeoutMs = controller != null ? controllerShowTimeoutMs : 0;
  353 +// this.controllerShowTimeoutMs = controller != null ? controllerShowTimeoutMs : 0;
330 354 this.controllerHideOnTouch = controllerHideOnTouch;
331 355 this.controllerAutoShow = controllerAutoShow;
332 356 this.controllerHideDuringAds = controllerHideDuringAds;
333   - this.useController = useController && controller != null;
334   - hideController();
335   - updateContentDescription();
336   - if (controller != null) {
337   - controller.addVisibilityListener(/* listener= */ componentListener);
338   - }
339   - Uri mp4VideoUri = Uri.parse("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8");
340   - player.setDataSource(mp4VideoUri);
341   - player.prepare(true);
342   - setPlayer(player);
  357 +// this.useController = useController && controller != null;
  358 +// hideController();
  359 +// updateContentDescription();
  360 +// if (controller != null) {
  361 +// controller.addVisibilityListener(/* listener= */ componentListener);
  362 +// }
  363 +// Uri mp4VideoUri = Uri.parse("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8");
  364 +// player.setDataSource(mp4VideoUri);
  365 +// player.prepare(true);
  366 +// setPlayer(player);
  367 + //设置初始布局参数
  368 + post(new Runnable() {
  369 + @Override
  370 + public void run() {
  371 + rootParams = (LinearLayout.LayoutParams) getLayoutParams();
  372 + }
  373 + });
  374 +
343 375 }
344 376  
345 377 public void setCustomControllView(CNLiveBaseVideoControlView controllerView) {
346 378 if (null != controllerPlaceholder && null != controllerView) {
347   - controllerView.setPlayer(player);
348   - controller.setId(R.id.cnlive_controller);
349   - controller.setLayoutParams(controllerPlaceholder.getLayoutParams());
350 379 ViewGroup parent = ((ViewGroup) controllerPlaceholder.getParent());
351 380 if (null != parent) {
352   - if (null!=controller){
  381 + if (null != controller) {
353 382 parent.removeView(controller);
354 383 }
355 384 int controllerIndex = parent.indexOfChild(controllerPlaceholder);
356 385 this.controller = controllerView;
  386 + controller.setId(R.id.cnlive_controller);
  387 + controller.setLayoutParams(controllerPlaceholder.getLayoutParams());
357 388 parent.addView(controller, controllerIndex);
358 389 parent.removeView(controllerPlaceholder);
  390 + controllerView.setPlayer(player);
359 391 }
360 392  
361 393 }
  394 + this.controllerShowTimeoutMs = controller != null ? controllerShowTimeoutMs : 0;
  395 + this.useController = useController && controller != null;
  396 + hideController();
  397 + updateContentDescription();
  398 + if (controller != null) {
  399 + controller.addVisibilityListener(/* listener= */ componentListener);
  400 + }
  401 + Uri mp4VideoUri = Uri.parse("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8");
  402 + player.setDataSource(mp4VideoUri);
  403 + player.prepare(false);
  404 + setPlayer(player);
  405 + controllerPlaceholder.setOnClickListener(new OnClickListener() {
  406 + @Override
  407 + public void onClick(View v) {
  408 + Log.e("", "onClick: ");
  409 + }
  410 + });
362 411 }
363 412  
364 413 /**
... ... @@ -465,7 +514,7 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
465 514 newTextComponent.addTextOutput(componentListener);
466 515 }
467 516 player.addListener(componentListener);
468   - maybeShowController(false);
  517 +// maybeShowController(false);
469 518 } else {
470 519 hideController();
471 520 }
... ... @@ -682,16 +731,16 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
682 731 boolean handled = false;
683 732 if (isDpadKey && useController() && !controller.isVisible()) {
684 733 // Handle the key event by showing the controller.
685   - maybeShowController(true);
  734 +// maybeShowController(true);
686 735 handled = true;
687 736 } else if (dispatchMediaKeyEvent(event) || super.dispatchKeyEvent(event)) {
688 737 // The key event was handled as a media key or by the super class. We should also show the
689 738 // controller, or extend its show timeout if already visible.
690   - maybeShowController(true);
  739 +// maybeShowController(true);
691 740 handled = true;
692 741 } else if (isDpadKey && useController()) {
693 742 // The key event wasn't handled, but we should extend the controller's show timeout.
694   - maybeShowController(true);
  743 +// maybeShowController(true);
695 744 }
696 745 return handled;
697 746 }
... ... @@ -831,16 +880,6 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
831 880 }
832 881 }
833 882  
834   - /**
835   - * Sets the {@link PlaybackPreparer}.
836   - *
837   - * @param playbackPreparer The {@link PlaybackPreparer}, or null to remove the current playback
838   - * preparer.
839   - */
840   - public void setPlaybackPreparer(@Nullable PlaybackPreparer playbackPreparer) {
841   - Assertions.checkStateNotNull(controller);
842   - controller.setPlaybackPreparer(playbackPreparer);
843   - }
844 883  
845 884 /**
846 885 * Sets the {@link ControlDispatcher}.
... ... @@ -859,10 +898,10 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
859 898 * @param rewindMs The rewind increment in milliseconds. A non-positive value will cause the
860 899 * rewind button to be disabled.
861 900 */
862   - public void setRewindIncrementMs(int rewindMs) {
863   - Assertions.checkStateNotNull(controller);
864   - controller.setRewindIncrementMs(rewindMs);
865   - }
  901 +// public void setRewindIncrementMs(int rewindMs) {
  902 +// Assertions.checkStateNotNull(controller);
  903 +// controller.setRewindIncrementMs(rewindMs);
  904 +// }
866 905  
867 906 /**
868 907 * Sets the fast forward increment in milliseconds.
... ... @@ -870,40 +909,31 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
870 909 * @param fastForwardMs The fast forward increment in milliseconds. A non-positive value will
871 910 * cause the fast forward button to be disabled.
872 911 */
873   - public void setFastForwardIncrementMs(int fastForwardMs) {
874   - Assertions.checkStateNotNull(controller);
875   - controller.setFastForwardIncrementMs(fastForwardMs);
876   - }
  912 +// public void setFastForwardIncrementMs(int fastForwardMs) {
  913 +// Assertions.checkStateNotNull(controller);
  914 +// controller.setFastForwardIncrementMs(fastForwardMs);
  915 +// }
877 916  
878 917 /**
879 918 * Sets which repeat toggle modes are enabled.
880 919 *
881 920 * @param repeatToggleModes A set of {@link RepeatModeUtil.RepeatToggleModes}.
882 921 */
883   - public void setRepeatToggleModes(@RepeatModeUtil.RepeatToggleModes int repeatToggleModes) {
884   - Assertions.checkStateNotNull(controller);
885   - controller.setRepeatToggleModes(repeatToggleModes);
886   - }
  922 +// public void setRepeatToggleModes(@RepeatModeUtil.RepeatToggleModes int repeatToggleModes) {
  923 +// Assertions.checkStateNotNull(controller);
  924 +// controller.setRepeatToggleModes(repeatToggleModes);
  925 +// }
887 926  
888 927 /**
889 928 * Sets whether the shuffle button is shown.
890 929 *
891 930 * @param showShuffleButton Whether the shuffle button is shown.
892 931 */
893   - public void setShowShuffleButton(boolean showShuffleButton) {
894   - Assertions.checkStateNotNull(controller);
895   - controller.setShowShuffleButton(showShuffleButton);
896   - }
  932 +// public void setShowShuffleButton(boolean showShuffleButton) {
  933 +// Assertions.checkStateNotNull(controller);
  934 +// controller.setShowShuffleButton(showShuffleButton);
  935 +// }
897 936  
898   - /**
899   - * Sets whether the time bar should show all windows, as opposed to just the current one.
900   - *
901   - * @param showMultiWindowTimeBar Whether to show all windows.
902   - */
903   - public void setShowMultiWindowTimeBar(boolean showMultiWindowTimeBar) {
904   - Assertions.checkStateNotNull(controller);
905   - controller.setShowMultiWindowTimeBar(showMultiWindowTimeBar);
906   - }
907 937  
908 938 /**
909 939 * Sets the millisecond positions of extra ad markers relative to the start of the window (or
... ... @@ -1010,7 +1040,7 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
1010 1040 if (!useController() || player == null) {
1011 1041 return false;
1012 1042 }
1013   - maybeShowController(true);
  1043 +// maybeShowController(true);
1014 1044 return true;
1015 1045 }
1016 1046  
... ... @@ -1103,7 +1133,7 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
1103 1133 return false;
1104 1134 }
1105 1135 if (!controller.isVisible()) {
1106   - maybeShowController(true);
  1136 +// maybeShowController(true);
1107 1137 } else if (controllerHideOnTouch) {
1108 1138 controller.hide();
1109 1139 }
... ... @@ -1113,19 +1143,18 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
1113 1143 /**
1114 1144 * Shows the playback controls, but only if forced or shown indefinitely.
1115 1145 */
1116   - private void maybeShowController(boolean isForced) {
1117   - if (isPlayingAd() && controllerHideDuringAds) {
1118   - return;
1119   - }
1120   - if (useController()) {
1121   - boolean wasShowingIndefinitely = controller.isVisible() && controller.getShowTimeoutMs() <= 0;
1122   - boolean shouldShowIndefinitely = shouldShowControllerIndefinitely();
1123   - if (isForced || wasShowingIndefinitely || shouldShowIndefinitely) {
1124   - showController(shouldShowIndefinitely);
1125   - }
1126   - }
1127   - }
1128   -
  1146 +// private void maybeShowController(boolean isForced) {
  1147 +// if (isPlayingAd() && controllerHideDuringAds) {
  1148 +// return;
  1149 +// }
  1150 +// if (useController()) {
  1151 +// boolean wasShowingIndefinitely = controller.isVisible() && controller.getShowTimeoutMs() <= 0;
  1152 +// boolean shouldShowIndefinitely = shouldShowControllerIndefinitely();
  1153 +// if (isForced || wasShowingIndefinitely || shouldShowIndefinitely) {
  1154 +// showController(shouldShowIndefinitely);
  1155 +// }
  1156 +// }
  1157 +// }
1129 1158 private boolean shouldShowControllerIndefinitely() {
1130 1159 if (player == null) {
1131 1160 return true;
... ... @@ -1141,7 +1170,7 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
1141 1170 if (!useController()) {
1142 1171 return;
1143 1172 }
1144   - controller.setShowTimeoutMs(showIndefinitely ? 0 : controllerShowTimeoutMs);
  1173 +// controller.setShowTimeoutMs(showIndefinitely ? 0 : controllerShowTimeoutMs);
1145 1174 controller.show();
1146 1175 }
1147 1176  
... ... @@ -1419,7 +1448,7 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
1419 1448 if (isPlayingAd() && controllerHideDuringAds) {
1420 1449 hideController();
1421 1450 } else {
1422   - maybeShowController(false);
  1451 +// maybeShowController(false);
1423 1452 }
1424 1453 }
1425 1454  
... ... @@ -1467,12 +1496,48 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
1467 1496 *
1468 1497 * @param color
1469 1498 */
1470   - public void setPlayedProgressColor(@ColorInt int color) {
1471   - if (null != controller && controller instanceof CNLiveBaseVideoControlView) {
1472   - CNLiveBaseVideoControlView controlView = controller;
1473   - controller.setPlayedColor(color);
  1499 +// public void setPlayedProgressColor(@ColorInt int color) {
  1500 +// if (null != controller && controller instanceof CNLiveBaseVideoControlView) {
  1501 +// CNLiveBaseVideoControlView controlView = controller;
  1502 +// controller.setPlayedColor(color);
  1503 +// }
  1504 +// }
  1505 + public void onBackPress() {
  1506 + if (null != controller) {
  1507 + controller.onBackPress();
1474 1508 }
1475 1509 }
1476 1510  
  1511 + /**
  1512 + * 横竖屏切换
  1513 + *
  1514 + * @param newConfig
  1515 + */
  1516 + @Override
  1517 + protected void onConfigurationChanged(Configuration newConfig) {
  1518 + super.onConfigurationChanged(newConfig);
  1519 + if (null == newConfig) {
  1520 + return;
  1521 + }
  1522 + //新状态为横屏
  1523 + if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
  1524 + //隐藏状态栏
  1525 + WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
  1526 + lp.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
  1527 + activity.getWindow().setAttributes(lp);
  1528 + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
  1529 + setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
  1530 + } else {
  1531 + //竖屏
  1532 + //显示状态栏
  1533 + WindowManager.LayoutParams attr = activity.getWindow().getAttributes();
  1534 + attr.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN);
  1535 + activity.getWindow().setAttributes(attr);
  1536 + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
  1537 + if (null != rootParams) {
  1538 + setLayoutParams(rootParams);
  1539 + }
  1540 + }
  1541 + }
1477 1542 }
1478 1543  
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/IVideoPlayer.java
... ... @@ -11,6 +11,7 @@ import com.google.android.exoplayer2.PlaybackParameters;
11 11 import com.google.android.exoplayer2.Player;
12 12 import com.google.android.exoplayer2.Renderer;
13 13 import com.google.android.exoplayer2.Timeline;
  14 +import com.google.android.exoplayer2.analytics.AnalyticsListener;
14 15 import com.google.android.exoplayer2.source.MediaSource;
15 16 import com.google.android.exoplayer2.source.TrackGroupArray;
16 17 import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
... ... @@ -47,6 +48,8 @@ public interface IVideoPlayer {
47 48  
48 49 void removeListener(Player.EventListener listener);
49 50  
  51 + void removeAnalyticsListener(AnalyticsListener listener);
  52 +
50 53 @Nullable
51 54 Player.VideoComponent getVideoComponent();
52 55  
... ... @@ -55,24 +58,32 @@ public interface IVideoPlayer {
55 58  
56 59 void addListener(Player.EventListener listener);
57 60  
  61 + void addAnalyticsListener(AnalyticsListener listener);
  62 +
  63 + void addVideoListener(com.google.android.exoplayer2.video.VideoListener listener);
  64 +
58 65 @Player.RepeatMode
59 66 int getRepeatMode();
60 67  
61 68 Timeline getCurrentTimeline();
  69 +
62 70 /**
63 71 * Returns whether the player is currently playing an ad.
64 72 */
65 73 boolean isPlayingAd();
  74 +
66 75 /**
67 76 * Returns whether a previous window exists, which may depend on the current repeat mode and
68 77 * whether shuffle mode is enabled.
69 78 */
70 79 boolean hasPrevious();
  80 +
71 81 /**
72 82 * Returns whether a next window exists, which may depend on the current repeat mode and whether
73 83 * shuffle mode is enabled.
74 84 */
75 85 boolean hasNext();
  86 +
76 87 /**
77 88 * If {@link #isPlayingAd()} returns {@code true}, returns the content position that will be
78 89 * played once all ads in the ad group have finished playing, in milliseconds. If there is no ad
... ... @@ -86,7 +97,9 @@ public interface IVideoPlayer {
86 97 * playing, the returned position is the same as that returned by {@link #getBufferedPosition()}.
87 98 */
88 99 long getContentBufferedPosition();
  100 +
89 101 int getPlaybackState();
  102 +
90 103 /**
91 104 * Returns the currently active playback parameters.
92 105 *
... ... @@ -98,12 +111,14 @@ public interface IVideoPlayer {
98 111 * Returns whether shuffling of windows is enabled.
99 112 */
100 113 boolean getShuffleModeEnabled();
  114 +
101 115 /**
102 116 * Whether playback will proceed when {@link #getPlaybackState()} == {@link #STATE_READY}.
103 117 *
104 118 * @return Whether playback will proceed when ready.
105 119 */
106 120 boolean getPlayWhenReady();
  121 +
107 122 /**
108 123 * Returns whether the current window is seekable, or {@code false} if the {@link Timeline} is
109 124 * empty.
... ... @@ -111,15 +126,21 @@ public interface IVideoPlayer {
111 126 * @see Timeline.Window#isSeekable
112 127 */
113 128 boolean isCurrentWindowSeekable();
  129 +
114 130 int getPreviousWindowIndex();
115   - /** Returns the playback position in the current content window or ad, in milliseconds. */
  131 +
  132 + /**
  133 + * Returns the playback position in the current content window or ad, in milliseconds.
  134 + */
116 135 long getCurrentPosition();
  136 +
117 137 /**
118 138 * Returns the index of the next timeline window to be played, which may depend on the current
119 139 * repeat mode and whether shuffle mode is enabled. Returns {@link C#INDEX_UNSET} if the window
120 140 * currently being played is the last window.
121 141 */
122 142 int getNextWindowIndex();
  143 +
123 144 /**
124 145 * 释放资源
125 146 */
... ... @@ -160,39 +181,44 @@ public interface IVideoPlayer {
160 181 /**
161 182 * Returns the track type that the renderer at a given index handles.
162 183 *
163   - * @see Renderer#getTrackType()
164 184 * @param index The index of the renderer.
165 185 * @return One of the {@code TRACK_TYPE_*} constants defined in {@link C}.
  186 + * @see Renderer#getTrackType()
166 187 */
167 188 int getRendererType(int index);
  189 +
168 190 /**
169 191 * Returns whether the player is playing, i.e. {@link #getContentPosition()} is advancing.
170 192 *
171 193 * <p>If {@code false}, then at least one of the following is true:
172 194 *
173 195 * <ul>
174   - * <li>The {@link #getPlaybackState() playback state} is not {@link #STATE_READY ready}.
175   - * <li>There is no {@link #getPlayWhenReady() intention to play}.
176   - * <li>Playback is {@link #getPlaybackSuppressionReason() suppressed for other reasons}.
  196 + * <li>The {@link #getPlaybackState() playback state} is not {@link #STATE_READY ready}.
  197 + * <li>There is no {@link #getPlayWhenReady() intention to play}.
  198 + * <li>Playback is {@link #getPlaybackSuppressionReason() suppressed for other reasons}.
177 199 * </ul>
178 200 *
179 201 * @return Whether the player is playing.
180 202 */
181 203 boolean isPlaying();
  204 +
182 205 /**
183 206 * Sets the {@link Player.RepeatMode} to be used for playback.
184 207 *
185 208 * @param repeatMode The repeat mode.
186 209 */
187 210 void setRepeatMode(@Player.RepeatMode int repeatMode);
  211 +
188 212 /**
189 213 * Sets whether shuffling of windows is enabled.
190 214 *
191 215 * @param shuffleModeEnabled Whether shuffling is enabled.
192 216 */
193 217 void setShuffleModeEnabled(boolean shuffleModeEnabled);
  218 +
194 219 @Nullable
195 220 ExoPlaybackException getPlaybackError();
  221 +
196 222 interface OnPreparedListener {
197 223 void onPrepared(IVideoPlayer videoPlayer);
198 224 }
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/MyTestControlView.java
... ... @@ -2,14 +2,25 @@ package com.libs.video.video.exoplayer;
2 2  
3 3 import android.content.Context;
4 4 import android.util.AttributeSet;
  5 +import android.util.Log;
5 6 import android.view.View;
  7 +import android.widget.ImageView;
  8 +import android.widget.SeekBar;
  9 +import android.widget.TextView;
6 10  
7 11 import androidx.annotation.Nullable;
  12 +import androidx.appcompat.widget.AppCompatSeekBar;
  13 +import androidx.core.content.ContextCompat;
8 14  
9 15 import com.cnlive.cloud.video.R;
10 16  
11 17 public class MyTestControlView extends CNLiveBaseVideoControlView {
12 18 private View playButton;
  19 + private ImageView ivPortraitPlay;
  20 + private String TAG = getClass().getName();
  21 + private TextView tvCurrentTime;
  22 + private TextView tvAllTime;
  23 + private AppCompatSeekBar seekBar;
13 24  
14 25 public MyTestControlView(Context context) {
15 26 super(context);
... ... @@ -22,25 +33,80 @@ public class MyTestControlView extends CNLiveBaseVideoControlView {
22 33 @Override
23 34 protected void initPortraitView(View basePortraitView, ComponentListener onClickListener) {
24 35 playButton = basePortraitView.findViewById(R.id.btn_start);
  36 + ivPortraitPlay = basePortraitView.findViewById(R.id.iv_play);
  37 + tvCurrentTime = basePortraitView.findViewById(R.id.tv_current_time);
  38 + tvAllTime = basePortraitView.findViewById(R.id.tv_all_time);
  39 + seekBar = basePortraitView.findViewById(R.id.seekBar);
25 40 playButton.setOnClickListener(onClickListener);
  41 + ivPortraitPlay.setOnClickListener(onClickListener);
  42 + seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
  43 + @Override
  44 + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
  45 + Log.e(TAG, "onProgressChanged: " + fromUser);
  46 + if (fromUser) {
  47 + //更新时间
  48 + tvCurrentTime.setText(getFormatDuration(progress));
  49 + //移动画面
  50 + seekToDuration(progress);
  51 + }
  52 + }
  53 +
  54 + @Override
  55 + public void onStartTrackingTouch(SeekBar seekBar) {
  56 +
  57 + }
  58 +
  59 + @Override
  60 + public void onStopTrackingTouch(SeekBar seekBar) {
  61 +
  62 + }
  63 + });
26 64 }
27 65  
28 66  
29 67 @Override
30   - protected int getControllViewId() {
31   - return R.layout.test_view;
  68 + protected int getPortraitControllViewId() {
  69 + return R.layout.layout_protrait_control_view;
  70 + }
  71 +
  72 + @Override
  73 + protected int getLandscapeControllViewId() {
  74 + return R.layout.layout_landscape_control_view;
32 75 }
33 76  
  77 +
34 78 @Override
35 79 protected void onViewClick(View view) {
36   - if (view.getId()==R.id.btn_start){
37   -// if (isPlaying()){
38   -// pauseVideo();
39   -// }else {
40   -// playVideo();
41   -// }
  80 + if (view.getId() == R.id.btn_start) {
  81 + //切换屏幕布局
42 82 switchScreenDirection();
43   -
  83 + } else if (view.getId() == R.id.iv_play) {
  84 + if (isPlaying()) {
  85 + pauseVideo();
  86 + ivPortraitPlay.setBackground(ContextCompat.getDrawable(context, R.drawable.icon_cnvideo_play_pause_icon));
  87 + } else {
  88 + playVideo();
  89 + ivPortraitPlay.setBackground(ContextCompat.getDrawable(context, R.drawable.icon_cnvideo_play_def_icon));
  90 + }
44 91 }
45 92 }
  93 +
  94 +
  95 + @Override
  96 + public void onProgressChange(long position, String durationStr) {
  97 + tvCurrentTime.setText(durationStr);
  98 + seekBar.setProgress((int) position);
  99 + }
  100 +
  101 + @Override
  102 + public void onVideoBufferChange(long buffer) {
  103 + seekBar.incrementSecondaryProgressBy((int) buffer);
  104 + }
  105 +
  106 + @Override
  107 + public void onDurationFinish(long duration, String durationStr) {
  108 + tvAllTime.setText(durationStr);
  109 + seekBar.setMax((int) duration);
  110 + }
  111 +
46 112 }
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/VideoPlayer.java
... ... @@ -13,6 +13,7 @@ import com.google.android.exoplayer2.PlaybackParameters;
13 13 import com.google.android.exoplayer2.Player;
14 14 import com.google.android.exoplayer2.SimpleExoPlayer;
15 15 import com.google.android.exoplayer2.Timeline;
  16 +import com.google.android.exoplayer2.analytics.AnalyticsListener;
16 17 import com.google.android.exoplayer2.ext.rtmp.RtmpDataSourceFactory;
17 18 import com.google.android.exoplayer2.source.MediaSource;
18 19 import com.google.android.exoplayer2.source.ProgressiveMediaSource;
... ... @@ -20,12 +21,18 @@ import com.google.android.exoplayer2.source.TrackGroupArray;
20 21 import com.google.android.exoplayer2.source.dash.DashMediaSource;
21 22 import com.google.android.exoplayer2.source.hls.HlsMediaSource;
22 23 import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
  24 +import com.google.android.exoplayer2.text.Cue;
  25 +import com.google.android.exoplayer2.text.TextOutput;
23 26 import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
24 27 import com.google.android.exoplayer2.ui.PlayerView;
25 28 import com.google.android.exoplayer2.upstream.DataSource;
26 29 import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
27 30 import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
28 31 import com.google.android.exoplayer2.util.Util;
  32 +import com.google.android.exoplayer2.video.VideoDecoderOutputBuffer;
  33 +import com.google.android.exoplayer2.video.VideoDecoderOutputBufferRenderer;
  34 +import com.google.android.exoplayer2.video.VideoListener;
  35 +import com.google.android.exoplayer2.video.spherical.CameraMotionListener;
29 36 import com.libs.video.data.network.Callback;
30 37 import com.libs.video.data.network.DataLoader;
31 38 import com.libs.video.util.AuthUtil;
... ... @@ -38,6 +45,7 @@ import com.umeng.analytics.MobclickAgent;
38 45 import java.security.InvalidKeyException;
39 46 import java.security.spec.InvalidKeySpecException;
40 47 import java.util.HashMap;
  48 +import java.util.List;
41 49 import java.util.Map;
42 50  
43 51 import javax.crypto.BadPaddingException;
... ... @@ -392,6 +400,11 @@ public class VideoPlayer implements IVideoPlayer {
392 400 player.removeListener(listener);
393 401 }
394 402  
  403 + @Override
  404 + public void removeAnalyticsListener(AnalyticsListener listener) {
  405 + player.removeAnalyticsListener(listener);
  406 + }
  407 +
395 408 @Nullable
396 409 @Override
397 410 public Player.VideoComponent getVideoComponent() {
... ... @@ -410,6 +423,16 @@ public class VideoPlayer implements IVideoPlayer {
410 423 }
411 424  
412 425 @Override
  426 + public void addAnalyticsListener(AnalyticsListener listener) {
  427 + player.addAnalyticsListener(listener);
  428 + }
  429 +
  430 + @Override
  431 + public void addVideoListener(VideoListener listener) {
  432 + player.addVideoListener(listener);
  433 + }
  434 +
  435 + @Override
413 436 public int getRepeatMode() {
414 437 return player.getRepeatMode();
415 438 }
... ... @@ -486,6 +509,7 @@ public class VideoPlayer implements IVideoPlayer {
486 509  
487 510 @Override
488 511 public void release() {
  512 +
489 513 //释放资源
490 514 if (null != player) {
491 515 player.release();
... ... @@ -512,18 +536,20 @@ public class VideoPlayer implements IVideoPlayer {
512 536 */
513 537 @Override
514 538 public int getCurrentWindowIndex() {
  539 + int result=0;
515 540 if (null != player) {
516   - player.getCurrentWindowIndex();
  541 + result=player.getCurrentWindowIndex();
517 542 }
518   - return 0;
  543 + return result;
519 544 }
520 545  
521 546 @Override
522 547 public long getDuration() {
  548 + long result=0;
523 549 if (null != player) {
524   - player.getDuration();
  550 + result=player.getDuration();
525 551 }
526   - return 0;
  552 + return result;
527 553 }
528 554  
529 555 @Override
... ...
cloud/video/src/main/res/drawable-hdpi/bg_cnvideo_bottom.png 0 → 100644

331 Bytes

cloud/video/src/main/res/drawable-hdpi/bg_cnvideo_bottom_fullscreen_btn.png 0 → 100644

621 Bytes

cloud/video/src/main/res/drawable-hdpi/icon_cnvideo_play_def_icon.png 0 → 100644

650 Bytes

cloud/video/src/main/res/drawable-hdpi/icon_cnvideo_play_pause_icon.png 0 → 100644

412 Bytes

cloud/video/src/main/res/drawable-hdpi/shadow_bottom.png 0 → 100644

296 Bytes

cloud/video/src/main/res/drawable/video_seekbar_progress.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
  3 +
  4 + <!--背景-->
  5 + <item android:id="@android:id/background">
  6 + <shape>
  7 + <solid android:color="#ededed"/>
  8 + </shape>
  9 + </item>
  10 + <!--缓冲进度-->
  11 + <item android:id="@android:id/secondaryProgress" >
  12 + <clip>
  13 + <shape>
  14 + <solid android:color="#bdbdbd"/>
  15 + </shape>
  16 + </clip>
  17 + </item>
  18 + <!--进度条-->
  19 + <item android:id="@android:id/progress">
  20 + <clip>
  21 + <shape>
  22 + <solid android:color="@color/notificationFinish"/>
  23 + </shape>
  24 + </clip>
  25 + </item>
  26 +
  27 +</layer-list>
0 28 \ No newline at end of file
... ...
cloud/video/src/main/res/layout/layout_base_viedo_view.xml renamed to cloud/video/src/main/res/layout/layout_base_video_view.xml
cloud/video/src/main/res/layout/layout_cnlive_control_view.xml
... ... @@ -14,129 +14,13 @@
14 14 -->
15 15 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
16 16 xmlns:tools="http://schemas.android.com/tools"
  17 + android:id="@+id/fl_root"
17 18 android:layout_width="match_parent"
18 19 android:layout_height="match_parent"
19   - android:orientation="vertical"
20   - tools:targetApi="28">
  20 + android:focusable="false"
  21 + android:clickable="false"
  22 + android:background="@color/transparent"
  23 + android:orientation="vertical">
21 24  
22 25  
23   - <!-- 控制视图-->
24   - <LinearLayout
25   - android:layout_width="match_parent"
26   - android:layout_height="wrap_content"
27   - android:layout_gravity="bottom"
28   - android:background="#80000000"
29   - android:orientation="vertical">
30   - <!-- 进度条-->
31   - <LinearLayout
32   - android:layout_width="match_parent"
33   - android:layout_height="wrap_content"
34   - android:layout_marginTop="4dp"
35   - android:gravity="center_vertical"
36   - android:orientation="horizontal">
37   -
38   - <TextView
39   - android:id="@id/cnlive_position"
40   - android:layout_width="wrap_content"
41   - android:layout_height="wrap_content"
42   - android:includeFontPadding="false"
43   - android:paddingLeft="4dp"
44   - android:paddingRight="4dp"
45   - android:textColor="#FFBEBEBE"
46   - android:textSize="14sp"
47   - android:textStyle="bold" />
48   -
49   - <View
50   - android:id="@id/cnlive_progress_placeholder"
51   - android:layout_width="0dp"
52   - android:layout_height="26dp"
53   - android:layout_weight="1" />
54   -
55   - <TextView
56   - android:id="@id/cnlive_duration"
57   - android:layout_width="wrap_content"
58   - android:layout_height="wrap_content"
59   - android:includeFontPadding="false"
60   - android:paddingLeft="4dp"
61   - android:paddingRight="4dp"
62   - android:textColor="#FFBEBEBE"
63   - android:textSize="14sp"
64   - android:textStyle="bold" />
65   -
66   - </LinearLayout>
67   - <!---->
68   - <LinearLayout
69   - android:layout_width="match_parent"
70   - android:layout_height="wrap_content"
71   - android:layout_gravity="bottom"
72   - android:gravity="center"
73   - android:layoutDirection="ltr"
74   - android:orientation="horizontal"
75   - android:paddingTop="4dp">
76   -
77   - <ImageButton
78   - android:id="@id/cnlive_prev"
79   - style="@style/ExoMediaButton.Previous" />
80   -
81   - <ImageButton
82   - android:id="@id/cnlive_rew"
83   - style="@style/ExoMediaButton.Rewind" />
84   -
85   - <ImageButton
86   - android:id="@id/cnlive_shuffle"
87   - style="@style/ExoMediaButton" />
88   -
89   - <ImageButton
90   - android:id="@id/cnlive_repeat_toggle"
91   - android:layout_width="30dp"
92   - android:layout_height="30dp"
93   - android:src="@drawable/wufalianjie" />
94   -
95   - <ImageButton
96   - android:id="@id/cnlive_play"
97   - style="@style/ExoMediaButton.Play" />
98   -
99   - <ImageButton
100   - android:id="@id/cnlive_pause"
101   - style="@style/ExoMediaButton.Pause" />
102   -
103   - <ImageButton
104   - android:id="@id/cnlive_switch_screen"
105   - style="@style/ExoMediaButton.FastForward" />
106   -
107   - <ImageButton
108   - android:id="@id/cnlive_next"
109   - style="@style/ExoMediaButton.Next" />
110   -
111   - <ImageButton
112   - android:id="@id/cnlive_vr"
113   - style="@style/ExoMediaButton.VR" />
114   -
115   - </LinearLayout>
116   -
117   -
118   - </LinearLayout>
119   - <!--顶部视图-->
120   - <RelativeLayout
121   - android:layout_width="match_parent"
122   - android:layout_height="40dp"
123   - android:background="#80000000">
124   -
125   - <TextView
126   - android:id="@id/cnlive_top_title"
127   - android:layout_width="wrap_content"
128   - android:layout_height="wrap_content"
129   - android:layout_centerVertical="true"
130   - android:layout_marginLeft="10dp"
131   - android:textColor="@color/white"
132   - android:textSize="15sp"
133   - android:textStyle="bold" />
134   -
135   - <ImageButton
136   - android:id="@id/cnlive_play"
137   - style="@style/ExoMediaButton.VR"
138   - android:layout_alignParentRight="true"
139   - android:layout_centerVertical="true" />
140   - </RelativeLayout>
141   -
142 26 </FrameLayout>
... ...
cloud/video/src/main/res/layout/layout_test.xml renamed to cloud/video/src/main/res/layout/layout_landscape_control_view.xml
... ... @@ -4,8 +4,9 @@
4 4 android:layout_height="match_parent"
5 5 android:orientation="vertical">
6 6  
7   - <SurfaceView
8   - android:id="@+id/sv"
  7 + <TextView
9 8 android:layout_width="match_parent"
10   - android:layout_height="match_parent"></SurfaceView>
  9 + android:background="@color/black"
  10 + android:layout_height="wrap_content"
  11 + android:text="你好" />
11 12 </LinearLayout>
12 13 \ No newline at end of file
... ...
cloud/video/src/main/res/layout/layout_protrait_control_view.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:id="@+id/rl_protrait_root"
  4 + android:layout_width="match_parent"
  5 + android:layout_height="match_parent"
  6 + android:orientation="vertical">
  7 +
  8 + <LinearLayout
  9 + android:layout_width="match_parent"
  10 + android:layout_height="wrap_content"
  11 + android:layout_alignParentTop="true"
  12 + android:background="@drawable/shadow_bottom"
  13 + android:gravity="center_vertical"></LinearLayout>
  14 +
  15 + <LinearLayout
  16 + android:layout_width="match_parent"
  17 + android:layout_height="40dp"
  18 + android:layout_alignParentBottom="true"
  19 + android:background="@drawable/bg_cnvideo_bottom"
  20 + android:gravity="center_vertical">
  21 +
  22 + <ImageView
  23 + android:id="@+id/iv_play"
  24 + android:layout_width="20dp"
  25 + android:layout_height="20dp"
  26 + android:layout_marginLeft="10dp"
  27 + android:layout_marginRight="10dp"
  28 + android:background="@drawable/icon_cnvideo_play_pause_icon"
  29 + android:clickable="true" />
  30 +
  31 + <TextView
  32 + android:id="@+id/tv_current_time"
  33 + android:layout_width="wrap_content"
  34 + android:layout_height="wrap_content"
  35 + android:text="00:00"
  36 + android:textColor="@color/white" />
  37 +
  38 + <androidx.appcompat.widget.AppCompatSeekBar
  39 + android:id="@+id/seekBar"
  40 + android:layout_width="0dp"
  41 + android:layout_height="wrap_content"
  42 + android:layout_marginLeft="5dp"
  43 + android:layout_marginRight="5dp"
  44 + android:layout_weight="1"
  45 + android:maxHeight="3dp"
  46 + android:minHeight="3dp"
  47 + android:progressDrawable="@drawable/video_seekbar_progress" />
  48 +
  49 + <TextView
  50 + android:id="@+id/tv_all_time"
  51 + android:layout_width="wrap_content"
  52 + android:layout_height="wrap_content"
  53 + android:text="00:00"
  54 + android:textColor="@color/white" />
  55 +
  56 + <ImageView
  57 + android:id="@+id/btn_start"
  58 + android:layout_width="20dp"
  59 + android:layout_height="20dp"
  60 + android:layout_marginLeft="10dp"
  61 + android:layout_marginRight="10dp"
  62 + android:background="@drawable/bg_cnvideo_bottom_fullscreen_btn" />
  63 +
  64 + </LinearLayout>
  65 +
  66 +</RelativeLayout>
0 67 \ No newline at end of file
... ...
cloud/video/src/main/res/layout/test_view.xml deleted 100644 → 0
1   -<?xml version="1.0" encoding="utf-8"?>
2   -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3   - android:layout_width="match_parent"
4   - android:layout_height="wrap_content"
5   - android:layout_gravity="bottom"
6   - android:background="@color/color_282828"
7   - android:orientation="vertical">
8   -
9   - <Button
10   - android:id="@+id/btn_start"
11   - android:layout_width="50dp"
12   - android:layout_height="50dp" />
13   -</LinearLayout>
14 0 \ No newline at end of file