Commit 146a809a9b7deb29a1e120326a32b663b8e3de7c

Authored by YangShuai
1 parent 97ca2a02

1 视频封装增加详细的错误信息回调

2 修改播放器初始化逻辑
Showing 28 changed files with 430 additions and 77 deletions
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.demo.exoplayer.demo.DemoApplication" 12 + android:name="com.cnlive.strike.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"
app/strike/src/main/java/com/cnlive/strike/demo/exoplayer/demo/DemoApplication.java renamed to app/strike/src/main/java/com/cnlive/strike/DemoApplication.java
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package com.cnlive.strike.demo.exoplayer.demo; 16 +package com.cnlive.strike;
17 17
18 import android.app.Application; 18 import android.app.Application;
19 19
@@ -23,6 +23,7 @@ import com.baidu.mapapi.SDKInitializer; @@ -23,6 +23,7 @@ import com.baidu.mapapi.SDKInitializer;
23 import com.cnlive.cloud.user.auth.UserService; 23 import com.cnlive.cloud.user.auth.UserService;
24 import com.cnlive.core.libs.base.application.AppConfig; 24 import com.cnlive.core.libs.base.application.AppConfig;
25 import com.cnlive.core.libs.base.application.BaseApplication; 25 import com.cnlive.core.libs.base.application.BaseApplication;
  26 +import com.cnlive.strike.demo.exoplayer.demo.DownloadTracker;
26 import com.google.android.exoplayer2.BuildConfig; 27 import com.google.android.exoplayer2.BuildConfig;
27 import com.google.android.exoplayer2.DefaultRenderersFactory; 28 import com.google.android.exoplayer2.DefaultRenderersFactory;
28 import com.google.android.exoplayer2.RenderersFactory; 29 import com.google.android.exoplayer2.RenderersFactory;
@@ -45,6 +46,13 @@ import com.google.android.exoplayer2.upstream.cache.NoOpCacheEvictor; @@ -45,6 +46,13 @@ import com.google.android.exoplayer2.upstream.cache.NoOpCacheEvictor;
45 import com.google.android.exoplayer2.upstream.cache.SimpleCache; 46 import com.google.android.exoplayer2.upstream.cache.SimpleCache;
46 import com.google.android.exoplayer2.util.Log; 47 import com.google.android.exoplayer2.util.Log;
47 import com.google.android.exoplayer2.util.Util; 48 import com.google.android.exoplayer2.util.Util;
  49 +import com.libs.video.video.exoplayer.play.VideoViewConfig;
  50 +import com.libs.video.video.exoplayer.play.VideoViewManager;
  51 +import com.libs.video.video.exoplayer.playerCore.exoplayer.ExoMediaPlayerFactory;
  52 +import com.libs.video.video.exoplayer.render.surface.SurfaceRenderViewFactory;
  53 +import com.libs.video.video.exoplayer.render.texture.TextureRenderView;
  54 +import com.libs.video.video.exoplayer.render.texture.TextureRenderViewFactory;
  55 +
48 import java.io.File; 56 import java.io.File;
49 import java.io.IOException; 57 import java.io.IOException;
50 58
@@ -87,6 +95,21 @@ public class DemoApplication extends BaseApplication { @@ -87,6 +95,21 @@ public class DemoApplication extends BaseApplication {
87 com.cnlive.cloud.BuildConfig.SHARE_DOWNLOAD, com.cnlive.cloud.BuildConfig.SHARE_ICON, com.cnlive.cloud.BuildConfig.PAY_ACCOUNT, 95 com.cnlive.cloud.BuildConfig.SHARE_DOWNLOAD, com.cnlive.cloud.BuildConfig.SHARE_ICON, com.cnlive.cloud.BuildConfig.PAY_ACCOUNT,
88 com.cnlive.cloud.BuildConfig.SHARE_TITLE, com.cnlive.cloud.BuildConfig.SHARE_SUBTITLE, com.cnlive.cloud.BuildConfig.REPORT_URL, 96 com.cnlive.cloud.BuildConfig.SHARE_TITLE, com.cnlive.cloud.BuildConfig.SHARE_SUBTITLE, com.cnlive.cloud.BuildConfig.REPORT_URL,
89 com.cnlive.cloud.BuildConfig.BAIDU_MAP_APP_KEY, com.cnlive.cloud.BuildConfig.SHOP_PATH); 97 com.cnlive.cloud.BuildConfig.BAIDU_MAP_APP_KEY, com.cnlive.cloud.BuildConfig.SHOP_PATH);
  98 +
  99 + //播放器配置,注意:此为全局配置,按需开启
  100 + VideoViewManager.setConfig(VideoViewConfig.newBuilder()
  101 + .setLogEnabled(com.cnlive.cloud.BuildConfig.DEBUG)//调试的时候请打开日志,方便排错
  102 +// .setPlayerFactory(IjkPlayerFactory.create())
  103 +// .setPlayerFactory(ThunderMediaPlayerFactory.create())
  104 + .setPlayerFactory(ExoMediaPlayerFactory.create())
  105 + .setRenderViewFactory(TextureRenderViewFactory.create())
  106 + .setEnableOrientation(true)
  107 +// .setEnableAudioFocus(false)
  108 +// .setScreenScaleType(VideoView.SCREEN_SCALE_MATCH_PARENT)
  109 +// .setAdaptCutout(false)
  110 +// .setPlayOnMobileNetwork(true)
  111 +// .setProgressManager(new ProgressManagerImpl())
  112 + .build());
90 // if (AppConfig.isDebug()) { 113 // if (AppConfig.isDebug()) {
91 // Constant.SERVICE_ID = 213511; 114 // Constant.SERVICE_ID = 213511;
92 // } else { 115 // } else {
app/strike/src/main/java/com/cnlive/strike/MyApp.java
@@ -7,6 +7,10 @@ import com.cnlive.cloud.BuildConfig; @@ -7,6 +7,10 @@ import com.cnlive.cloud.BuildConfig;
7 import com.cnlive.cloud.user.auth.UserService; 7 import com.cnlive.cloud.user.auth.UserService;
8 import com.cnlive.core.libs.base.application.AppConfig; 8 import com.cnlive.core.libs.base.application.AppConfig;
9 import com.cnlive.core.libs.base.application.BaseApplication; 9 import com.cnlive.core.libs.base.application.BaseApplication;
  10 +import com.libs.video.video.exoplayer.play.VideoViewConfig;
  11 +import com.libs.video.video.exoplayer.play.VideoViewManager;
  12 +import com.libs.video.video.exoplayer.playerCore.exoplayer.ExoMediaPlayerFactory;
  13 +import com.libs.video.video.exoplayer.render.surface.SurfaceRenderViewFactory;
10 14
11 public class MyApp extends BaseApplication { 15 public class MyApp extends BaseApplication {
12 @Override 16 @Override
@@ -19,6 +23,21 @@ public class MyApp extends BaseApplication { @@ -19,6 +23,21 @@ public class MyApp extends BaseApplication {
19 BuildConfig.SHARE_DOWNLOAD, BuildConfig.SHARE_ICON, BuildConfig.PAY_ACCOUNT, 23 BuildConfig.SHARE_DOWNLOAD, BuildConfig.SHARE_ICON, BuildConfig.PAY_ACCOUNT,
20 BuildConfig.SHARE_TITLE, BuildConfig.SHARE_SUBTITLE, BuildConfig.REPORT_URL, 24 BuildConfig.SHARE_TITLE, BuildConfig.SHARE_SUBTITLE, BuildConfig.REPORT_URL,
21 BuildConfig.BAIDU_MAP_APP_KEY, BuildConfig.SHOP_PATH); 25 BuildConfig.BAIDU_MAP_APP_KEY, BuildConfig.SHOP_PATH);
  26 +
  27 + //播放器配置,注意:此为全局配置,按需开启
  28 + VideoViewManager.setConfig(VideoViewConfig.newBuilder()
  29 + .setLogEnabled(BuildConfig.DEBUG)//调试的时候请打开日志,方便排错
  30 +// .setPlayerFactory(IjkPlayerFactory.create())
  31 +// .setPlayerFactory(ThunderMediaPlayerFactory.create())
  32 + .setPlayerFactory(ExoMediaPlayerFactory.create())
  33 + .setRenderViewFactory(SurfaceRenderViewFactory.create())
  34 + .setEnableOrientation(true)
  35 +// .setEnableAudioFocus(false)
  36 +// .setScreenScaleType(VideoView.SCREEN_SCALE_MATCH_PARENT)
  37 +// .setAdaptCutout(false)
  38 +// .setPlayOnMobileNetwork(true)
  39 +// .setProgressManager(new ProgressManagerImpl())
  40 + .build());
22 initARouter(); 41 initARouter();
23 // if (AppConfig.isDebug()) { 42 // if (AppConfig.isDebug()) {
24 // Constant.SERVICE_ID = 213511; 43 // Constant.SERVICE_ID = 213511;
app/strike/src/main/java/com/cnlive/strike/demo/activity/ExoPlayerActivity.java
@@ -17,6 +17,7 @@ import com.google.android.exoplayer2.source.hls.HlsMediaSource; @@ -17,6 +17,7 @@ import com.google.android.exoplayer2.source.hls.HlsMediaSource;
17 import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory; 17 import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
18 import com.google.android.exoplayer2.util.Util; 18 import com.google.android.exoplayer2.util.Util;
19 import com.google.android.exoplayer2.video.VideoListener; 19 import com.google.android.exoplayer2.video.VideoListener;
  20 +import com.libs.video.video.exoplayer.component.DefaultErrorView;
20 import com.libs.video.video.exoplayer.play.CNVideoView; 21 import com.libs.video.video.exoplayer.play.CNVideoView;
21 import com.libs.video.video.test.VideoPlayer; 22 import com.libs.video.video.test.VideoPlayer;
22 import com.libs.video.video.exoplayer.component.DefaultAdControlView; 23 import com.libs.video.video.exoplayer.component.DefaultAdControlView;
@@ -75,20 +76,9 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl @@ -75,20 +76,9 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl
75 // player.addListener(this); 76 // player.addListener(this);
76 // // Prepare the player with the source. 77 // // Prepare the player with the source.
77 player.prepare(hlsMediaSource); 78 player.prepare(hlsMediaSource);
78 - //播放器配置,注意:此为全局配置,按需开启  
79 - VideoViewManager.setConfig(VideoViewConfig.newBuilder()  
80 - .setLogEnabled(BuildConfig.DEBUG)//调试的时候请打开日志,方便排错  
81 -// .setPlayerFactory(IjkPlayerFactory.create())  
82 -// .setPlayerFactory(ThunderMediaPlayerFactory.create())  
83 - .setPlayerFactory(ExoMediaPlayerFactory.create())  
84 - .setRenderViewFactory(SurfaceRenderViewFactory.create())  
85 - .setEnableOrientation(true)  
86 -// .setEnableAudioFocus(false)  
87 -// .setScreenScaleType(VideoView.SCREEN_SCALE_MATCH_PARENT)  
88 -// .setAdaptCutout(false)  
89 -// .setPlayOnMobileNetwork(true)  
90 -// .setProgressManager(new ProgressManagerImpl())  
91 - .build()); 79 +
  80 +
  81 +
92 mController = new StandardVideoController(this); 82 mController = new StandardVideoController(this);
93 DefaultAdControlView adControlView = new DefaultAdControlView(this); 83 DefaultAdControlView adControlView = new DefaultAdControlView(this);
94 adControlView.setListener(new DefaultAdControlView.AdControlListener() { 84 adControlView.setListener(new DefaultAdControlView.AdControlListener() {
@@ -102,7 +92,9 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl @@ -102,7 +92,9 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl
102 playVideo(); 92 playVideo();
103 } 93 }
104 }); 94 });
105 - mController.addControlComponent(adControlView); 95 + DefaultErrorView errorView=new DefaultErrorView(this);
  96 + mController.addControlComponent(adControlView, errorView);
  97 + //直播
106 binding.playerView.setUrl("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8"); 98 binding.playerView.setUrl("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8");
107 binding.playerView.setVideoController(mController); 99 binding.playerView.setVideoController(mController);
108 binding.playerView.start(); 100 binding.playerView.start();
@@ -154,14 +146,16 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl @@ -154,14 +146,16 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl
154 private void playVideo() { 146 private void playVideo() {
155 binding.playerView.release(); 147 binding.playerView.release();
156 mController.removeAllControlComponent(); 148 mController.removeAllControlComponent();
157 - mController.addDefaultControlComponent("正片", false); 149 + mController.addDefaultControlComponent("正片", true);
158 //重新设置数据 150 //重新设置数据
159 - List<String> list = new ArrayList<>();  
160 - list.add("http://sbslive.cnrmobile.com/storage/storage4/76/23/10/14de52115893fb5371b7e064f910ab7b.3gp");  
161 - list.add("https://qq.com-ok-qq.com/20191005/24249_f5e36323/index.m3u8");  
162 - list.add("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8");  
163 - list.add("http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8");  
164 - binding.playerView.setDataSource(list); 151 +// List<String> list = new ArrayList<>();
  152 +// list.add("http://sbslive.cnrmobile.com/storage/storage4/76/23/10/14de52115893fb5371b7e064f910ab7b.3gp");
  153 +// list.add("https://qq.com-ok-qq.com/20191005/24249_f5e36323/index.m3u8");
  154 +// list.add("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8");
  155 +// list.add("http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8");
  156 +// binding.playerView.setDataSource(list);
  157 + binding.playerView.setUrl("rtmp://tyzg.rtmps2.cnlive.com/live-tyzg-577/577_999");
  158 +
165 //开始播放 159 //开始播放
166 binding.playerView.start(); 160 binding.playerView.start();
167 } 161 }
app/strike/src/main/java/com/cnlive/strike/demo/exoplayer/demo/DemoDownloadService.java
@@ -18,6 +18,7 @@ package com.cnlive.strike.demo.exoplayer.demo; @@ -18,6 +18,7 @@ package com.cnlive.strike.demo.exoplayer.demo;
18 import android.app.Notification; 18 import android.app.Notification;
19 19
20 import com.cnlive.cloud.R; 20 import com.cnlive.cloud.R;
  21 +import com.cnlive.strike.DemoApplication;
21 import com.google.android.exoplayer2.offline.Download; 22 import com.google.android.exoplayer2.offline.Download;
22 import com.google.android.exoplayer2.offline.DownloadManager; 23 import com.google.android.exoplayer2.offline.DownloadManager;
23 import com.google.android.exoplayer2.offline.DownloadService; 24 import com.google.android.exoplayer2.offline.DownloadService;
app/strike/src/main/java/com/cnlive/strike/demo/exoplayer/demo/PlayerActivity.java
@@ -33,6 +33,7 @@ import androidx.annotation.Nullable; @@ -33,6 +33,7 @@ import androidx.annotation.Nullable;
33 import androidx.appcompat.app.AppCompatActivity; 33 import androidx.appcompat.app.AppCompatActivity;
34 34
35 import com.cnlive.cloud.R; 35 import com.cnlive.cloud.R;
  36 +import com.cnlive.strike.DemoApplication;
36 import com.google.android.exoplayer2.C; 37 import com.google.android.exoplayer2.C;
37 import com.google.android.exoplayer2.C.ContentType; 38 import com.google.android.exoplayer2.C.ContentType;
38 import com.google.android.exoplayer2.ExoPlaybackException; 39 import com.google.android.exoplayer2.ExoPlaybackException;
app/strike/src/main/java/com/cnlive/strike/demo/exoplayer/demo/SampleChooserActivity.java
@@ -38,6 +38,7 @@ import androidx.annotation.Nullable; @@ -38,6 +38,7 @@ import androidx.annotation.Nullable;
38 import androidx.appcompat.app.AppCompatActivity; 38 import androidx.appcompat.app.AppCompatActivity;
39 39
40 import com.cnlive.cloud.R; 40 import com.cnlive.cloud.R;
  41 +import com.cnlive.strike.DemoApplication;
41 import com.google.android.exoplayer2.ParserException; 42 import com.google.android.exoplayer2.ParserException;
42 import com.google.android.exoplayer2.RenderersFactory; 43 import com.google.android.exoplayer2.RenderersFactory;
43 import com.google.android.exoplayer2.offline.DownloadService; 44 import com.google.android.exoplayer2.offline.DownloadService;
@@ -55,7 +56,7 @@ import java.util.ArrayList; @@ -55,7 +56,7 @@ import java.util.ArrayList;
55 import java.util.Arrays; 56 import java.util.Arrays;
56 import java.util.Collections; 57 import java.util.Collections;
57 import java.util.List; 58 import java.util.List;
58 -import com.cnlive.strike.demo.exoplayer.demo.Sample; 59 +
59 /** An activity for selecting from a list of media samples. */ 60 /** An activity for selecting from a list of media samples. */
60 public class SampleChooserActivity extends AppCompatActivity 61 public class SampleChooserActivity extends AppCompatActivity
61 implements DownloadTracker.Listener, OnChildClickListener { 62 implements DownloadTracker.Listener, OnChildClickListener {
app/strike/src/main/res/layout/activity_explayer.xml
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 4 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
5 android:layout_width="match_parent" 5 android:layout_width="match_parent"
6 android:layout_height="match_parent" 6 android:layout_height="match_parent"
7 - android:background="@color/black" 7 + android:background="@color/white"
8 android:orientation="vertical"> 8 android:orientation="vertical">
9 9
10 <!-- <com.libs.video.video.test.CNLiveVideoView--> 10 <!-- <com.libs.video.video.test.CNLiveVideoView-->
cloud/video/src/main/java/com/libs/video/video/exoplayer/PlayErrorException.java 0 → 100644
  1 +package com.libs.video.video.exoplayer;
  2 +
  3 +import android.media.MediaPlayer;
  4 +import android.text.TextUtils;
  5 +
  6 +import androidx.annotation.IntDef;
  7 +
  8 +import com.cnlive.core.libs.base.util.StatusBarConfig;
  9 +
  10 +import java.lang.annotation.Retention;
  11 +import java.lang.annotation.RetentionPolicy;
  12 +
  13 +/**
  14 + * 播放异常
  15 + */
  16 +public class PlayErrorException extends Exception {
  17 + public static final int TYPE_NETWORK_ERROR = 0;//网络错误
  18 + public static final int TYPE_SOURCE_ERROR = 1;//资源错误
  19 + public static final int TYPE_OUT_OF_MEMORY = 2;//内存溢出
  20 + public static final int TYPE_UNEXPECTED_ERROR = 3;//未知错误
  21 + public static final int TYPE_RENDERER_ERROR = 4;//渲染异常
  22 + public static final int TYPE_MediaPlayer_IOException = 5;
  23 + public static final int TYPE_MediaPlayer_IllegalArgumentException = 6;
  24 + public static final int TYPE_MediaPlayer_SecurityException = 7;
  25 + public static final int TYPE_MediaPlayer_IllegalStateException = 8;
  26 + public static final int TYPE_MediaPlayer_unknownException = 9;
  27 + public static final int TYPE_MediaPlayer_ON_ERROR = 10;
  28 +
  29 +
  30 + private int errorType;//错误类型
  31 + private String errorMsg;//错误信息
  32 +
  33 +
  34 + private MediaPlayer mediaPlayer;
  35 + private int mediaPlayer_what;
  36 + private int mediaPlayer_extra;
  37 +
  38 +
  39 + @IntDef({TYPE_NETWORK_ERROR, TYPE_SOURCE_ERROR, TYPE_OUT_OF_MEMORY, TYPE_UNEXPECTED_ERROR, TYPE_RENDERER_ERROR,
  40 + TYPE_MediaPlayer_IOException, TYPE_MediaPlayer_IllegalArgumentException, TYPE_MediaPlayer_SecurityException,
  41 + TYPE_MediaPlayer_IllegalStateException, TYPE_MediaPlayer_unknownException, TYPE_MediaPlayer_ON_ERROR})
  42 + @Retention(RetentionPolicy.SOURCE)
  43 + public @interface Type {
  44 + }
  45 +
  46 + public PlayErrorException() {
  47 + }
  48 +
  49 + public PlayErrorException(@PlayErrorException.Type int errorType, String errorMsg) {
  50 + this.errorType = errorType;
  51 + this.errorMsg = errorMsg;
  52 + }
  53 +
  54 + public int getErrorType() {
  55 + return errorType;
  56 + }
  57 +
  58 + public void setErrorType(int errorType) {
  59 + this.errorType = errorType;
  60 + }
  61 +
  62 + public String getErrorMsg() {
  63 + if (!TextUtils.isEmpty(errorMsg)) {
  64 + return errorMsg;
  65 + }
  66 + return "";
  67 + }
  68 +
  69 + public void setErrorMsg(String errorMsg) {
  70 + this.errorMsg = errorMsg;
  71 + }
  72 +
  73 + public MediaPlayer getMediaPlayer() {
  74 + return mediaPlayer;
  75 + }
  76 +
  77 + public void setMediaPlayer(MediaPlayer mediaPlayer) {
  78 + this.mediaPlayer = mediaPlayer;
  79 + }
  80 +
  81 + public int getMediaPlayer_what() {
  82 + return mediaPlayer_what;
  83 + }
  84 +
  85 + public void setMediaPlayer_what(int mediaPlayer_what) {
  86 + this.mediaPlayer_what = mediaPlayer_what;
  87 + }
  88 +
  89 + public int getMediaPlayer_extra() {
  90 + return mediaPlayer_extra;
  91 + }
  92 +
  93 + public void setMediaPlayer_extra(int mediaPlayer_extra) {
  94 + this.mediaPlayer_extra = mediaPlayer_extra;
  95 + }
  96 +}
cloud/video/src/main/java/com/libs/video/video/exoplayer/component/DefaultAdControlView.java
@@ -12,6 +12,7 @@ import android.widget.TextView; @@ -12,6 +12,7 @@ import android.widget.TextView;
12 12
13 13
14 import com.cnlive.cloud.video.R; 14 import com.cnlive.cloud.video.R;
  15 +import com.libs.video.video.exoplayer.PlayErrorException;
15 import com.libs.video.video.exoplayer.controller.ControlWrapper; 16 import com.libs.video.video.exoplayer.controller.ControlWrapper;
16 import com.libs.video.video.exoplayer.controller.IControlComponent; 17 import com.libs.video.video.exoplayer.controller.IControlComponent;
17 import com.libs.video.video.exoplayer.play.CNVideoView; 18 import com.libs.video.video.exoplayer.play.CNVideoView;
@@ -82,6 +83,9 @@ public class DefaultAdControlView extends FrameLayout implements IControlCompone @@ -82,6 +83,9 @@ public class DefaultAdControlView extends FrameLayout implements IControlCompone
82 83
83 } 84 }
84 85
  86 + /**
  87 + * @param playState
  88 + */
85 @Override 89 @Override
86 public void onPlayStateChanged(int playState) { 90 public void onPlayStateChanged(int playState) {
87 switch (playState) { 91 switch (playState) {
@@ -92,6 +96,8 @@ public class DefaultAdControlView extends FrameLayout implements IControlCompone @@ -92,6 +96,8 @@ public class DefaultAdControlView extends FrameLayout implements IControlCompone
92 case CNVideoView.STATE_PAUSED: 96 case CNVideoView.STATE_PAUSED:
93 mPlayButton.setSelected(false); 97 mPlayButton.setSelected(false);
94 break; 98 break;
  99 + case CNVideoView.STATE_ERROR:
  100 + break;
95 } 101 }
96 } 102 }
97 103
@@ -123,6 +129,11 @@ public class DefaultAdControlView extends FrameLayout implements IControlCompone @@ -123,6 +129,11 @@ public class DefaultAdControlView extends FrameLayout implements IControlCompone
123 } 129 }
124 130
125 @Override 131 @Override
  132 + public void onPlayError(PlayErrorException exception) {
  133 +
  134 + }
  135 +
  136 + @Override
126 public void onClick(View v) { 137 public void onClick(View v) {
127 int id = v.getId(); 138 int id = v.getId();
128 if (id == R.id.back | id == R.id.fullscreen) { 139 if (id == R.id.back | id == R.id.fullscreen) {
cloud/video/src/main/java/com/libs/video/video/exoplayer/component/DefaultCompleteView.java
@@ -11,6 +11,7 @@ import android.widget.FrameLayout; @@ -11,6 +11,7 @@ import android.widget.FrameLayout;
11 import android.widget.ImageView; 11 import android.widget.ImageView;
12 12
13 import com.cnlive.cloud.video.R; 13 import com.cnlive.cloud.video.R;
  14 +import com.libs.video.video.exoplayer.PlayErrorException;
14 import com.libs.video.video.exoplayer.controller.ControlWrapper; 15 import com.libs.video.video.exoplayer.controller.ControlWrapper;
15 import com.libs.video.video.exoplayer.controller.IControlComponent; 16 import com.libs.video.video.exoplayer.controller.IControlComponent;
16 import com.libs.video.video.exoplayer.play.CNVideoView; 17 import com.libs.video.video.exoplayer.play.CNVideoView;
@@ -125,4 +126,9 @@ public class DefaultCompleteView extends FrameLayout implements IControlComponen @@ -125,4 +126,9 @@ public class DefaultCompleteView extends FrameLayout implements IControlComponen
125 public void onLockStateChanged(boolean isLock) { 126 public void onLockStateChanged(boolean isLock) {
126 127
127 } 128 }
  129 +
  130 + @Override
  131 + public void onPlayError(PlayErrorException exception) {
  132 +
  133 + }
128 } 134 }
cloud/video/src/main/java/com/libs/video/video/exoplayer/component/DefaultErrorView.java
@@ -2,16 +2,22 @@ package com.libs.video.video.exoplayer.component; @@ -2,16 +2,22 @@ package com.libs.video.video.exoplayer.component;
2 2
3 import android.content.Context; 3 import android.content.Context;
4 import android.util.AttributeSet; 4 import android.util.AttributeSet;
  5 +import android.util.Log;
5 import android.view.LayoutInflater; 6 import android.view.LayoutInflater;
6 import android.view.MotionEvent; 7 import android.view.MotionEvent;
7 import android.view.View; 8 import android.view.View;
8 import android.view.ViewConfiguration; 9 import android.view.ViewConfiguration;
9 import android.view.animation.Animation; 10 import android.view.animation.Animation;
  11 +import android.widget.Button;
10 import android.widget.LinearLayout; 12 import android.widget.LinearLayout;
  13 +import android.widget.TextView;
11 14
12 import com.cnlive.cloud.video.R; 15 import com.cnlive.cloud.video.R;
  16 +import com.cnlive.core.libs.base.util.NetworkUtil;
  17 +import com.libs.video.video.exoplayer.PlayErrorException;
13 import com.libs.video.video.exoplayer.controller.ControlWrapper; 18 import com.libs.video.video.exoplayer.controller.ControlWrapper;
14 import com.libs.video.video.exoplayer.controller.IControlComponent; 19 import com.libs.video.video.exoplayer.controller.IControlComponent;
  20 +import com.libs.video.video.exoplayer.play.AbstractPlayer;
15 import com.libs.video.video.exoplayer.play.CNVideoView; 21 import com.libs.video.video.exoplayer.play.CNVideoView;
16 22
17 import androidx.annotation.NonNull; 23 import androidx.annotation.NonNull;
@@ -24,8 +30,10 @@ public class DefaultErrorView extends LinearLayout implements IControlComponent @@ -24,8 +30,10 @@ public class DefaultErrorView extends LinearLayout implements IControlComponent
24 30
25 private float mDownX; 31 private float mDownX;
26 private float mDownY; 32 private float mDownY;
27 -  
28 - private ControlWrapper mControlWrapper; 33 + private Button btnRetry;
  34 + private TextView tvMessage;
  35 + private ControlWrapper mControlWrapper;//公共控制接口
  36 + private String TAG = this.getClass().getName();
29 37
30 public DefaultErrorView(Context context) { 38 public DefaultErrorView(Context context) {
31 this(context, null); 39 this(context, null);
@@ -42,7 +50,9 @@ public class DefaultErrorView extends LinearLayout implements IControlComponent @@ -42,7 +50,9 @@ public class DefaultErrorView extends LinearLayout implements IControlComponent
42 { 50 {
43 setVisibility(GONE); 51 setVisibility(GONE);
44 LayoutInflater.from(getContext()).inflate(R.layout.cnvideo_layout_error_view, this, true); 52 LayoutInflater.from(getContext()).inflate(R.layout.cnvideo_layout_error_view, this, true);
45 - findViewById(R.id.status_btn).setOnClickListener(new OnClickListener() { 53 + btnRetry = findViewById(R.id.btn_retry);
  54 + tvMessage=findViewById(R.id.tv_message);
  55 + btnRetry.setOnClickListener(new OnClickListener() {
46 @Override 56 @Override
47 public void onClick(View v) { 57 public void onClick(View v) {
48 setVisibility(GONE); 58 setVisibility(GONE);
@@ -62,14 +72,11 @@ public class DefaultErrorView extends LinearLayout implements IControlComponent @@ -62,14 +72,11 @@ public class DefaultErrorView extends LinearLayout implements IControlComponent
62 return this; 72 return this;
63 } 73 }
64 74
65 - @Override  
66 - public void onVisibilityChanged(boolean isVisible, Animation anim) {  
67 -  
68 - }  
69 75
70 @Override 76 @Override
71 public void onPlayStateChanged(int playState) { 77 public void onPlayStateChanged(int playState) {
72 if (playState == CNVideoView.STATE_ERROR) { 78 if (playState == CNVideoView.STATE_ERROR) {
  79 + //将view的z轴改变,置于父view的最上方。这个方法会将view从父view中移除,再添加到父view中。
73 bringToFront(); 80 bringToFront();
74 setVisibility(VISIBLE); 81 setVisibility(VISIBLE);
75 } else if (playState == CNVideoView.STATE_IDLE) { 82 } else if (playState == CNVideoView.STATE_IDLE) {
@@ -77,20 +84,6 @@ public class DefaultErrorView extends LinearLayout implements IControlComponent @@ -77,20 +84,6 @@ public class DefaultErrorView extends LinearLayout implements IControlComponent
77 } 84 }
78 } 85 }
79 86
80 - @Override  
81 - public void onPlayerStateChanged(int playerState) {  
82 -  
83 - }  
84 -  
85 - @Override  
86 - public void setProgress(int duration, int position) {  
87 -  
88 - }  
89 -  
90 - @Override  
91 - public void onLockStateChanged(boolean isLock) {  
92 -  
93 - }  
94 87
95 @Override 88 @Override
96 public boolean dispatchTouchEvent(MotionEvent ev) { 89 public boolean dispatchTouchEvent(MotionEvent ev) {
@@ -113,4 +106,39 @@ public class DefaultErrorView extends LinearLayout implements IControlComponent @@ -113,4 +106,39 @@ public class DefaultErrorView extends LinearLayout implements IControlComponent
113 } 106 }
114 return super.dispatchTouchEvent(ev); 107 return super.dispatchTouchEvent(ev);
115 } 108 }
  109 +
  110 + @Override
  111 + public void onVisibilityChanged(boolean isVisible, Animation anim) {
  112 +
  113 + }
  114 +
  115 + @Override
  116 + public void onPlayerStateChanged(int playerState) {
  117 +
  118 + }
  119 +
  120 + @Override
  121 + public void setProgress(int duration, int position) {
  122 +
  123 + }
  124 +
  125 + @Override
  126 + public void onLockStateChanged(boolean isLock) {
  127 +
  128 + }
  129 +
  130 + @Override
  131 + public void onPlayError(PlayErrorException exception) {
  132 + //获取当前类型
  133 + if (null == tvMessage) {
  134 + return;
  135 + }
  136 + switch (exception.getErrorType()) {
  137 + case PlayErrorException.TYPE_NETWORK_ERROR:
  138 + tvMessage.setText(exception.getErrorMsg());
  139 + break;
  140 + }
  141 + }
  142 +
  143 +
116 } 144 }
cloud/video/src/main/java/com/libs/video/video/exoplayer/component/DefaultPrepareView.java
@@ -10,6 +10,7 @@ import android.widget.ImageView; @@ -10,6 +10,7 @@ import android.widget.ImageView;
10 import android.widget.ProgressBar; 10 import android.widget.ProgressBar;
11 11
12 import com.cnlive.cloud.video.R; 12 import com.cnlive.cloud.video.R;
  13 +import com.libs.video.video.exoplayer.PlayErrorException;
13 import com.libs.video.video.exoplayer.controller.ControlWrapper; 14 import com.libs.video.video.exoplayer.controller.ControlWrapper;
14 import com.libs.video.video.exoplayer.controller.IControlComponent; 15 import com.libs.video.video.exoplayer.controller.IControlComponent;
15 import com.libs.video.video.exoplayer.play.CNVideoView; 16 import com.libs.video.video.exoplayer.play.CNVideoView;
@@ -133,4 +134,9 @@ public class DefaultPrepareView extends FrameLayout implements IControlComponent @@ -133,4 +134,9 @@ public class DefaultPrepareView extends FrameLayout implements IControlComponent
133 public void onLockStateChanged(boolean isLocked) { 134 public void onLockStateChanged(boolean isLocked) {
134 135
135 } 136 }
  137 +
  138 + @Override
  139 + public void onPlayError(PlayErrorException exception) {
  140 +
  141 + }
136 } 142 }
cloud/video/src/main/java/com/libs/video/video/exoplayer/component/DefaultTitleView.java
@@ -18,6 +18,7 @@ import android.widget.TextView; @@ -18,6 +18,7 @@ import android.widget.TextView;
18 18
19 19
20 import com.cnlive.cloud.video.R; 20 import com.cnlive.cloud.video.R;
  21 +import com.libs.video.video.exoplayer.PlayErrorException;
21 import com.libs.video.video.exoplayer.controller.ControlWrapper; 22 import com.libs.video.video.exoplayer.controller.ControlWrapper;
22 import com.libs.video.video.exoplayer.controller.IControlComponent; 23 import com.libs.video.video.exoplayer.controller.IControlComponent;
23 import com.libs.video.video.exoplayer.play.CNVideoView; 24 import com.libs.video.video.exoplayer.play.CNVideoView;
@@ -184,6 +185,11 @@ public class DefaultTitleView extends FrameLayout implements IControlComponent { @@ -184,6 +185,11 @@ public class DefaultTitleView extends FrameLayout implements IControlComponent {
184 } 185 }
185 } 186 }
186 187
  188 + @Override
  189 + public void onPlayError(PlayErrorException exception) {
  190 +
  191 + }
  192 +
187 private static class BatteryReceiver extends BroadcastReceiver { 193 private static class BatteryReceiver extends BroadcastReceiver {
188 private ImageView pow; 194 private ImageView pow;
189 195
cloud/video/src/main/java/com/libs/video/video/exoplayer/component/DefaultVodControlView.java
@@ -18,6 +18,7 @@ import android.widget.SeekBar; @@ -18,6 +18,7 @@ import android.widget.SeekBar;
18 import android.widget.TextView; 18 import android.widget.TextView;
19 19
20 import com.cnlive.cloud.video.R; 20 import com.cnlive.cloud.video.R;
  21 +import com.libs.video.video.exoplayer.PlayErrorException;
21 import com.libs.video.video.exoplayer.controller.ControlWrapper; 22 import com.libs.video.video.exoplayer.controller.ControlWrapper;
22 import com.libs.video.video.exoplayer.controller.IControlComponent; 23 import com.libs.video.video.exoplayer.controller.IControlComponent;
23 import com.libs.video.video.exoplayer.play.CNVideoView; 24 import com.libs.video.video.exoplayer.play.CNVideoView;
@@ -234,6 +235,11 @@ public class DefaultVodControlView extends FrameLayout implements IControlCompon @@ -234,6 +235,11 @@ public class DefaultVodControlView extends FrameLayout implements IControlCompon
234 } 235 }
235 236
236 @Override 237 @Override
  238 + public void onPlayError(PlayErrorException exception) {
  239 +
  240 + }
  241 +
  242 + @Override
237 public void onClick(View v) { 243 public void onClick(View v) {
238 int id = v.getId(); 244 int id = v.getId();
239 if (id == R.id.fullscreen) { 245 if (id == R.id.fullscreen) {
cloud/video/src/main/java/com/libs/video/video/exoplayer/component/GestureView.java
@@ -15,6 +15,7 @@ import android.widget.TextView; @@ -15,6 +15,7 @@ import android.widget.TextView;
15 15
16 16
17 import com.cnlive.cloud.video.R; 17 import com.cnlive.cloud.video.R;
  18 +import com.libs.video.video.exoplayer.PlayErrorException;
18 import com.libs.video.video.exoplayer.controller.ControlWrapper; 19 import com.libs.video.video.exoplayer.controller.ControlWrapper;
19 import com.libs.video.video.exoplayer.controller.IGestureComponent; 20 import com.libs.video.video.exoplayer.controller.IGestureComponent;
20 import com.libs.video.video.exoplayer.play.CNVideoView; 21 import com.libs.video.video.exoplayer.play.CNVideoView;
@@ -158,4 +159,9 @@ public class GestureView extends FrameLayout implements IGestureComponent { @@ -158,4 +159,9 @@ public class GestureView extends FrameLayout implements IGestureComponent {
158 159
159 } 160 }
160 161
  162 + @Override
  163 + public void onPlayError(PlayErrorException exception) {
  164 +
  165 + }
  166 +
161 } 167 }
cloud/video/src/main/java/com/libs/video/video/exoplayer/component/LiveControlView.java
@@ -12,6 +12,7 @@ import android.widget.ImageView; @@ -12,6 +12,7 @@ import android.widget.ImageView;
12 import android.widget.LinearLayout; 12 import android.widget.LinearLayout;
13 13
14 import com.cnlive.cloud.video.R; 14 import com.cnlive.cloud.video.R;
  15 +import com.libs.video.video.exoplayer.PlayErrorException;
15 import com.libs.video.video.exoplayer.controller.ControlWrapper; 16 import com.libs.video.video.exoplayer.controller.ControlWrapper;
16 import com.libs.video.video.exoplayer.controller.IControlComponent; 17 import com.libs.video.video.exoplayer.controller.IControlComponent;
17 import com.libs.video.video.exoplayer.play.CNVideoView; 18 import com.libs.video.video.exoplayer.play.CNVideoView;
@@ -145,6 +146,11 @@ public class LiveControlView extends FrameLayout implements IControlComponent, V @@ -145,6 +146,11 @@ public class LiveControlView extends FrameLayout implements IControlComponent, V
145 } 146 }
146 147
147 @Override 148 @Override
  149 + public void onPlayError(PlayErrorException exception) {
  150 +
  151 + }
  152 +
  153 + @Override
148 public void onClick(View v) { 154 public void onClick(View v) {
149 int id = v.getId(); 155 int id = v.getId();
150 if (id == R.id.fullscreen) { 156 if (id == R.id.fullscreen) {
cloud/video/src/main/java/com/libs/video/video/exoplayer/controller/BaseVideoController.java
@@ -11,6 +11,8 @@ import android.view.animation.AlphaAnimation; @@ -11,6 +11,8 @@ import android.view.animation.AlphaAnimation;
11 import android.view.animation.Animation; 11 import android.view.animation.Animation;
12 import android.widget.FrameLayout; 12 import android.widget.FrameLayout;
13 13
  14 +import com.libs.video.video.exoplayer.PlayErrorException;
  15 +import com.libs.video.video.exoplayer.play.AbstractPlayer;
14 import com.libs.video.video.exoplayer.play.CNVideoView; 16 import com.libs.video.video.exoplayer.play.CNVideoView;
15 import com.libs.video.video.exoplayer.play.VideoViewManager; 17 import com.libs.video.video.exoplayer.play.VideoViewManager;
16 import com.libs.video.video.exoplayer.util.CutoutUtil; 18 import com.libs.video.video.exoplayer.util.CutoutUtil;
@@ -108,8 +110,9 @@ public abstract class BaseVideoController extends FrameLayout @@ -108,8 +110,9 @@ public abstract class BaseVideoController extends FrameLayout
108 * 重要:此方法用于将{@link CNVideoView} 和控制器绑定 110 * 重要:此方法用于将{@link CNVideoView} 和控制器绑定
109 */ 111 */
110 @CallSuper 112 @CallSuper
111 - public void setMediaPlayer(MediaPlayerControl mediaPlayer) { 113 + public void setMediaPlayer(MediaPlayerControl mediaPlayer,AbstractPlayer abstractPlayer) {
112 mControlWrapper = new ControlWrapper(mediaPlayer, this); 114 mControlWrapper = new ControlWrapper(mediaPlayer, this);
  115 + mControlWrapper.setAbstractPlayer(abstractPlayer);
113 //绑定ControlComponent和Controller 116 //绑定ControlComponent和Controller
114 for (Map.Entry<IControlComponent, Boolean> next : mControlComponents.entrySet()) { 117 for (Map.Entry<IControlComponent, Boolean> next : mControlComponents.entrySet()) {
115 IControlComponent component = next.getKey(); 118 IControlComponent component = next.getKey();
@@ -549,6 +552,15 @@ public abstract class BaseVideoController extends FrameLayout @@ -549,6 +552,15 @@ public abstract class BaseVideoController extends FrameLayout
549 onPlayStateChanged(playState); 552 onPlayStateChanged(playState);
550 } 553 }
551 554
  555 + @CallSuper
  556 + public void onPlayError(PlayErrorException exception){
  557 + for (Map.Entry<IControlComponent, Boolean> next
  558 + : mControlComponents.entrySet()) {
  559 + IControlComponent component = next.getKey();
  560 + component.onPlayError(exception);
  561 + }
  562 + }
  563 +
552 /** 564 /**
553 * 子类重写此方法并在其中更新控制器在不同播放状态下的ui 565 * 子类重写此方法并在其中更新控制器在不同播放状态下的ui
554 */ 566 */
@@ -645,5 +657,6 @@ public abstract class BaseVideoController extends FrameLayout @@ -645,5 +657,6 @@ public abstract class BaseVideoController extends FrameLayout
645 657
646 } 658 }
647 659
  660 +
648 //------------------------ end handle event change ------------------------// 661 //------------------------ end handle event change ------------------------//
649 } 662 }
cloud/video/src/main/java/com/libs/video/video/exoplayer/controller/ControlWrapper.java
@@ -6,6 +6,8 @@ import android.graphics.Bitmap; @@ -6,6 +6,8 @@ import android.graphics.Bitmap;
6 6
7 import androidx.annotation.NonNull; 7 import androidx.annotation.NonNull;
8 8
  9 +import com.libs.video.video.exoplayer.play.AbstractPlayer;
  10 +
9 /** 11 /**
10 * 此类的目的是为了在ControlComponent中既能调用VideoView的api又能调用BaseVideoController的api, 12 * 此类的目的是为了在ControlComponent中既能调用VideoView的api又能调用BaseVideoController的api,
11 * 并对部分api做了封装,方便使用 13 * 并对部分api做了封装,方便使用
@@ -14,12 +16,21 @@ public class ControlWrapper implements MediaPlayerControl, IVideoController { @@ -14,12 +16,21 @@ public class ControlWrapper implements MediaPlayerControl, IVideoController {
14 16
15 private MediaPlayerControl mPlayerControl; 17 private MediaPlayerControl mPlayerControl;
16 private IVideoController mController; 18 private IVideoController mController;
  19 + private AbstractPlayer abstractPlayer;//用于获取当前的播放器
17 20
18 public ControlWrapper(@NonNull MediaPlayerControl playerControl, @NonNull IVideoController controller) { 21 public ControlWrapper(@NonNull MediaPlayerControl playerControl, @NonNull IVideoController controller) {
19 mPlayerControl = playerControl; 22 mPlayerControl = playerControl;
20 mController = controller; 23 mController = controller;
21 } 24 }
22 25
  26 + public void setAbstractPlayer(AbstractPlayer abstractPlayer) {
  27 + this.abstractPlayer = abstractPlayer;
  28 + }
  29 +
  30 + public AbstractPlayer getAbstractPlayer() {
  31 + return abstractPlayer;
  32 + }
  33 +
23 @Override 34 @Override
24 public int getMediaCount() { 35 public int getMediaCount() {
25 return mPlayerControl.getMediaCount(); 36 return mPlayerControl.getMediaCount();
cloud/video/src/main/java/com/libs/video/video/exoplayer/controller/IControlComponent.java
@@ -5,6 +5,8 @@ import android.view.animation.Animation; @@ -5,6 +5,8 @@ import android.view.animation.Animation;
5 5
6 import androidx.annotation.NonNull; 6 import androidx.annotation.NonNull;
7 7
  8 +import com.libs.video.video.exoplayer.PlayErrorException;
  9 +
8 /** 10 /**
9 * 视频控制组件接口 11 * 视频控制组件接口
10 */ 12 */
@@ -41,6 +43,7 @@ public interface IControlComponent { @@ -41,6 +43,7 @@ public interface IControlComponent {
41 */ 43 */
42 void onPlayerStateChanged(int playerState); 44 void onPlayerStateChanged(int playerState);
43 45
  46 +
44 /** 47 /**
45 * 设置进度 48 * 设置进度
46 * 49 *
@@ -56,4 +59,10 @@ public interface IControlComponent { @@ -56,4 +59,10 @@ public interface IControlComponent {
56 */ 59 */
57 void onLockStateChanged(boolean isLocked); 60 void onLockStateChanged(boolean isLocked);
58 61
  62 + /**
  63 + * 播放出错
  64 + *
  65 + * @param exception
  66 + */
  67 + void onPlayError(PlayErrorException exception);
59 } 68 }
cloud/video/src/main/java/com/libs/video/video/exoplayer/controller/MediaPlayerControl.java
@@ -2,10 +2,13 @@ package com.libs.video.video.exoplayer.controller; @@ -2,10 +2,13 @@ package com.libs.video.video.exoplayer.controller;
2 2
3 import android.graphics.Bitmap; 3 import android.graphics.Bitmap;
4 4
  5 +import com.libs.video.video.exoplayer.play.AbstractPlayer;
  6 +
5 /** 7 /**
6 * 播放器控制接口 8 * 播放器控制接口
7 */ 9 */
8 public interface MediaPlayerControl { 10 public interface MediaPlayerControl {
  11 +
9 int getMediaCount(); 12 int getMediaCount();
10 13
11 void start(); 14 void start();
cloud/video/src/main/java/com/libs/video/video/exoplayer/controller/StandardVideoController.java
@@ -3,6 +3,7 @@ package com.libs.video.video.exoplayer.controller; @@ -3,6 +3,7 @@ package com.libs.video.video.exoplayer.controller;
3 import android.content.Context; 3 import android.content.Context;
4 import android.content.pm.ActivityInfo; 4 import android.content.pm.ActivityInfo;
5 import android.util.AttributeSet; 5 import android.util.AttributeSet;
  6 +import android.util.Log;
6 import android.view.View; 7 import android.view.View;
7 import android.view.ViewGroup; 8 import android.view.ViewGroup;
8 import android.view.animation.Animation; 9 import android.view.animation.Animation;
@@ -12,6 +13,7 @@ import android.widget.ProgressBar; @@ -12,6 +13,7 @@ import android.widget.ProgressBar;
12 import android.widget.Toast; 13 import android.widget.Toast;
13 14
14 import com.cnlive.cloud.video.R; 15 import com.cnlive.cloud.video.R;
  16 +import com.libs.video.video.exoplayer.PlayErrorException;
15 import com.libs.video.video.exoplayer.component.DefaultCompleteView; 17 import com.libs.video.video.exoplayer.component.DefaultCompleteView;
16 import com.libs.video.video.exoplayer.component.DefaultErrorView; 18 import com.libs.video.video.exoplayer.component.DefaultErrorView;
17 import com.libs.video.video.exoplayer.component.GestureView; 19 import com.libs.video.video.exoplayer.component.GestureView;
@@ -19,6 +21,7 @@ import com.libs.video.video.exoplayer.component.LiveControlView; @@ -19,6 +21,7 @@ import com.libs.video.video.exoplayer.component.LiveControlView;
19 import com.libs.video.video.exoplayer.component.DefaultPrepareView; 21 import com.libs.video.video.exoplayer.component.DefaultPrepareView;
20 import com.libs.video.video.exoplayer.component.DefaultTitleView; 22 import com.libs.video.video.exoplayer.component.DefaultTitleView;
21 import com.libs.video.video.exoplayer.component.DefaultVodControlView; 23 import com.libs.video.video.exoplayer.component.DefaultVodControlView;
  24 +import com.libs.video.video.exoplayer.play.AbstractPlayer;
22 import com.libs.video.video.exoplayer.play.CNVideoView; 25 import com.libs.video.video.exoplayer.play.CNVideoView;
23 import com.libs.video.video.exoplayer.util.PlayerUtils; 26 import com.libs.video.video.exoplayer.util.PlayerUtils;
24 27
@@ -30,7 +33,7 @@ import androidx.annotation.Nullable; @@ -30,7 +33,7 @@ import androidx.annotation.Nullable;
30 * 直播/点播控制器 33 * 直播/点播控制器
31 */ 34 */
32 35
33 -public class StandardVideoController extends GestureVideoController implements View.OnClickListener { 36 +public class StandardVideoController extends GestureVideoController implements View.OnClickListener, AbstractPlayer.PlayerEventListener {
34 37
35 protected ImageView mLockButton;//锁屏按钮 38 protected ImageView mLockButton;//锁屏按钮
36 39
@@ -61,6 +64,7 @@ public class StandardVideoController extends GestureVideoController implements V @@ -61,6 +64,7 @@ public class StandardVideoController extends GestureVideoController implements V
61 mLoadingProgress = findViewById(R.id.loading); 64 mLoadingProgress = findViewById(R.id.loading);
62 } 65 }
63 66
  67 +
64 /** 68 /**
65 * 快速添加各个组件 69 * 快速添加各个组件
66 * 70 *
@@ -199,4 +203,29 @@ public class StandardVideoController extends GestureVideoController implements V @@ -199,4 +203,29 @@ public class StandardVideoController extends GestureVideoController implements V
199 } 203 }
200 return super.onBackPressed(); 204 return super.onBackPressed();
201 } 205 }
  206 +
  207 + @Override
  208 + public void onError(PlayErrorException playErrorException) {
  209 + Log.e("测试", "onError: " );
  210 + }
  211 +
  212 + @Override
  213 + public void onCompletion() {
  214 +
  215 + }
  216 +
  217 + @Override
  218 + public void onInfo(int what, int extra) {
  219 +
  220 + }
  221 +
  222 + @Override
  223 + public void onPrepared() {
  224 +
  225 + }
  226 +
  227 + @Override
  228 + public void onVideoSizeChanged(int width, int height) {
  229 +
  230 + }
202 } 231 }
cloud/video/src/main/java/com/libs/video/video/exoplayer/play/AbstractPlayer.java
@@ -4,6 +4,8 @@ import android.content.res.AssetFileDescriptor; @@ -4,6 +4,8 @@ import android.content.res.AssetFileDescriptor;
4 import android.view.Surface; 4 import android.view.Surface;
5 import android.view.SurfaceHolder; 5 import android.view.SurfaceHolder;
6 6
  7 +import com.libs.video.video.exoplayer.PlayErrorException;
  8 +
7 import java.util.Map; 9 import java.util.Map;
8 10
9 /** 11 /**
@@ -155,7 +157,7 @@ public abstract class AbstractPlayer { @@ -155,7 +157,7 @@ public abstract class AbstractPlayer {
155 157
156 public interface PlayerEventListener { 158 public interface PlayerEventListener {
157 159
158 - void onError(); 160 + void onError(PlayErrorException playErrorException);
159 161
160 void onCompletion(); 162 void onCompletion();
161 163
cloud/video/src/main/java/com/libs/video/video/exoplayer/play/AndroidMediaPlayer.java
@@ -9,6 +9,9 @@ import android.os.Build; @@ -9,6 +9,9 @@ import android.os.Build;
9 import android.view.Surface; 9 import android.view.Surface;
10 import android.view.SurfaceHolder; 10 import android.view.SurfaceHolder;
11 11
  12 +import com.libs.video.video.exoplayer.PlayErrorException;
  13 +
  14 +import java.io.IOException;
12 import java.util.Map; 15 import java.util.Map;
13 16
14 public class AndroidMediaPlayer extends AbstractPlayer { 17 public class AndroidMediaPlayer extends AbstractPlayer {
@@ -40,7 +43,7 @@ public class AndroidMediaPlayer extends AbstractPlayer { @@ -40,7 +43,7 @@ public class AndroidMediaPlayer extends AbstractPlayer {
40 try { 43 try {
41 mMediaPlayer.setDataSource(mAppContext, Uri.parse(path), headers); 44 mMediaPlayer.setDataSource(mAppContext, Uri.parse(path), headers);
42 } catch (Exception e) { 45 } catch (Exception e) {
43 - mPlayerEventListener.onError(); 46 + getException(e);
44 } 47 }
45 } 48 }
46 49
@@ -49,16 +52,37 @@ public class AndroidMediaPlayer extends AbstractPlayer { @@ -49,16 +52,37 @@ public class AndroidMediaPlayer extends AbstractPlayer {
49 try { 52 try {
50 mMediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength()); 53 mMediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
51 } catch (Exception e) { 54 } catch (Exception e) {
52 - mPlayerEventListener.onError(); 55 + getException(e);
53 } 56 }
54 } 57 }
55 58
  59 + /**
  60 + * 获取当前异常
  61 + *
  62 + * @param e
  63 + */
  64 + private void getException(Exception e) {
  65 + PlayErrorException errorException = null;
  66 + if (e instanceof IOException) {
  67 + errorException = new PlayErrorException(PlayErrorException.TYPE_MediaPlayer_IOException, e.getMessage());
  68 + } else if (e instanceof IllegalArgumentException) {
  69 + errorException = new PlayErrorException(PlayErrorException.TYPE_MediaPlayer_IllegalArgumentException, e.getMessage());
  70 + } else if (e instanceof SecurityException) {
  71 + errorException = new PlayErrorException(PlayErrorException.TYPE_MediaPlayer_SecurityException, e.getMessage());
  72 + } else if (e instanceof IllegalStateException) {
  73 + errorException = new PlayErrorException(PlayErrorException.TYPE_MediaPlayer_IllegalStateException, e.getMessage());
  74 + } else {
  75 + errorException = new PlayErrorException(PlayErrorException.TYPE_MediaPlayer_unknownException, e.getMessage());
  76 + }
  77 + mPlayerEventListener.onError(errorException);
  78 + }
  79 +
56 @Override 80 @Override
57 public void start() { 81 public void start() {
58 try { 82 try {
59 mMediaPlayer.start(); 83 mMediaPlayer.start();
60 } catch (IllegalStateException e) { 84 } catch (IllegalStateException e) {
61 - mPlayerEventListener.onError(); 85 + getException(e);
62 } 86 }
63 } 87 }
64 88
@@ -67,7 +91,7 @@ public class AndroidMediaPlayer extends AbstractPlayer { @@ -67,7 +91,7 @@ public class AndroidMediaPlayer extends AbstractPlayer {
67 try { 91 try {
68 mMediaPlayer.pause(); 92 mMediaPlayer.pause();
69 } catch (IllegalStateException e) { 93 } catch (IllegalStateException e) {
70 - mPlayerEventListener.onError(); 94 + getException(e);
71 } 95 }
72 } 96 }
73 97
@@ -76,7 +100,7 @@ public class AndroidMediaPlayer extends AbstractPlayer { @@ -76,7 +100,7 @@ public class AndroidMediaPlayer extends AbstractPlayer {
76 try { 100 try {
77 mMediaPlayer.stop(); 101 mMediaPlayer.stop();
78 } catch (IllegalStateException e) { 102 } catch (IllegalStateException e) {
79 - mPlayerEventListener.onError(); 103 + getException(e);
80 } 104 }
81 } 105 }
82 106
@@ -86,7 +110,7 @@ public class AndroidMediaPlayer extends AbstractPlayer { @@ -86,7 +110,7 @@ public class AndroidMediaPlayer extends AbstractPlayer {
86 mIsPreparing = true; 110 mIsPreparing = true;
87 mMediaPlayer.prepareAsync(); 111 mMediaPlayer.prepareAsync();
88 } catch (IllegalStateException e) { 112 } catch (IllegalStateException e) {
89 - mPlayerEventListener.onError(); 113 + getException(e);
90 } 114 }
91 } 115 }
92 116
@@ -108,7 +132,8 @@ public class AndroidMediaPlayer extends AbstractPlayer { @@ -108,7 +132,8 @@ public class AndroidMediaPlayer extends AbstractPlayer {
108 try { 132 try {
109 mMediaPlayer.seekTo((int) time); 133 mMediaPlayer.seekTo((int) time);
110 } catch (IllegalStateException e) { 134 } catch (IllegalStateException e) {
111 - mPlayerEventListener.onError(); 135 + mPlayerEventListener.onError(new PlayErrorException(PlayErrorException.TYPE_MediaPlayer_IllegalStateException, e.getMessage()));
  136 +
112 } 137 }
113 } 138 }
114 139
@@ -152,7 +177,7 @@ public class AndroidMediaPlayer extends AbstractPlayer { @@ -152,7 +177,7 @@ public class AndroidMediaPlayer extends AbstractPlayer {
152 try { 177 try {
153 mMediaPlayer.setSurface(surface); 178 mMediaPlayer.setSurface(surface);
154 } catch (Exception e) { 179 } catch (Exception e) {
155 - mPlayerEventListener.onError(); 180 + getException(e);
156 } 181 }
157 } 182 }
158 183
@@ -161,7 +186,7 @@ public class AndroidMediaPlayer extends AbstractPlayer { @@ -161,7 +186,7 @@ public class AndroidMediaPlayer extends AbstractPlayer {
161 try { 186 try {
162 mMediaPlayer.setDisplay(holder); 187 mMediaPlayer.setDisplay(holder);
163 } catch (Exception e) { 188 } catch (Exception e) {
164 - mPlayerEventListener.onError(); 189 + getException(e);
165 } 190 }
166 } 191 }
167 192
@@ -186,7 +211,7 @@ public class AndroidMediaPlayer extends AbstractPlayer { @@ -186,7 +211,7 @@ public class AndroidMediaPlayer extends AbstractPlayer {
186 try { 211 try {
187 mMediaPlayer.setPlaybackParams(mMediaPlayer.getPlaybackParams().setSpeed(speed)); 212 mMediaPlayer.setPlaybackParams(mMediaPlayer.getPlaybackParams().setSpeed(speed));
188 } catch (Exception e) { 213 } catch (Exception e) {
189 - mPlayerEventListener.onError(); 214 + getException(e);
190 } 215 }
191 } 216 }
192 } 217 }
@@ -200,7 +225,12 @@ public class AndroidMediaPlayer extends AbstractPlayer { @@ -200,7 +225,12 @@ public class AndroidMediaPlayer extends AbstractPlayer {
200 private MediaPlayer.OnErrorListener onErrorListener = new MediaPlayer.OnErrorListener() { 225 private MediaPlayer.OnErrorListener onErrorListener = new MediaPlayer.OnErrorListener() {
201 @Override 226 @Override
202 public boolean onError(MediaPlayer mp, int what, int extra) { 227 public boolean onError(MediaPlayer mp, int what, int extra) {
203 - mPlayerEventListener.onError(); 228 + PlayErrorException errorException = new PlayErrorException();
  229 + errorException.setErrorType(PlayErrorException.TYPE_MediaPlayer_ON_ERROR);
  230 + errorException.setMediaPlayer(mp);
  231 + errorException.setMediaPlayer_what(what);
  232 + errorException.setMediaPlayer_extra(extra);
  233 + mPlayerEventListener.onError(errorException);
204 return true; 234 return true;
205 } 235 }
206 }; 236 };
cloud/video/src/main/java/com/libs/video/video/exoplayer/play/CNVideoView.java
@@ -19,6 +19,7 @@ import android.view.WindowManager; @@ -19,6 +19,7 @@ import android.view.WindowManager;
19 import android.widget.FrameLayout; 19 import android.widget.FrameLayout;
20 20
21 import com.cnlive.cloud.video.R; 21 import com.cnlive.cloud.video.R;
  22 +import com.libs.video.video.exoplayer.PlayErrorException;
22 import com.libs.video.video.exoplayer.controller.BaseVideoController; 23 import com.libs.video.video.exoplayer.controller.BaseVideoController;
23 import com.libs.video.video.exoplayer.controller.MediaPlayerControl; 24 import com.libs.video.video.exoplayer.controller.MediaPlayerControl;
24 import com.libs.video.video.exoplayer.util.L; 25 import com.libs.video.video.exoplayer.util.L;
@@ -157,6 +158,7 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout @@ -157,6 +158,7 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
157 a.recycle(); 158 a.recycle();
158 159
159 initView(); 160 initView();
  161 +
160 } 162 }
161 163
162 /** 164 /**
@@ -182,6 +184,7 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout @@ -182,6 +184,7 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
182 } 184 }
183 185
184 186
  187 +
185 /** 188 /**
186 * 当前媒体数量 189 * 当前媒体数量
187 * 190 *
@@ -231,8 +234,7 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout @@ -231,8 +234,7 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
231 if (mProgressManager != null) { 234 if (mProgressManager != null) {
232 mCurrentPosition = mProgressManager.getSavedProgress(mUrl); 235 mCurrentPosition = mProgressManager.getSavedProgress(mUrl);
233 } 236 }
234 - //初始化播放器  
235 - initPlayer(); 237 + initPlayer();
236 //添加渲染视图 238 //添加渲染视图
237 addDisplay(); 239 addDisplay();
238 startPrepare(false); 240 startPrepare(false);
@@ -267,7 +269,10 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout @@ -267,7 +269,10 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
267 * 初始化播放器 269 * 初始化播放器
268 */ 270 */
269 protected void initPlayer() { 271 protected void initPlayer() {
270 - mMediaPlayer = mPlayerFactory.createPlayer(getContext()); 272 + if (null==mMediaPlayer){
  273 + //初始化播放器
  274 + mMediaPlayer = mPlayerFactory.createPlayer(getContext());
  275 + }
271 mMediaPlayer.setPlayerEventListener(this); 276 mMediaPlayer.setPlayerEventListener(this);
272 setInitOptions(); 277 setInitOptions();
273 mMediaPlayer.initPlayer(); 278 mMediaPlayer.initPlayer();
@@ -553,8 +558,11 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout @@ -553,8 +558,11 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
553 * 视频播放出错回调 558 * 视频播放出错回调
554 */ 559 */
555 @Override 560 @Override
556 - public void onError() { 561 + public void onError(PlayErrorException playErrorException) {
557 mPlayerContainer.setKeepScreenOn(false); 562 mPlayerContainer.setKeepScreenOn(false);
  563 + if (mVideoController != null) {
  564 + mVideoController.onPlayError(playErrorException);
  565 + }
558 setPlayState(STATE_ERROR); 566 setPlayState(STATE_ERROR);
559 } 567 }
560 568
@@ -933,10 +941,14 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout @@ -933,10 +941,14 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
933 * 设置控制器,传null表示移除控制器 941 * 设置控制器,传null表示移除控制器
934 */ 942 */
935 public void setVideoController(@Nullable BaseVideoController mediaController) { 943 public void setVideoController(@Nullable BaseVideoController mediaController) {
  944 + if (null==mMediaPlayer){
  945 + //初始化播放器
  946 + mMediaPlayer = mPlayerFactory.createPlayer(getContext());
  947 + }
936 mPlayerContainer.removeView(mVideoController); 948 mPlayerContainer.removeView(mVideoController);
937 mVideoController = mediaController; 949 mVideoController = mediaController;
938 if (mediaController != null) { 950 if (mediaController != null) {
939 - mediaController.setMediaPlayer(this); 951 + mediaController.setMediaPlayer(this,mMediaPlayer);
940 LayoutParams params = new LayoutParams( 952 LayoutParams params = new LayoutParams(
941 ViewGroup.LayoutParams.MATCH_PARENT, 953 ViewGroup.LayoutParams.MATCH_PARENT,
942 ViewGroup.LayoutParams.MATCH_PARENT); 954 ViewGroup.LayoutParams.MATCH_PARENT);
cloud/video/src/main/java/com/libs/video/video/exoplayer/playerCore/exoplayer/ExoMediaPlayer.java
@@ -6,6 +6,8 @@ import android.os.Handler; @@ -6,6 +6,8 @@ import android.os.Handler;
6 import android.view.Surface; 6 import android.view.Surface;
7 import android.view.SurfaceHolder; 7 import android.view.SurfaceHolder;
8 8
  9 +import com.cnlive.cloud.video.R;
  10 +import com.cnlive.core.libs.base.util.NetworkUtil;
9 import com.google.android.exoplayer2.DefaultLoadControl; 11 import com.google.android.exoplayer2.DefaultLoadControl;
10 import com.google.android.exoplayer2.DefaultRenderersFactory; 12 import com.google.android.exoplayer2.DefaultRenderersFactory;
11 import com.google.android.exoplayer2.ExoPlaybackException; 13 import com.google.android.exoplayer2.ExoPlaybackException;
@@ -26,6 +28,7 @@ import com.google.android.exoplayer2.util.Clock; @@ -26,6 +28,7 @@ import com.google.android.exoplayer2.util.Clock;
26 import com.google.android.exoplayer2.util.EventLogger; 28 import com.google.android.exoplayer2.util.EventLogger;
27 import com.google.android.exoplayer2.util.Util; 29 import com.google.android.exoplayer2.util.Util;
28 import com.google.android.exoplayer2.video.VideoListener; 30 import com.google.android.exoplayer2.video.VideoListener;
  31 +import com.libs.video.video.exoplayer.PlayErrorException;
29 import com.libs.video.video.exoplayer.play.AbstractPlayer; 32 import com.libs.video.video.exoplayer.play.AbstractPlayer;
30 import com.libs.video.video.exoplayer.play.VideoViewManager; 33 import com.libs.video.video.exoplayer.play.VideoViewManager;
31 34
@@ -221,7 +224,9 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla @@ -221,7 +224,9 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
221 mSpeedPlaybackParameters = null; 224 mSpeedPlaybackParameters = null;
222 } 225 }
223 226
224 - /**获取当前的播放进度 227 + /**
  228 + * 获取当前的播放进度
  229 + *
225 * @return 230 * @return
226 */ 231 */
227 @Override 232 @Override
@@ -371,12 +376,39 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla @@ -371,12 +376,39 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
371 */ 376 */
372 @Override 377 @Override
373 public void onPlayerError(ExoPlaybackException error) { 378 public void onPlayerError(ExoPlaybackException error) {
374 - if (mPlayerEventListener != null) {  
375 - mPlayerEventListener.onError(); 379 + if (mPlayerEventListener != null && null != mAppContext) {
  380 + PlayErrorException errorException = null;
  381 + switch (error.type) {
  382 + //资源异常
  383 + case ExoPlaybackException.TYPE_SOURCE:
  384 + //先判断是否有网络连接
  385 + if (!NetworkUtil.isConnectInternet(mAppContext)) {
  386 + errorException = new PlayErrorException(PlayErrorException.TYPE_NETWORK_ERROR, mAppContext.getResources().getString(R.string.cnvideo_no_network));
  387 + } else {
  388 + errorException = new PlayErrorException(PlayErrorException.TYPE_SOURCE_ERROR, mAppContext.getResources().getString(R.string.cnvideo_load_source_error));
  389 + }
  390 + break;
  391 + //内存溢出
  392 + case ExoPlaybackException.TYPE_OUT_OF_MEMORY:
  393 + errorException = new PlayErrorException(PlayErrorException.TYPE_OUT_OF_MEMORY, error.getMessage());
  394 + break;
  395 + case ExoPlaybackException.TYPE_UNEXPECTED:
  396 + errorException = new PlayErrorException(PlayErrorException.TYPE_UNEXPECTED_ERROR, error.getMessage());
  397 + break;
  398 +
  399 + case ExoPlaybackException.TYPE_RENDERER:
  400 + errorException = new PlayErrorException(PlayErrorException.TYPE_RENDERER_ERROR, error.getMessage());
  401 + break;
  402 + }
  403 + if (null != errorException) {
  404 + mPlayerEventListener.onError(errorException);
  405 + }
376 } 406 }
377 } 407 }
378 408
379 - /**视频大小发生变化 409 + /**
  410 + * 视频大小发生变化
  411 + *
380 * @param width 412 * @param width
381 * @param height 413 * @param height
382 * @param unappliedRotationDegrees 414 * @param unappliedRotationDegrees
cloud/video/src/main/res/drawable/cnvideo_shape_status_view_btn.xml
1 <?xml version="1.0" encoding="utf-8"?> 1 <?xml version="1.0" encoding="utf-8"?>
2 <shape xmlns:android="http://schemas.android.com/apk/res/android"> 2 <shape xmlns:android="http://schemas.android.com/apk/res/android">
3 - <solid android:color="@color/cnvideo_theme_color"/> 3 + <solid android:color="@color/cnvideo_color_btn_error"/>
4 <corners android:radius="30dp"/> 4 <corners android:radius="30dp"/>
5 </shape> 5 </shape>
6 \ No newline at end of file 6 \ No newline at end of file
cloud/video/src/main/res/layout/cnvideo_layout_error_view.xml
@@ -11,17 +11,18 @@ @@ -11,17 +11,18 @@
11 android:orientation="vertical"> 11 android:orientation="vertical">
12 12
13 <TextView 13 <TextView
14 - android:id="@+id/message" 14 + android:id="@+id/tv_message"
15 android:layout_width="wrap_content" 15 android:layout_width="wrap_content"
16 android:layout_height="wrap_content" 16 android:layout_height="wrap_content"
17 android:gravity="center" 17 android:gravity="center"
18 android:text="@string/cnvideo_error_message" 18 android:text="@string/cnvideo_error_message"
19 - android:textColor="@android:color/white" /> 19 + android:textColor="@android:color/white"
  20 + android:textSize="16sp" />
20 21
21 - <TextView  
22 - android:id="@+id/status_btn" 22 + <Button
  23 + android:id="@+id/btn_retry"
23 android:layout_width="wrap_content" 24 android:layout_width="wrap_content"
24 - android:layout_height="wrap_content" 25 + android:layout_height="30dp"
25 android:layout_marginTop="16dp" 26 android:layout_marginTop="16dp"
26 android:background="@drawable/cnvideo_shape_status_view_btn" 27 android:background="@drawable/cnvideo_shape_status_view_btn"
27 android:gravity="center" 28 android:gravity="center"
@@ -30,7 +31,8 @@ @@ -30,7 +31,8 @@
30 android:paddingRight="18dp" 31 android:paddingRight="18dp"
31 android:paddingBottom="4dp" 32 android:paddingBottom="4dp"
32 android:text="@string/cnvideo_retry" 33 android:text="@string/cnvideo_retry"
33 - android:textColor="@android:color/white" /> 34 + android:textColor="@android:color/white"
  35 + android:textSize="15sp" />
34 36
35 </LinearLayout> 37 </LinearLayout>
36 </FrameLayout> 38 </FrameLayout>
37 \ No newline at end of file 39 \ No newline at end of file