Commit d6adfcf66da54db5238dfc075bd4d03d2c2e50d8

Authored by 杨帅
1 parent 14ed85cd

1 封装视频库

app/strike/src/main/AndroidManifest.xml
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 9 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
10 10
11 <application 11 <application
12 - android:name="com.cnlive.strike.MyApp" 12 + android:name="com.cnlive.strike.demo.exoplayer.demo.DemoApplication"
13 android:allowBackup="true" 13 android:allowBackup="true"
14 android:icon="@mipmap/ic_launcher" 14 android:icon="@mipmap/ic_launcher"
15 android:label="@string/app_name" 15 android:label="@string/app_name"
cloud/video/src/main/java/com/libs/video/video/exoplayer/CNLiveBaseVideoControlView.java
@@ -9,15 +9,17 @@ import android.content.res.TypedArray; @@ -9,15 +9,17 @@ import android.content.res.TypedArray;
9 import android.os.Looper; 9 import android.os.Looper;
10 import android.util.AttributeSet; 10 import android.util.AttributeSet;
11 import android.util.Log; 11 import android.util.Log;
  12 +import android.view.Gravity;
12 import android.view.KeyEvent; 13 import android.view.KeyEvent;
13 import android.view.LayoutInflater; 14 import android.view.LayoutInflater;
14 import android.view.Surface; 15 import android.view.Surface;
15 import android.view.View; 16 import android.view.View;
16 -import android.view.WindowManager; 17 +import android.view.ViewGroup;
17 import android.widget.FrameLayout; 18 import android.widget.FrameLayout;
18 -import android.widget.TextView; 19 +import android.widget.LinearLayout;
19 20
20 import androidx.annotation.Nullable; 21 import androidx.annotation.Nullable;
  22 +import androidx.core.content.ContextCompat;
21 23
22 import com.cnlive.cloud.video.R; 24 import com.cnlive.cloud.video.R;
23 import com.google.android.exoplayer2.C; 25 import com.google.android.exoplayer2.C;
@@ -25,7 +27,6 @@ import com.google.android.exoplayer2.ExoPlaybackException; @@ -25,7 +27,6 @@ import com.google.android.exoplayer2.ExoPlaybackException;
25 import com.google.android.exoplayer2.ExoPlayerLibraryInfo; 27 import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
26 import com.google.android.exoplayer2.Format; 28 import com.google.android.exoplayer2.Format;
27 import com.google.android.exoplayer2.PlaybackParameters; 29 import com.google.android.exoplayer2.PlaybackParameters;
28 -import com.google.android.exoplayer2.PlaybackPreparer;  
29 import com.google.android.exoplayer2.Player; 30 import com.google.android.exoplayer2.Player;
30 import com.google.android.exoplayer2.Timeline; 31 import com.google.android.exoplayer2.Timeline;
31 import com.google.android.exoplayer2.analytics.AnalyticsListener; 32 import com.google.android.exoplayer2.analytics.AnalyticsListener;
@@ -44,6 +45,9 @@ import java.util.Formatter; @@ -44,6 +45,9 @@ import java.util.Formatter;
44 import java.util.Locale; 45 import java.util.Locale;
45 import java.util.concurrent.CopyOnWriteArrayList; 46 import java.util.concurrent.CopyOnWriteArrayList;
46 47
  48 +/**
  49 + * 视频控制视图基类
  50 + */
47 public abstract class CNLiveBaseVideoControlView extends FrameLayout implements AnalyticsListener { 51 public abstract class CNLiveBaseVideoControlView extends FrameLayout implements AnalyticsListener {
48 52
49 static { 53 static {
@@ -135,7 +139,10 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -135,7 +139,10 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
135 private FrameLayout fl_root;//根布局 139 private FrameLayout fl_root;//根布局
136 @Nullable 140 @Nullable
137 public Context context; 141 public Context context;
  142 + //用于获取当前屏幕朝向
138 private Configuration newConfig; 143 private Configuration newConfig;
  144 + //延时隐藏当前播放视图
  145 + private Runnable delayHideViewAction;
139 146
140 public CNLiveBaseVideoControlView(Context context) { 147 public CNLiveBaseVideoControlView(Context context) {
141 this(context, /* attrs= */ null, 0, null); 148 this(context, /* attrs= */ null, 0, null);
@@ -143,14 +150,29 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -143,14 +150,29 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
143 visibilityListeners = new CopyOnWriteArrayList<>(); 150 visibilityListeners = new CopyOnWriteArrayList<>();
144 } 151 }
145 152
  153 + /**
  154 + * 获取竖屏ui
  155 + *
  156 + * @return
  157 + */
146 protected int getPortraitControllViewId() { 158 protected int getPortraitControllViewId() {
147 return -1; 159 return -1;
148 } 160 }
149 161
  162 + /**
  163 + * 获取横屏UI
  164 + *
  165 + * @return
  166 + */
150 protected int getLandscapeControllViewId() { 167 protected int getLandscapeControllViewId() {
151 return -1; 168 return -1;
152 } 169 }
153 170
  171 + /**
  172 + * 按鈕点击事件
  173 + *
  174 + * @param view
  175 + */
154 protected abstract void onViewClick(View view); 176 protected abstract void onViewClick(View view);
155 177
156 @SuppressWarnings({ 178 @SuppressWarnings({
@@ -168,6 +190,7 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -168,6 +190,7 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
168 if (context instanceof Activity) { 190 if (context instanceof Activity) {
169 this.activity = (Activity) context; 191 this.activity = (Activity) context;
170 } 192 }
  193 +
171 formatBuilder = new StringBuilder(); 194 formatBuilder = new StringBuilder();
172 formatter = new Formatter(formatBuilder, Locale.getDefault()); 195 formatter = new Formatter(formatBuilder, Locale.getDefault());
173 period = new Timeline.Period(); 196 period = new Timeline.Period();
@@ -177,147 +200,9 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -177,147 +200,9 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
177 componentListener = new CNLiveBaseVideoControlView.ComponentListener(); 200 componentListener = new CNLiveBaseVideoControlView.ComponentListener();
178 // controlDispatcher = new CNLiveDefaultControlDispatcher(); 201 // controlDispatcher = new CNLiveDefaultControlDispatcher();
179 controllerLayoutId = R.layout.layout_cnlive_control_view; 202 controllerLayoutId = R.layout.layout_cnlive_control_view;
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 203
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; 204 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 // 205 //
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 //设置底层视图 206 //设置底层视图
322 baseRootView = LayoutInflater.from(context).inflate(R.layout.layout_cnlive_control_view, /* root= */ this); 207 baseRootView = LayoutInflater.from(context).inflate(R.layout.layout_cnlive_control_view, /* root= */ this);
323 if (null != baseRootView) { 208 if (null != baseRootView) {
@@ -326,21 +211,8 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -326,21 +211,8 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
326 baseRootView.post(new Runnable() { 211 baseRootView.post(new Runnable() {
327 @Override 212 @Override
328 public void run() { 213 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 - }  
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 - 214 + //初始化视图UI
  215 + initView();
344 if (null != componentListener && null != basePortraitView) { 216 if (null != componentListener && null != basePortraitView) {
345 initPortraitView(basePortraitView, componentListener); 217 initPortraitView(basePortraitView, componentListener);
346 } 218 }
@@ -348,27 +220,98 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -348,27 +220,98 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
348 baseRootView.setOnClickListener(new OnClickListener() { 220 baseRootView.setOnClickListener(new OnClickListener() {
349 @Override 221 @Override
350 public void onClick(View v) { 222 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 - } 223 + showControlView();
366 } 224 }
367 }); 225 });
368 } 226 }
369 227
370 }); 228 });
  229 +// post(new Runnable() {
  230 +// @Override
  231 +// public void run() {
  232 +// initView();
  233 +// if (null != componentListener && null != basePortraitView) {
  234 +// initPortraitView(basePortraitView, componentListener);
  235 +// }
  236 +// LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
  237 +// LinearLayout lineLayout = new LinearLayout(context);
  238 +// lineLayout.setOrientation(LinearLayout.VERTICAL);
  239 +// lineLayout.setLayoutParams(params);
  240 +// lineLayout.setGravity(Gravity.CENTER );
  241 +// lineLayout.setClickable(true);
  242 +// lineLayout.setBackgroundColor(ContextCompat.getColor(context,R.color.black));
  243 +//
  244 +// addView(lineLayout);
  245 +// }
  246 +// });
  247 + }
  248 +
  249 + /**
  250 + * 显示控制UI
  251 + */
  252 + private void showControlView() {
  253 + //获取当前屏幕朝向
  254 + if (null == newConfig) {
  255 + showPortraitView();
  256 + } else {
  257 + if (null != basePortraitView && null != baseLandscapeView) {
  258 + //当前是竖屏
  259 + if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
  260 + showPortraitView();
  261 + } else {
  262 + showLandscapeView();
  263 + }
  264 + } else {
  265 + showPortraitView();
  266 + }
  267 + }
  268 + if (null != delayHideViewAction) {
  269 + removeCallbacks(delayHideViewAction);
  270 + postDelayed(delayHideViewAction, 10 * 1000);
  271 + }
  272 +
  273 + }
  274 +
  275 + /**
  276 + * 初始化视图
  277 + */
  278 + private void initView() {
  279 + //隐藏视图
  280 + delayHideViewAction = new Runnable() {
  281 + @Override
  282 + public void run() {
  283 + if (null != basePortraitView) {
  284 + basePortraitView.setVisibility(GONE);
  285 + }
  286 + if (null != baseLandscapeView) {
  287 + baseLandscapeView.setVisibility(GONE);
  288 + }
  289 + }
  290 + };
  291 +
  292 + if (-1 != getPortraitControllViewId()) {
  293 + basePortraitView = LayoutInflater.from(context).inflate(getPortraitControllViewId(), /* root= */ null);
  294 +// if (null != fl_root && null != basePortraitView) {
  295 +// fl_root.addView(basePortraitView);
  296 +// }
  297 + addView(basePortraitView);
  298 + }
  299 + if (-1 != getLandscapeControllViewId()) {
  300 + baseLandscapeView = LayoutInflater.from(context).inflate(getLandscapeControllViewId(), /* root= */ null);
  301 +// if (null != fl_root && null != baseLandscapeView) {
  302 +// fl_root.addView(baseLandscapeView);
  303 +// }
  304 + addView(baseLandscapeView);
  305 + }
371 306
  307 + basePortraitView.setVisibility(VISIBLE);
  308 + if (null != baseLandscapeView) {
  309 + baseLandscapeView.setVisibility(GONE);
  310 + }
  311 + if (null != delayHideViewAction) {
  312 + removeCallbacks(delayHideViewAction);
  313 + postDelayed(delayHideViewAction, 10 * 1000);
  314 + }
372 } 315 }
373 316
374 /** 317 /**
@@ -385,19 +328,20 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -385,19 +328,20 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
385 * 显示横屏 328 * 显示横屏
386 */ 329 */
387 private void showLandscapeView() { 330 private void showLandscapeView() {
388 - if (null == baseLandscapeView) {  
389 - return;  
390 - }  
391 - if (baseLandscapeView.getVisibility() == View.VISIBLE) {  
392 - baseLandscapeView.setVisibility(View.GONE);  
393 - } else {  
394 - baseLandscapeView.setVisibility(View.VISIBLE);  
395 - } 331 + //当前有横屏UI
  332 + if (null != baseLandscapeView) {
  333 + if (baseLandscapeView.getVisibility() == View.VISIBLE) {
  334 + baseLandscapeView.setVisibility(View.GONE);
  335 + } else {
  336 + baseLandscapeView.setVisibility(View.VISIBLE);
  337 + }
396 338
397 - if (null != basePortraitView) {  
398 - basePortraitView.setVisibility(View.GONE); 339 + if (null != basePortraitView) {
  340 + basePortraitView.setVisibility(View.GONE);
  341 + }
  342 + } else {
  343 + basePortraitView.setVisibility(View.VISIBLE);
399 } 344 }
400 -  
401 } 345 }
402 346
403 /** 347 /**
@@ -407,11 +351,7 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -407,11 +351,7 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
407 if (null == basePortraitView) { 351 if (null == basePortraitView) {
408 return; 352 return;
409 } 353 }
410 - if (basePortraitView.getVisibility() == View.VISIBLE) {  
411 - basePortraitView.setVisibility(View.GONE);  
412 - } else {  
413 - basePortraitView.setVisibility(View.VISIBLE);  
414 - } 354 + basePortraitView.setVisibility(View.VISIBLE);
415 if (null != baseLandscapeView) { 355 if (null != baseLandscapeView) {
416 baseLandscapeView.setVisibility(GONE); 356 baseLandscapeView.setVisibility(GONE);
417 } 357 }
@@ -554,35 +494,6 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -554,35 +494,6 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
554 // updateShuffleButton(); 494 // updateShuffleButton();
555 // } 495 // }
556 496
557 - /**  
558 - * Returns whether the VR button is shown.  
559 - */  
560 -// public boolean getShowVrButton() {  
561 -// return vrButton != null && vrButton.getVisibility() == VISIBLE;  
562 -// }  
563 -  
564 - /**  
565 - * Sets whether the VR button is shown.  
566 - *  
567 - * @param showVrButton Whether the VR button is shown.  
568 - */  
569 -// public void setShowVrButton(boolean showVrButton) {  
570 -// if (vrButton != null) {  
571 -// vrButton.setVisibility(showVrButton ? VISIBLE : GONE);  
572 -// }  
573 -// }  
574 -  
575 - /**  
576 - * Sets listener for the VR button.  
577 - *  
578 - * @param onClickListener Listener for the VR button, or null to clear the listener.  
579 - */  
580 -// public void setVrButtonListener(@Nullable OnClickListener onClickListener) {  
581 -// if (vrButton != null) {  
582 -// vrButton.setOnClickListener(onClickListener);  
583 -// }  
584 -// }  
585 -  
586 497
587 /** 498 /**
588 * Shows the playback controls. If {@link #getShowTimeoutMs()} is positive then the controls will 499 * Shows the playback controls. If {@link #getShowTimeoutMs()} is positive then the controls will
@@ -775,7 +686,7 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -775,7 +686,7 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
775 * 更新进度条 686 * 更新进度条
776 */ 687 */
777 private void updateProgress() { 688 private void updateProgress() {
778 - if (!isVisible() || !isAttachedToWindow) { 689 + if (!isVisible() || !isAttachedToWindow || null == basePortraitView) {
779 return; 690 return;
780 } 691 }
781 long position = 0; 692 long position = 0;
@@ -783,23 +694,18 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -783,23 +694,18 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
783 position = player.getContentPosition(); 694 position = player.getContentPosition();
784 } 695 }
785 Log.e(TAG, "updateProgress: " + position); 696 Log.e(TAG, "updateProgress: " + position);
786 -// if (positionView != null && !scrubbing) {  
787 -// positionView.setText(Util.getStringForTime(formatBuilder, formatter, position));  
788 -// }  
789 -// if (progressUpdateListener != null) {  
790 -// progressUpdateListener.onProgressUpdate(position, bufferedPosition);  
791 -// }  
792 //先移除之前的动作 697 //先移除之前的动作
793 removeCallbacks(updateProgressAction); 698 removeCallbacks(updateProgressAction);
794 int playbackState = player == null ? Player.STATE_IDLE : player.getPlaybackState(); 699 int playbackState = player == null ? Player.STATE_IDLE : player.getPlaybackState();
795 - onProgressChange(position, Util.getStringForTime(formatBuilder, formatter, position));  
796 if (player != null && player.isPlaying()) { 700 if (player != null && player.isPlaying()) {
797 postDelayed(updateProgressAction, MAX_UPDATE_INTERVAL_MS); 701 postDelayed(updateProgressAction, MAX_UPDATE_INTERVAL_MS);
  702 + onProgressChange(position, Util.getStringForTime(formatBuilder, formatter, position));
798 } else if (playbackState != Player.STATE_ENDED && playbackState != Player.STATE_IDLE) { 703 } else if (playbackState != Player.STATE_ENDED && playbackState != Player.STATE_IDLE) {
799 postDelayed(updateProgressAction, MAX_UPDATE_INTERVAL_MS); 704 postDelayed(updateProgressAction, MAX_UPDATE_INTERVAL_MS);
800 } 705 }
801 } 706 }
802 707
  708 +
803 // private void requestPlayPauseFocus() { 709 // private void requestPlayPauseFocus() {
804 // boolean shouldShowPauseButton = shouldShowPauseButton(); 710 // boolean shouldShowPauseButton = shouldShowPauseButton();
805 // if (!shouldShowPauseButton && playButton != null) { 711 // if (!shouldShowPauseButton && playButton != null) {
@@ -818,7 +724,7 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -818,7 +724,7 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
818 // view.setVisibility(VISIBLE); 724 // view.setVisibility(VISIBLE);
819 // } 725 // }
820 726
821 - private void previous(VideoPlayer player) { 727 + private void previous() {
822 Timeline timeline = player.getCurrentTimeline(); 728 Timeline timeline = player.getCurrentTimeline();
823 if (timeline.isEmpty() || player.isPlayingAd()) { 729 if (timeline.isEmpty() || player.isPlayingAd()) {
824 return; 730 return;
@@ -837,10 +743,8 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -837,10 +743,8 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
837 743
838 /** 744 /**
839 * 播放下一个视频 745 * 播放下一个视频
840 - *  
841 - * @param player  
842 */ 746 */
843 - public void next(VideoPlayer player) { 747 + public void next() {
844 Timeline timeline = player.getCurrentTimeline(); 748 Timeline timeline = player.getCurrentTimeline();
845 if (timeline.isEmpty() || player.isPlayingAd()) { 749 if (timeline.isEmpty() || player.isPlayingAd()) {
846 return; 750 return;
@@ -942,7 +846,12 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -942,7 +846,12 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
942 public void onDetachedFromWindow() { 846 public void onDetachedFromWindow() {
943 super.onDetachedFromWindow(); 847 super.onDetachedFromWindow();
944 isAttachedToWindow = false; 848 isAttachedToWindow = false;
945 - removeCallbacks(updateProgressAction); 849 + if (null != delayHideViewAction) {
  850 + removeCallbacks(delayHideViewAction);
  851 + }
  852 + if (null != updateProgressAction) {
  853 + removeCallbacks(updateProgressAction);
  854 + }
946 // removeCallbacks(hideAction); 855 // removeCallbacks(hideAction);
947 } 856 }
948 857
@@ -994,10 +903,10 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -994,10 +903,10 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
994 pauseVideo(); 903 pauseVideo();
995 break; 904 break;
996 case KeyEvent.KEYCODE_MEDIA_NEXT: 905 case KeyEvent.KEYCODE_MEDIA_NEXT:
997 - next(player); 906 +// next(player);
998 break; 907 break;
999 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 908 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
1000 - previous(player); 909 +// previous(player);
1001 break; 910 break;
1002 default: 911 default:
1003 break; 912 break;
@@ -1087,13 +996,6 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -1087,13 +996,6 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
1087 } 996 }
1088 } 997 }
1089 998
1090 - public void setShuffleModeEnabled(boolean isShuffleModeEnabled) {  
1091 - if (null == player) {  
1092 - return;  
1093 - }  
1094 - player.setShuffleModeEnabled(isShuffleModeEnabled);  
1095 -// controlDispatcher.dispatchSetShuffleModeEnabled(player, !player.getShuffleModeEnabled());  
1096 - }  
1097 999
1098 /** 1000 /**
1099 * 设置播放模式 1001 * 设置播放模式
@@ -1117,12 +1019,19 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -1117,12 +1019,19 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
1117 //获取当前屏幕朝向 1019 //获取当前屏幕朝向
1118 Configuration mConfiguration = activity.getResources().getConfiguration(); //获取设置的配置信息 1020 Configuration mConfiguration = activity.getResources().getConfiguration(); //获取设置的配置信息
1119 int ori = mConfiguration.orientation; //获取屏幕方向 1021 int ori = mConfiguration.orientation; //获取屏幕方向
1120 - if (ori == mConfiguration.ORIENTATION_LANDSCAPE) { 1022 + if (ori == Configuration.ORIENTATION_LANDSCAPE) {
1121 //强制为竖屏 1023 //强制为竖屏
1122 activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 1024 activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
1123 - } else if (ori == mConfiguration.ORIENTATION_PORTRAIT) { 1025 + } else if (ori == Configuration.ORIENTATION_PORTRAIT) {
1124 //强制为横屏 1026 //强制为横屏
1125 activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 1027 activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
  1028 + //修改当前UI宽高
  1029 + LayoutParams lp = (LayoutParams) getLayoutParams();
  1030 + lp.setMargins(0, 0, 0, 0);
  1031 + lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
  1032 + lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
  1033 + lp.gravity = Gravity.CENTER;
  1034 + setLayoutParams(lp);
1126 } 1035 }
1127 } 1036 }
1128 } 1037 }
@@ -1131,21 +1040,7 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -1131,21 +1040,7 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
1131 protected void onConfigurationChanged(Configuration newConfig) { 1040 protected void onConfigurationChanged(Configuration newConfig) {
1132 super.onConfigurationChanged(newConfig); 1041 super.onConfigurationChanged(newConfig);
1133 this.newConfig = newConfig; 1042 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 - } 1043 + showControlView();
1149 } 1044 }
1150 1045
1151 /** 1046 /**
@@ -1243,7 +1138,9 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements @@ -1243,7 +1138,9 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
1243 } 1138 }
1244 } 1139 }
1245 1140
1246 - /**获取格式化后的时间 1141 + /**
  1142 + * 获取格式化后的时间
  1143 + *
1247 * @param duration 1144 * @param duration
1248 * @return 1145 * @return
1249 */ 1146 */
cloud/video/src/main/java/com/libs/video/video/exoplayer/CNLiveVideoView.java
@@ -29,6 +29,7 @@ import android.widget.FrameLayout; @@ -29,6 +29,7 @@ import android.widget.FrameLayout;
29 import android.widget.ImageView; 29 import android.widget.ImageView;
30 import android.widget.LinearLayout; 30 import android.widget.LinearLayout;
31 import android.widget.TextView; 31 import android.widget.TextView;
  32 +import android.widget.Toast;
32 33
33 import androidx.annotation.ColorInt; 34 import androidx.annotation.ColorInt;
34 import androidx.annotation.IntDef; 35 import androidx.annotation.IntDef;
@@ -42,9 +43,11 @@ import com.google.android.exoplayer2.DefaultControlDispatcher; @@ -42,9 +43,11 @@ import com.google.android.exoplayer2.DefaultControlDispatcher;
42 import com.google.android.exoplayer2.ExoPlaybackException; 43 import com.google.android.exoplayer2.ExoPlaybackException;
43 import com.google.android.exoplayer2.PlaybackPreparer; 44 import com.google.android.exoplayer2.PlaybackPreparer;
44 import com.google.android.exoplayer2.Player; 45 import com.google.android.exoplayer2.Player;
  46 +import com.google.android.exoplayer2.analytics.AnalyticsListener;
45 import com.google.android.exoplayer2.metadata.Metadata; 47 import com.google.android.exoplayer2.metadata.Metadata;
46 import com.google.android.exoplayer2.metadata.flac.PictureFrame; 48 import com.google.android.exoplayer2.metadata.flac.PictureFrame;
47 import com.google.android.exoplayer2.metadata.id3.ApicFrame; 49 import com.google.android.exoplayer2.metadata.id3.ApicFrame;
  50 +import com.google.android.exoplayer2.source.MediaSourceEventListener;
48 import com.google.android.exoplayer2.source.TrackGroupArray; 51 import com.google.android.exoplayer2.source.TrackGroupArray;
49 import com.google.android.exoplayer2.source.ads.AdsLoader; 52 import com.google.android.exoplayer2.source.ads.AdsLoader;
50 import com.google.android.exoplayer2.text.Cue; 53 import com.google.android.exoplayer2.text.Cue;
@@ -63,13 +66,18 @@ import com.google.android.exoplayer2.util.Util; @@ -63,13 +66,18 @@ import com.google.android.exoplayer2.util.Util;
63 import com.google.android.exoplayer2.video.VideoDecoderGLSurfaceView; 66 import com.google.android.exoplayer2.video.VideoDecoderGLSurfaceView;
64 import com.google.android.exoplayer2.video.VideoListener; 67 import com.google.android.exoplayer2.video.VideoListener;
65 68
  69 +import java.io.IOException;
66 import java.lang.annotation.Documented; 70 import java.lang.annotation.Documented;
67 import java.lang.annotation.Retention; 71 import java.lang.annotation.Retention;
68 import java.lang.annotation.RetentionPolicy; 72 import java.lang.annotation.RetentionPolicy;
69 import java.util.ArrayList; 73 import java.util.ArrayList;
70 import java.util.List; 74 import java.util.List;
71 75
72 -public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProvider { 76 +public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProvider, AnalyticsListener {
  77 +
  78 +
  79 + private String TAG = this.getClass().getName();
  80 +
73 /** 81 /**
74 * Determines when the buffering view is shown. One of {@link #SHOW_BUFFERING_NEVER}, {@link 82 * Determines when the buffering view is shown. One of {@link #SHOW_BUFFERING_NEVER}, {@link
75 * #SHOW_BUFFERING_WHEN_PLAYING} or {@link #SHOW_BUFFERING_ALWAYS}. 83 * #SHOW_BUFFERING_WHEN_PLAYING} or {@link #SHOW_BUFFERING_ALWAYS}.
@@ -118,7 +126,7 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv @@ -118,7 +126,7 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
118 @Nullable 126 @Nullable
119 private final View bufferingView; 127 private final View bufferingView;
120 @Nullable 128 @Nullable
121 - private final TextView errorMessageView; 129 + private final LinearLayout errorMessageView;
122 @Nullable 130 @Nullable
123 private CNLiveBaseVideoControlView controller; 131 private CNLiveBaseVideoControlView controller;
124 @Nullable 132 @Nullable
@@ -177,6 +185,8 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv @@ -177,6 +185,8 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
177 componentListener = new CNLiveVideoView.ComponentListener(); 185 componentListener = new CNLiveVideoView.ComponentListener();
178 //初始化videoplayer 186 //初始化videoplayer
179 player = new VideoPlayer(context); 187 player = new VideoPlayer(context);
  188 + //添加事件监听
  189 + player.addAnalyticsListener(this);
180 if (isInEditMode()) { 190 if (isInEditMode()) {
181 contentFrame = null; 191 contentFrame = null;
182 shutterView = null; 192 shutterView = null;
@@ -313,7 +323,13 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv @@ -313,7 +323,13 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
313 if (errorMessageView != null) { 323 if (errorMessageView != null) {
314 errorMessageView.setVisibility(View.GONE); 324 errorMessageView.setVisibility(View.GONE);
315 } 325 }
316 - 326 + errorMessageView.setOnClickListener(new OnClickListener() {
  327 + @Override
  328 + public void onClick(View view) {
  329 + errorMessageView.setVisibility(GONE);
  330 + player.retry();
  331 + }
  332 + });
317 // Playback control view. 333 // Playback control view.
318 CNLiveBaseVideoControlView customController = findViewById(R.id.cnlive_controller); 334 CNLiveBaseVideoControlView customController = findViewById(R.id.cnlive_controller);
319 controllerPlaceholder = findViewById(R.id.cnlive_controller_placeholder); 335 controllerPlaceholder = findViewById(R.id.cnlive_controller_placeholder);
@@ -399,8 +415,14 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv @@ -399,8 +415,14 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
399 controller.addVisibilityListener(/* listener= */ componentListener); 415 controller.addVisibilityListener(/* listener= */ componentListener);
400 } 416 }
401 Uri mp4VideoUri = Uri.parse("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8"); 417 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); 418 + List<String> list = new ArrayList<>();
  419 + list.add("https://qq.com-ok-qq.com/20191005/24249_f5e36323/index.m3u8");
  420 + list.add("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8");
  421 + list.add("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8");
  422 +
  423 +
  424 + player.setDataSource(list);
  425 + player.prepare();
404 setPlayer(player); 426 setPlayer(player);
405 controllerPlaceholder.setOnClickListener(new OnClickListener() { 427 controllerPlaceholder.setOnClickListener(new OnClickListener() {
406 @Override 428 @Override
@@ -763,16 +785,6 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv @@ -763,16 +785,6 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
763 return controller != null && controller.isVisible(); 785 return controller != null && controller.isVisible();
764 } 786 }
765 787
766 - /**  
767 - * Shows the playback controls. Does nothing if playback controls are disabled.  
768 - *  
769 - * <p>The playback controls are automatically hidden during playback after {{@link  
770 - * #getControllerShowTimeoutMs()}}. They are shown indefinitely when playback has not started yet,  
771 - * is paused, has ended or failed.  
772 - */  
773 - public void showController() {  
774 - showController(shouldShowControllerIndefinitely());  
775 - }  
776 788
777 /** 789 /**
778 * Hides the playback controls. Does nothing if playback controls are disabled. 790 * Hides the playback controls. Does nothing if playback controls are disabled.
@@ -807,7 +819,7 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv @@ -807,7 +819,7 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
807 this.controllerShowTimeoutMs = controllerShowTimeoutMs; 819 this.controllerShowTimeoutMs = controllerShowTimeoutMs;
808 if (controller.isVisible()) { 820 if (controller.isVisible()) {
809 // Update the controller's timeout if necessary. 821 // Update the controller's timeout if necessary.
810 - showController(); 822 +// showController();
811 } 823 }
812 } 824 }
813 825
@@ -838,16 +850,6 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv @@ -838,16 +850,6 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
838 return controllerAutoShow; 850 return controllerAutoShow;
839 } 851 }
840 852
841 - /**  
842 - * Sets whether the playback controls are automatically shown when playback starts, pauses, ends,  
843 - * or fails. If set to false, the playback controls can be manually operated with {@link  
844 - * #showController()} and {@link #hideController()}.  
845 - *  
846 - * @param controllerAutoShow Whether the playback controls are allowed to show automatically.  
847 - */  
848 - public void setControllerAutoShow(boolean controllerAutoShow) {  
849 - this.controllerAutoShow = controllerAutoShow;  
850 - }  
851 853
852 /** 854 /**
853 * Sets whether the playback controls are hidden when ads are playing. Controls are always shown 855 * Sets whether the playback controls are hidden when ads are playing. Controls are always shown
@@ -1166,13 +1168,6 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv @@ -1166,13 +1168,6 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
1166 || !player.getPlayWhenReady()); 1168 || !player.getPlayWhenReady());
1167 } 1169 }
1168 1170
1169 - private void showController(boolean showIndefinitely) {  
1170 - if (!useController()) {  
1171 - return;  
1172 - }  
1173 -// controller.setShowTimeoutMs(showIndefinitely ? 0 : controllerShowTimeoutMs);  
1174 - controller.show();  
1175 - }  
1176 1171
1177 private boolean isPlayingAd() { 1172 private boolean isPlayingAd() {
1178 return player != null && player.isPlayingAd() && player.getPlayWhenReady(); 1173 return player != null && player.isPlayingAd() && player.getPlayWhenReady();
@@ -1295,21 +1290,21 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv @@ -1295,21 +1290,21 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
1295 } 1290 }
1296 1291
1297 private void updateErrorMessage() { 1292 private void updateErrorMessage() {
1298 - if (errorMessageView != null) {  
1299 - if (customErrorMessage != null) {  
1300 - errorMessageView.setText(customErrorMessage);  
1301 - errorMessageView.setVisibility(View.VISIBLE);  
1302 - return;  
1303 - }  
1304 - @Nullable ExoPlaybackException error = player != null ? player.getPlaybackError() : null;  
1305 - if (error != null && errorMessageProvider != null) {  
1306 - CharSequence errorMessage = errorMessageProvider.getErrorMessage(error).second;  
1307 - errorMessageView.setText(errorMessage);  
1308 - errorMessageView.setVisibility(View.VISIBLE);  
1309 - } else {  
1310 - errorMessageView.setVisibility(View.GONE);  
1311 - }  
1312 - } 1293 +// if (errorMessageView != null) {
  1294 +// if (customErrorMessage != null) {
  1295 +// errorMessageView.setText(customErrorMessage);
  1296 +// errorMessageView.setVisibility(View.VISIBLE);
  1297 +// return;
  1298 +// }
  1299 +// @Nullable ExoPlaybackException error = player != null ? player.getPlaybackError() : null;
  1300 +// if (error != null && errorMessageProvider != null) {
  1301 +// CharSequence errorMessage = errorMessageProvider.getErrorMessage(error).second;
  1302 +// errorMessageView.setText(errorMessage);
  1303 +// errorMessageView.setVisibility(View.VISIBLE);
  1304 +// } else {
  1305 +// errorMessageView.setVisibility(View.GONE);
  1306 +// }
  1307 +// }
1313 } 1308 }
1314 1309
1315 private void updateContentDescription() { 1310 private void updateContentDescription() {
@@ -1491,17 +1486,6 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv @@ -1491,17 +1486,6 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
1491 } 1486 }
1492 1487
1493 1488
1494 - /**  
1495 - * 设置播放进度条的颜色  
1496 - *  
1497 - * @param color  
1498 - */  
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() { 1489 public void onBackPress() {
1506 if (null != controller) { 1490 if (null != controller) {
1507 controller.onBackPress(); 1491 controller.onBackPress();
@@ -1539,5 +1523,86 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv @@ -1539,5 +1523,86 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
1539 } 1523 }
1540 } 1524 }
1541 } 1525 }
  1526 +
  1527 + @Override
  1528 + public void onLoadingChanged(EventTime eventTime, boolean isLoading) {
  1529 + if (null == bufferingView) {
  1530 + return;
  1531 + }
  1532 +// if (isLoading) {
  1533 +// bufferingView.setVisibility(VISIBLE);
  1534 +// } else {
  1535 +// bufferingView.setVisibility(GONE);
  1536 +// }
  1537 + Log.e(TAG, "onLoadingChanged: ");
  1538 + }
  1539 +
  1540 + @Override
  1541 + public void onLoadCanceled(EventTime eventTime, MediaSourceEventListener.LoadEventInfo loadEventInfo, MediaSourceEventListener.MediaLoadData mediaLoadData) {
  1542 + if (null == bufferingView) {
  1543 + return;
  1544 + }
  1545 + bufferingView.setVisibility(GONE);
  1546 + Log.e(TAG, "onLoadCanceled: ");
  1547 + }
  1548 +
  1549 + @Override
  1550 + public void onLoadStarted(EventTime eventTime, MediaSourceEventListener.LoadEventInfo loadEventInfo, MediaSourceEventListener.MediaLoadData mediaLoadData) {
  1551 + Log.e(TAG, "onLoadStarted: ");
  1552 + bufferingView.setVisibility(VISIBLE);
  1553 + }
  1554 +
  1555 + @Override
  1556 + public void onPlayerError(EventTime eventTime, ExoPlaybackException error) {
  1557 + if (null != errorMessageView) {
  1558 + errorMessageView.setVisibility(VISIBLE);
  1559 + }
  1560 + // 报错
  1561 + switch (error.type) {
  1562 + case ExoPlaybackException.TYPE_SOURCE:
  1563 + // 加载资源时出错
  1564 + break;
  1565 + case ExoPlaybackException.TYPE_RENDERER:
  1566 + // 渲染时出错
  1567 + break;
  1568 + case ExoPlaybackException.TYPE_UNEXPECTED:
  1569 + // 意外的错误
  1570 + break;
  1571 + }
  1572 + }
  1573 +
  1574 + @Override
  1575 + public void onLoadCompleted(EventTime eventTime, MediaSourceEventListener.LoadEventInfo loadEventInfo, MediaSourceEventListener.MediaLoadData mediaLoadData) {
  1576 + bufferingView.setVisibility(GONE);
  1577 + }
  1578 +
  1579 + @Override
  1580 + public void onLoadError(EventTime eventTime, MediaSourceEventListener.LoadEventInfo loadEventInfo, MediaSourceEventListener.MediaLoadData mediaLoadData, IOException error, boolean wasCanceled) {
  1581 + bufferingView.setVisibility(GONE);
  1582 + }
  1583 +
  1584 + @Override
  1585 + public void onPlayerStateChanged(EventTime eventTime, boolean playWhenReady, int playbackState) {
  1586 + switch (playbackState) {
  1587 + case Player.STATE_IDLE:
  1588 + Log.e(TAG, "空闲 ");
  1589 + // 空闲
  1590 + break;
  1591 + case Player.STATE_BUFFERING:
  1592 + // 缓冲中
  1593 + Log.e(TAG, "缓冲中 ");
  1594 + break;
  1595 + case Player.STATE_READY:
  1596 + Log.e(TAG, "准备好 ");
  1597 +
  1598 + // 准备好
  1599 + break;
  1600 + case Player.STATE_ENDED:
  1601 + // 结束
  1602 + break;
  1603 + default:
  1604 + break;
  1605 + }
  1606 + }
1542 } 1607 }
1543 1608
cloud/video/src/main/java/com/libs/video/video/exoplayer/IVideoMultDataSource.java 0 → 100644
  1 +package com.libs.video.video.exoplayer;
  2 +
  3 +import android.net.Uri;
  4 +
  5 +import java.util.List;
  6 +
  7 +/**
  8 + * 多资源播放
  9 + */
  10 +public interface IVideoMultDataSource {
  11 + List<String> getDataSourceId();
  12 +
  13 + List<String> getDataSourceType();
  14 +
  15 + List<String> getPlayUri();
  16 +}
cloud/video/src/main/java/com/libs/video/video/exoplayer/IVideoPlayer.java
@@ -19,16 +19,17 @@ import com.google.android.exoplayer2.ui.PlayerView; @@ -19,16 +19,17 @@ import com.google.android.exoplayer2.ui.PlayerView;
19 import com.libs.video.video.base.IDataSource; 19 import com.libs.video.video.base.IDataSource;
20 import com.libs.video.video.base.IMediaPlayer; 20 import com.libs.video.video.base.IMediaPlayer;
21 21
  22 +import java.util.List;
  23 +
22 public interface IVideoPlayer { 24 public interface IVideoPlayer {
23 - // /**  
24 -// * 设置播放资源  
25 -// *  
26 -// * @param data  
27 -// */ 25 + void setDataSource(IVideoMultDataSource data);
  26 +
28 void setDataSource(IVideoDataSource data); 27 void setDataSource(IVideoDataSource data);
29 28
30 void setDataSource(Uri data); 29 void setDataSource(Uri data);
31 30
  31 + void setDataSource(List<String> data);
  32 +
32 void setPlayView(CNLiveVideoView playView); 33 void setPlayView(CNLiveVideoView playView);
33 34
34 void play() throws IllegalStateException; 35 void play() throws IllegalStateException;
@@ -39,7 +40,11 @@ public interface IVideoPlayer { @@ -39,7 +40,11 @@ public interface IVideoPlayer {
39 40
40 void prepare(); 41 void prepare();
41 42
42 - void prepare(boolean isPlay); 43 + void retry();
  44 +
  45 + void onPause();
  46 +
  47 + void onDestroy();
43 48
44 void setForegroundMode(boolean foregroundMode); 49 void setForegroundMode(boolean foregroundMode);
45 50
cloud/video/src/main/java/com/libs/video/video/exoplayer/MyTestControlView.java
@@ -13,6 +13,7 @@ import androidx.appcompat.widget.AppCompatSeekBar; @@ -13,6 +13,7 @@ import androidx.appcompat.widget.AppCompatSeekBar;
13 import androidx.core.content.ContextCompat; 13 import androidx.core.content.ContextCompat;
14 14
15 import com.cnlive.cloud.video.R; 15 import com.cnlive.cloud.video.R;
  16 +import com.google.android.exoplayer2.source.MediaSourceEventListener;
16 17
17 public class MyTestControlView extends CNLiveBaseVideoControlView { 18 public class MyTestControlView extends CNLiveBaseVideoControlView {
18 private View playButton; 19 private View playButton;
@@ -70,11 +71,14 @@ public class MyTestControlView extends CNLiveBaseVideoControlView { @@ -70,11 +71,14 @@ public class MyTestControlView extends CNLiveBaseVideoControlView {
70 } 71 }
71 72
72 @Override 73 @Override
  74 +// protected int getLandscapeControllViewId() {
  75 +// return R.layout.layout_landscape_control_view;
  76 +// }
  77 +
73 protected int getLandscapeControllViewId() { 78 protected int getLandscapeControllViewId() {
74 - return R.layout.layout_landscape_control_view; 79 + return -1;
75 } 80 }
76 81
77 -  
78 @Override 82 @Override
79 protected void onViewClick(View view) { 83 protected void onViewClick(View view) {
80 if (view.getId() == R.id.btn_start) { 84 if (view.getId() == R.id.btn_start) {
@@ -109,4 +113,13 @@ public class MyTestControlView extends CNLiveBaseVideoControlView { @@ -109,4 +113,13 @@ public class MyTestControlView extends CNLiveBaseVideoControlView {
109 seekBar.setMax((int) duration); 113 seekBar.setMax((int) duration);
110 } 114 }
111 115
112 -} 116 + @Override
  117 + public void onLoadStarted(EventTime eventTime, MediaSourceEventListener.LoadEventInfo loadEventInfo, MediaSourceEventListener.MediaLoadData mediaLoadData) {
  118 + super.onLoadStarted(eventTime, loadEventInfo, mediaLoadData);
  119 + }
  120 +
  121 + @Override
  122 + public void onLoadCompleted(EventTime eventTime, MediaSourceEventListener.LoadEventInfo loadEventInfo, MediaSourceEventListener.MediaLoadData mediaLoadData) {
  123 + super.onLoadCompleted(eventTime, loadEventInfo, mediaLoadData);
  124 + }
  125 +}
113 \ No newline at end of file 126 \ No newline at end of file
cloud/video/src/main/java/com/libs/video/video/exoplayer/VideoPlayer.java
@@ -15,6 +15,8 @@ import com.google.android.exoplayer2.SimpleExoPlayer; @@ -15,6 +15,8 @@ import com.google.android.exoplayer2.SimpleExoPlayer;
15 import com.google.android.exoplayer2.Timeline; 15 import com.google.android.exoplayer2.Timeline;
16 import com.google.android.exoplayer2.analytics.AnalyticsListener; 16 import com.google.android.exoplayer2.analytics.AnalyticsListener;
17 import com.google.android.exoplayer2.ext.rtmp.RtmpDataSourceFactory; 17 import com.google.android.exoplayer2.ext.rtmp.RtmpDataSourceFactory;
  18 +import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
  19 +import com.google.android.exoplayer2.source.ExtractorMediaSource;
18 import com.google.android.exoplayer2.source.MediaSource; 20 import com.google.android.exoplayer2.source.MediaSource;
19 import com.google.android.exoplayer2.source.ProgressiveMediaSource; 21 import com.google.android.exoplayer2.source.ProgressiveMediaSource;
20 import com.google.android.exoplayer2.source.TrackGroupArray; 22 import com.google.android.exoplayer2.source.TrackGroupArray;
@@ -208,8 +210,31 @@ public class VideoPlayer implements IVideoPlayer { @@ -208,8 +210,31 @@ public class VideoPlayer implements IVideoPlayer {
208 return buffer.toString(); 210 return buffer.toString();
209 } 211 }
210 212
  213 + /**
  214 + * 多资源播放
  215 + *
  216 + * @param data
  217 + */
  218 + @Override
  219 + public void setDataSource(IVideoMultDataSource data) {
  220 + if (null != data && null != data.getPlayUri()) {
  221 + MediaSource[] mediaSources = new MediaSource[data.getPlayUri().size()];
  222 + for (int i = 0; i < data.getPlayUri().size(); i++) {
  223 + mediaSources[i] = getPlayerMediaSource(data.getPlayUri().get(i));
  224 + }
  225 + currentMediaSource =
  226 + new ConcatenatingMediaSource(mediaSources);
  227 + }
  228 +
  229 +// LoopingMediaSource firstSourceTwice = new LoopingMediaSource(firstSource, 2);
  230 +
  231 + }
  232 +
211 @Override 233 @Override
212 public void setDataSource(IVideoDataSource data) { 234 public void setDataSource(IVideoDataSource data) {
  235 + ConcatenatingMediaSource concatenatedSource =
  236 + new ConcatenatingMediaSource();
  237 +
213 mDataSource = null; 238 mDataSource = null;
214 mDataSource = data; 239 mDataSource = data;
215 Map<String, String> probeData = new HashMap<>(); 240 Map<String, String> probeData = new HashMap<>();
@@ -270,6 +295,18 @@ public class VideoPlayer implements IVideoPlayer { @@ -270,6 +295,18 @@ public class VideoPlayer implements IVideoPlayer {
270 } 295 }
271 296
272 @Override 297 @Override
  298 + public void setDataSource(List<String> data) {
  299 + if (null != data) {
  300 + MediaSource[] mediaSources = new MediaSource[data.size()];
  301 + for (int i = 0; i < data.size(); i++) {
  302 + mediaSources[i] = getPlayerMediaSource(data.get(i));
  303 + }
  304 + currentMediaSource =
  305 + new ConcatenatingMediaSource(mediaSources);
  306 + }
  307 + }
  308 +
  309 + @Override
273 public void setPlayView(CNLiveVideoView playView) { 310 public void setPlayView(CNLiveVideoView playView) {
274 } 311 }
275 312
@@ -350,13 +387,29 @@ public class VideoPlayer implements IVideoPlayer { @@ -350,13 +387,29 @@ public class VideoPlayer implements IVideoPlayer {
350 } 387 }
351 388
352 @Override 389 @Override
353 - public void prepare(boolean isPlay) {  
354 - if (null != currentMediaSource && null != player) {  
355 - player.prepare(currentMediaSource);  
356 - player.setPlayWhenReady(isPlay); 390 + public void retry() {
  391 + if (null != player) {
  392 + player.retry();
  393 + }
  394 + }
  395 +
  396 + @Override
  397 + public void onPause() {
  398 + if (player != null) {
  399 + player.setPlayWhenReady(false);
357 } 400 }
358 } 401 }
359 402
  403 + @Override
  404 + public void onDestroy() {
  405 + if (player != null) {
  406 + player.stop();
  407 + player.release();
  408 + player = null;
  409 + }
  410 + }
  411 +
  412 +
360 private MediaSource getPlayerMediaSource(String playerUrl) { 413 private MediaSource getPlayerMediaSource(String playerUrl) {
361 if (TextUtils.isEmpty(playerUrl)) { 414 if (TextUtils.isEmpty(playerUrl)) {
362 return null; 415 return null;
@@ -536,18 +589,18 @@ public class VideoPlayer implements IVideoPlayer { @@ -536,18 +589,18 @@ public class VideoPlayer implements IVideoPlayer {
536 */ 589 */
537 @Override 590 @Override
538 public int getCurrentWindowIndex() { 591 public int getCurrentWindowIndex() {
539 - int result=0; 592 + int result = 0;
540 if (null != player) { 593 if (null != player) {
541 - result=player.getCurrentWindowIndex(); 594 + result = player.getCurrentWindowIndex();
542 } 595 }
543 return result; 596 return result;
544 } 597 }
545 598
546 @Override 599 @Override
547 public long getDuration() { 600 public long getDuration() {
548 - long result=0; 601 + long result = 0;
549 if (null != player) { 602 if (null != player) {
550 - result=player.getDuration(); 603 + result = player.getDuration();
551 } 604 }
552 return result; 605 return result;
553 } 606 }
cloud/video/src/main/res/drawable-hdpi/cover_youku_icon.png 0 → 100644

1.29 KB

cloud/video/src/main/res/drawable/video_seekbar_progress.xml
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 <item android:id="@android:id/secondaryProgress" > 11 <item android:id="@android:id/secondaryProgress" >
12 <clip> 12 <clip>
13 <shape> 13 <shape>
14 - <solid android:color="#bdbdbd"/> 14 + <solid android:color="@color/btnCancel"/>
15 </shape> 15 </shape>
16 </clip> 16 </clip>
17 </item> 17 </item>
cloud/video/src/main/res/layout/layout_base_video_view.xml
@@ -25,21 +25,6 @@ @@ -25,21 +25,6 @@
25 android:layout_width="match_parent" 25 android:layout_width="match_parent"
26 android:layout_height="match_parent" /> 26 android:layout_height="match_parent" />
27 27
28 - <ProgressBar  
29 - android:id="@id/cnlive_buffering"  
30 - android:layout_width="wrap_content"  
31 - android:layout_height="wrap_content"  
32 - android:layout_gravity="center"  
33 - android:indeterminate="true" />  
34 -  
35 - <TextView  
36 - android:id="@id/cnlive_error_message"  
37 - android:layout_width="match_parent"  
38 - android:layout_height="match_parent"  
39 - android:layout_gravity="center"  
40 - android:background="@color/exo_error_message_background_color"  
41 - android:gravity="center"  
42 - android:padding="16dp" />  
43 28
44 </com.google.android.exoplayer2.ui.AspectRatioFrameLayout> 29 </com.google.android.exoplayer2.ui.AspectRatioFrameLayout>
45 30
@@ -58,4 +43,25 @@ @@ -58,4 +43,25 @@
58 android:layout_width="match_parent" 43 android:layout_width="match_parent"
59 android:layout_height="match_parent" /> 44 android:layout_height="match_parent" />
60 45
  46 + <ProgressBar
  47 + android:id="@id/cnlive_buffering"
  48 + android:layout_width="wrap_content"
  49 + android:layout_height="wrap_content"
  50 + android:layout_gravity="center"
  51 + android:indeterminate="true" />
  52 +
  53 + <LinearLayout
  54 + android:id="@id/cnlive_error_message"
  55 + android:layout_width="match_parent"
  56 + android:layout_height="match_parent"
  57 + android:background="@color/black"
  58 + android:clickable="true"
  59 + android:gravity="center"
  60 + android:orientation="vertical">
  61 +
  62 + <Button
  63 + android:layout_width="wrap_content"
  64 + android:layout_height="wrap_content"
  65 + android:text="刷新" />
  66 + </LinearLayout>
61 </merge> 67 </merge>
62 \ No newline at end of file 68 \ No newline at end of file
cloud/video/src/main/res/layout/layout_protrait_control_view.xml
1 <?xml version="1.0" encoding="utf-8"?> 1 <?xml version="1.0" encoding="utf-8"?>
2 -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:id="@+id/rl_protrait_root" 3 android:id="@+id/rl_protrait_root"
4 android:layout_width="match_parent" 4 android:layout_width="match_parent"
5 android:layout_height="match_parent" 5 android:layout_height="match_parent"
  6 + android:background="@color/transparent"
6 android:orientation="vertical"> 7 android:orientation="vertical">
7 8
8 <LinearLayout 9 <LinearLayout
@@ -15,7 +16,7 @@ @@ -15,7 +16,7 @@
15 <LinearLayout 16 <LinearLayout
16 android:layout_width="match_parent" 17 android:layout_width="match_parent"
17 android:layout_height="40dp" 18 android:layout_height="40dp"
18 - android:layout_alignParentBottom="true" 19 + android:layout_gravity="bottom"
19 android:background="@drawable/bg_cnvideo_bottom" 20 android:background="@drawable/bg_cnvideo_bottom"
20 android:gravity="center_vertical"> 21 android:gravity="center_vertical">
21 22
@@ -63,4 +64,4 @@ @@ -63,4 +64,4 @@
63 64
64 </LinearLayout> 65 </LinearLayout>
65 66
66 -</RelativeLayout>  
67 \ No newline at end of file 67 \ No newline at end of file
  68 +</FrameLayout>
68 \ No newline at end of file 69 \ No newline at end of file