Commit d6adfcf66da54db5238dfc075bd4d03d2c2e50d8

Authored by 杨帅
1 parent 14ed85cd

1 封装视频库

app/strike/src/main/AndroidManifest.xml
... ... @@ -9,7 +9,7 @@
9 9 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
10 10  
11 11 <application
12   - android:name="com.cnlive.strike.MyApp"
  12 + android:name="com.cnlive.strike.demo.exoplayer.demo.DemoApplication"
13 13 android:allowBackup="true"
14 14 android:icon="@mipmap/ic_launcher"
15 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 9 import android.os.Looper;
10 10 import android.util.AttributeSet;
11 11 import android.util.Log;
  12 +import android.view.Gravity;
12 13 import android.view.KeyEvent;
13 14 import android.view.LayoutInflater;
14 15 import android.view.Surface;
15 16 import android.view.View;
16   -import android.view.WindowManager;
  17 +import android.view.ViewGroup;
17 18 import android.widget.FrameLayout;
18   -import android.widget.TextView;
  19 +import android.widget.LinearLayout;
19 20  
20 21 import androidx.annotation.Nullable;
  22 +import androidx.core.content.ContextCompat;
21 23  
22 24 import com.cnlive.cloud.video.R;
23 25 import com.google.android.exoplayer2.C;
... ... @@ -25,7 +27,6 @@ import com.google.android.exoplayer2.ExoPlaybackException;
25 27 import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
26 28 import com.google.android.exoplayer2.Format;
27 29 import com.google.android.exoplayer2.PlaybackParameters;
28   -import com.google.android.exoplayer2.PlaybackPreparer;
29 30 import com.google.android.exoplayer2.Player;
30 31 import com.google.android.exoplayer2.Timeline;
31 32 import com.google.android.exoplayer2.analytics.AnalyticsListener;
... ... @@ -44,6 +45,9 @@ import java.util.Formatter;
44 45 import java.util.Locale;
45 46 import java.util.concurrent.CopyOnWriteArrayList;
46 47  
  48 +/**
  49 + * 视频控制视图基类
  50 + */
47 51 public abstract class CNLiveBaseVideoControlView extends FrameLayout implements AnalyticsListener {
48 52  
49 53 static {
... ... @@ -135,7 +139,10 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
135 139 private FrameLayout fl_root;//根布局
136 140 @Nullable
137 141 public Context context;
  142 + //用于获取当前屏幕朝向
138 143 private Configuration newConfig;
  144 + //延时隐藏当前播放视图
  145 + private Runnable delayHideViewAction;
139 146  
140 147 public CNLiveBaseVideoControlView(Context context) {
141 148 this(context, /* attrs= */ null, 0, null);
... ... @@ -143,14 +150,29 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
143 150 visibilityListeners = new CopyOnWriteArrayList<>();
144 151 }
145 152  
  153 + /**
  154 + * 获取竖屏ui
  155 + *
  156 + * @return
  157 + */
146 158 protected int getPortraitControllViewId() {
147 159 return -1;
148 160 }
149 161  
  162 + /**
  163 + * 获取横屏UI
  164 + *
  165 + * @return
  166 + */
150 167 protected int getLandscapeControllViewId() {
151 168 return -1;
152 169 }
153 170  
  171 + /**
  172 + * 按鈕点击事件
  173 + *
  174 + * @param view
  175 + */
154 176 protected abstract void onViewClick(View view);
155 177  
156 178 @SuppressWarnings({
... ... @@ -168,6 +190,7 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
168 190 if (context instanceof Activity) {
169 191 this.activity = (Activity) context;
170 192 }
  193 +
171 194 formatBuilder = new StringBuilder();
172 195 formatter = new Formatter(formatBuilder, Locale.getDefault());
173 196 period = new Timeline.Period();
... ... @@ -177,147 +200,9 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
177 200 componentListener = new CNLiveBaseVideoControlView.ComponentListener();
178 201 // controlDispatcher = new CNLiveDefaultControlDispatcher();
179 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 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 207 baseRootView = LayoutInflater.from(context).inflate(R.layout.layout_cnlive_control_view, /* root= */ this);
323 208 if (null != baseRootView) {
... ... @@ -326,21 +211,8 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
326 211 baseRootView.post(new Runnable() {
327 212 @Override
328 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 216 if (null != componentListener && null != basePortraitView) {
345 217 initPortraitView(basePortraitView, componentListener);
346 218 }
... ... @@ -348,27 +220,98 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
348 220 baseRootView.setOnClickListener(new OnClickListener() {
349 221 @Override
350 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 328 * 显示横屏
386 329 */
387 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 351 if (null == basePortraitView) {
408 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 355 if (null != baseLandscapeView) {
416 356 baseLandscapeView.setVisibility(GONE);
417 357 }
... ... @@ -554,35 +494,6 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
554 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 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 686 * 更新进度条
776 687 */
777 688 private void updateProgress() {
778   - if (!isVisible() || !isAttachedToWindow) {
  689 + if (!isVisible() || !isAttachedToWindow || null == basePortraitView) {
779 690 return;
780 691 }
781 692 long position = 0;
... ... @@ -783,23 +694,18 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
783 694 position = player.getContentPosition();
784 695 }
785 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 698 removeCallbacks(updateProgressAction);
794 699 int playbackState = player == null ? Player.STATE_IDLE : player.getPlaybackState();
795   - onProgressChange(position, Util.getStringForTime(formatBuilder, formatter, position));
796 700 if (player != null && player.isPlaying()) {
797 701 postDelayed(updateProgressAction, MAX_UPDATE_INTERVAL_MS);
  702 + onProgressChange(position, Util.getStringForTime(formatBuilder, formatter, position));
798 703 } else if (playbackState != Player.STATE_ENDED && playbackState != Player.STATE_IDLE) {
799 704 postDelayed(updateProgressAction, MAX_UPDATE_INTERVAL_MS);
800 705 }
801 706 }
802 707  
  708 +
803 709 // private void requestPlayPauseFocus() {
804 710 // boolean shouldShowPauseButton = shouldShowPauseButton();
805 711 // if (!shouldShowPauseButton && playButton != null) {
... ... @@ -818,7 +724,7 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
818 724 // view.setVisibility(VISIBLE);
819 725 // }
820 726  
821   - private void previous(VideoPlayer player) {
  727 + private void previous() {
822 728 Timeline timeline = player.getCurrentTimeline();
823 729 if (timeline.isEmpty() || player.isPlayingAd()) {
824 730 return;
... ... @@ -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 748 Timeline timeline = player.getCurrentTimeline();
845 749 if (timeline.isEmpty() || player.isPlayingAd()) {
846 750 return;
... ... @@ -942,7 +846,12 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
942 846 public void onDetachedFromWindow() {
943 847 super.onDetachedFromWindow();
944 848 isAttachedToWindow = false;
945   - removeCallbacks(updateProgressAction);
  849 + if (null != delayHideViewAction) {
  850 + removeCallbacks(delayHideViewAction);
  851 + }
  852 + if (null != updateProgressAction) {
  853 + removeCallbacks(updateProgressAction);
  854 + }
946 855 // removeCallbacks(hideAction);
947 856 }
948 857  
... ... @@ -994,10 +903,10 @@ public abstract class CNLiveBaseVideoControlView extends FrameLayout implements
994 903 pauseVideo();
995 904 break;
996 905 case KeyEvent.KEYCODE_MEDIA_NEXT:
997   - next(player);
  906 +// next(player);
998 907 break;
999 908 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
1000   - previous(player);
  909 +// previous(player);
1001 910 break;
1002 911 default:
1003 912 break;
... ... @@ -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 1019 //获取当前屏幕朝向
1118 1020 Configuration mConfiguration = activity.getResources().getConfiguration(); //获取设置的配置信息
1119 1021 int ori = mConfiguration.orientation; //获取屏幕方向
1120   - if (ori == mConfiguration.ORIENTATION_LANDSCAPE) {
  1022 + if (ori == Configuration.ORIENTATION_LANDSCAPE) {
1121 1023 //强制为竖屏
1122 1024 activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
1123   - } else if (ori == mConfiguration.ORIENTATION_PORTRAIT) {
  1025 + } else if (ori == Configuration.ORIENTATION_PORTRAIT) {
1124 1026 //强制为横屏
1125 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 1040 protected void onConfigurationChanged(Configuration newConfig) {
1132 1041 super.onConfigurationChanged(newConfig);
1133 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 1138 }
1244 1139 }
1245 1140  
1246   - /**获取格式化后的时间
  1141 + /**
  1142 + * 获取格式化后的时间
  1143 + *
1247 1144 * @param duration
1248 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 29 import android.widget.ImageView;
30 30 import android.widget.LinearLayout;
31 31 import android.widget.TextView;
  32 +import android.widget.Toast;
32 33  
33 34 import androidx.annotation.ColorInt;
34 35 import androidx.annotation.IntDef;
... ... @@ -42,9 +43,11 @@ import com.google.android.exoplayer2.DefaultControlDispatcher;
42 43 import com.google.android.exoplayer2.ExoPlaybackException;
43 44 import com.google.android.exoplayer2.PlaybackPreparer;
44 45 import com.google.android.exoplayer2.Player;
  46 +import com.google.android.exoplayer2.analytics.AnalyticsListener;
45 47 import com.google.android.exoplayer2.metadata.Metadata;
46 48 import com.google.android.exoplayer2.metadata.flac.PictureFrame;
47 49 import com.google.android.exoplayer2.metadata.id3.ApicFrame;
  50 +import com.google.android.exoplayer2.source.MediaSourceEventListener;
48 51 import com.google.android.exoplayer2.source.TrackGroupArray;
49 52 import com.google.android.exoplayer2.source.ads.AdsLoader;
50 53 import com.google.android.exoplayer2.text.Cue;
... ... @@ -63,13 +66,18 @@ import com.google.android.exoplayer2.util.Util;
63 66 import com.google.android.exoplayer2.video.VideoDecoderGLSurfaceView;
64 67 import com.google.android.exoplayer2.video.VideoListener;
65 68  
  69 +import java.io.IOException;
66 70 import java.lang.annotation.Documented;
67 71 import java.lang.annotation.Retention;
68 72 import java.lang.annotation.RetentionPolicy;
69 73 import java.util.ArrayList;
70 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 82 * Determines when the buffering view is shown. One of {@link #SHOW_BUFFERING_NEVER}, {@link
75 83 * #SHOW_BUFFERING_WHEN_PLAYING} or {@link #SHOW_BUFFERING_ALWAYS}.
... ... @@ -118,7 +126,7 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
118 126 @Nullable
119 127 private final View bufferingView;
120 128 @Nullable
121   - private final TextView errorMessageView;
  129 + private final LinearLayout errorMessageView;
122 130 @Nullable
123 131 private CNLiveBaseVideoControlView controller;
124 132 @Nullable
... ... @@ -177,6 +185,8 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
177 185 componentListener = new CNLiveVideoView.ComponentListener();
178 186 //初始化videoplayer
179 187 player = new VideoPlayer(context);
  188 + //添加事件监听
  189 + player.addAnalyticsListener(this);
180 190 if (isInEditMode()) {
181 191 contentFrame = null;
182 192 shutterView = null;
... ... @@ -313,7 +323,13 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
313 323 if (errorMessageView != null) {
314 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 333 // Playback control view.
318 334 CNLiveBaseVideoControlView customController = findViewById(R.id.cnlive_controller);
319 335 controllerPlaceholder = findViewById(R.id.cnlive_controller_placeholder);
... ... @@ -399,8 +415,14 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
399 415 controller.addVisibilityListener(/* listener= */ componentListener);
400 416 }
401 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 426 setPlayer(player);
405 427 controllerPlaceholder.setOnClickListener(new OnClickListener() {
406 428 @Override
... ... @@ -763,16 +785,6 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
763 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 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 819 this.controllerShowTimeoutMs = controllerShowTimeoutMs;
808 820 if (controller.isVisible()) {
809 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 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 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 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 1172 private boolean isPlayingAd() {
1178 1173 return player != null && player.isPlayingAd() && player.getPlayWhenReady();
... ... @@ -1295,21 +1290,21 @@ public class CNLiveVideoView extends FrameLayout implements AdsLoader.AdViewProv
1295 1290 }
1296 1291  
1297 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 1310 private void updateContentDescription() {
... ... @@ -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 1489 public void onBackPress() {
1506 1490 if (null != controller) {
1507 1491 controller.onBackPress();
... ... @@ -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 19 import com.libs.video.video.base.IDataSource;
20 20 import com.libs.video.video.base.IMediaPlayer;
21 21  
  22 +import java.util.List;
  23 +
22 24 public interface IVideoPlayer {
23   - // /**
24   -// * 设置播放资源
25   -// *
26   -// * @param data
27   -// */
  25 + void setDataSource(IVideoMultDataSource data);
  26 +
28 27 void setDataSource(IVideoDataSource data);
29 28  
30 29 void setDataSource(Uri data);
31 30  
  31 + void setDataSource(List<String> data);
  32 +
32 33 void setPlayView(CNLiveVideoView playView);
33 34  
34 35 void play() throws IllegalStateException;
... ... @@ -39,7 +40,11 @@ public interface IVideoPlayer {
39 40  
40 41 void prepare();
41 42  
42   - void prepare(boolean isPlay);
  43 + void retry();
  44 +
  45 + void onPause();
  46 +
  47 + void onDestroy();
43 48  
44 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 13 import androidx.core.content.ContextCompat;
14 14  
15 15 import com.cnlive.cloud.video.R;
  16 +import com.google.android.exoplayer2.source.MediaSourceEventListener;
16 17  
17 18 public class MyTestControlView extends CNLiveBaseVideoControlView {
18 19 private View playButton;
... ... @@ -70,11 +71,14 @@ public class MyTestControlView extends CNLiveBaseVideoControlView {
70 71 }
71 72  
72 73 @Override
  74 +// protected int getLandscapeControllViewId() {
  75 +// return R.layout.layout_landscape_control_view;
  76 +// }
  77 +
73 78 protected int getLandscapeControllViewId() {
74   - return R.layout.layout_landscape_control_view;
  79 + return -1;
75 80 }
76 81  
77   -
78 82 @Override
79 83 protected void onViewClick(View view) {
80 84 if (view.getId() == R.id.btn_start) {
... ... @@ -109,4 +113,13 @@ public class MyTestControlView extends CNLiveBaseVideoControlView {
109 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 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 15 import com.google.android.exoplayer2.Timeline;
16 16 import com.google.android.exoplayer2.analytics.AnalyticsListener;
17 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 20 import com.google.android.exoplayer2.source.MediaSource;
19 21 import com.google.android.exoplayer2.source.ProgressiveMediaSource;
20 22 import com.google.android.exoplayer2.source.TrackGroupArray;
... ... @@ -208,8 +210,31 @@ public class VideoPlayer implements IVideoPlayer {
208 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 233 @Override
212 234 public void setDataSource(IVideoDataSource data) {
  235 + ConcatenatingMediaSource concatenatedSource =
  236 + new ConcatenatingMediaSource();
  237 +
213 238 mDataSource = null;
214 239 mDataSource = data;
215 240 Map<String, String> probeData = new HashMap<>();
... ... @@ -270,6 +295,18 @@ public class VideoPlayer implements IVideoPlayer {
270 295 }
271 296  
272 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 310 public void setPlayView(CNLiveVideoView playView) {
274 311 }
275 312  
... ... @@ -350,13 +387,29 @@ public class VideoPlayer implements IVideoPlayer {
350 387 }
351 388  
352 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 413 private MediaSource getPlayerMediaSource(String playerUrl) {
361 414 if (TextUtils.isEmpty(playerUrl)) {
362 415 return null;
... ... @@ -536,18 +589,18 @@ public class VideoPlayer implements IVideoPlayer {
536 589 */
537 590 @Override
538 591 public int getCurrentWindowIndex() {
539   - int result=0;
  592 + int result = 0;
540 593 if (null != player) {
541   - result=player.getCurrentWindowIndex();
  594 + result = player.getCurrentWindowIndex();
542 595 }
543 596 return result;
544 597 }
545 598  
546 599 @Override
547 600 public long getDuration() {
548   - long result=0;
  601 + long result = 0;
549 602 if (null != player) {
550   - result=player.getDuration();
  603 + result = player.getDuration();
551 604 }
552 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 11 <item android:id="@android:id/secondaryProgress" >
12 12 <clip>
13 13 <shape>
14   - <solid android:color="#bdbdbd"/>
  14 + <solid android:color="@color/btnCancel"/>
15 15 </shape>
16 16 </clip>
17 17 </item>
... ...
cloud/video/src/main/res/layout/layout_base_video_view.xml
... ... @@ -25,21 +25,6 @@
25 25 android:layout_width="match_parent"
26 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 29 </com.google.android.exoplayer2.ui.AspectRatioFrameLayout>
45 30  
... ... @@ -58,4 +43,25 @@
58 43 android:layout_width="match_parent"
59 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 67 </merge>
62 68 \ No newline at end of file
... ...
cloud/video/src/main/res/layout/layout_protrait_control_view.xml
1 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 3 android:id="@+id/rl_protrait_root"
4 4 android:layout_width="match_parent"
5 5 android:layout_height="match_parent"
  6 + android:background="@color/transparent"
6 7 android:orientation="vertical">
7 8  
8 9 <LinearLayout
... ... @@ -15,7 +16,7 @@
15 16 <LinearLayout
16 17 android:layout_width="match_parent"
17 18 android:layout_height="40dp"
18   - android:layout_alignParentBottom="true"
  19 + android:layout_gravity="bottom"
19 20 android:background="@drawable/bg_cnvideo_bottom"
20 21 android:gravity="center_vertical">
21 22  
... ... @@ -63,4 +64,4 @@
63 64  
64 65 </LinearLayout>
65 66  
66   -</RelativeLayout>
67 67 \ No newline at end of file
  68 +</FrameLayout>
68 69 \ No newline at end of file
... ...