diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 6f4c447c6..1a522d0c3 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -292,3 +292,5 @@ rx.internal.util.atomic.LinkedQueueNode* consumerNode; -keep class com.shayu.lib_google.**{*;} -keep class com.shayu.lib_huawei.**{*;} + +-keep class io.agora.**{*;} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ded4c2c0f..8d8a3325c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -89,6 +89,11 @@ + + + + + diff --git a/common/build.gradle b/common/build.gradle index d59049c32..b69c7b668 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -225,6 +225,7 @@ dependencies { api 'com.github.FlyJingFish:GradientTextView:1.2.4' //轮播 一屏显示多个 api 'com.github.xiaohaibin:XBanner:androidx_v1.2.6' - + //声网SDK + api 'io.agora.rtc:agora-special-full:4.1.1.28' } diff --git a/common/src/main/java/com/yunbao/common/CommonAppConfig.java b/common/src/main/java/com/yunbao/common/CommonAppConfig.java index 6b1a7119d..2f447a77e 100644 --- a/common/src/main/java/com/yunbao/common/CommonAppConfig.java +++ b/common/src/main/java/com/yunbao/common/CommonAppConfig.java @@ -77,7 +77,6 @@ public class CommonAppConfig { public static int alert_time = 1; public static int alert_end_time = 1; - private CommonAppConfig() { } diff --git a/common/src/main/java/com/yunbao/common/manager/SWAuManager.java b/common/src/main/java/com/yunbao/common/manager/SWAuManager.java new file mode 100644 index 000000000..7a3b9741e --- /dev/null +++ b/common/src/main/java/com/yunbao/common/manager/SWAuManager.java @@ -0,0 +1,147 @@ +package com.yunbao.common.manager; + +import android.app.Activity; +import android.content.Context; +import android.view.SurfaceView; +import android.widget.FrameLayout; + +import com.yunbao.common.CommonAppContext; +import com.yunbao.common.manager.base.BaseCacheManager; +import com.yunbao.common.utils.StringUtil; + +import io.agora.rtc2.ChannelMediaOptions; +import io.agora.rtc2.Constants; +import io.agora.rtc2.IRtcEngineEventHandler; +import io.agora.rtc2.RtcEngine; +import io.agora.rtc2.RtcEngineConfig; +import io.agora.rtc2.video.VideoCanvas; + +/** + * 声网主播管理类 + */ +public class SWAuManager extends BaseCacheManager { + + // 填写项目的 App ID,可在声网控制台中生成 + public static final String shengwang_appId = "4cf0376582d742ac8a96778b25b1079e"; + // 填写频道名 + public static final String shengwang_channelName = "12"; + // 填写声网控制台中生成的临时 Token + public static final String shengwang_token = "007eJxSYJi477Xju22xV7ov7GfzzOnbtCU0IuK9+YuwWf2uLPGnl8xRYDBJTjMwNjcztTBKMTcxSky2SLQ0Mze3SDIyTTI0MLdMPWQrltYQyMjw/4kCCyMDBIL4TAyGRiwMlpaWloAAAAD//w/TIFY="; + private Activity mContext; + public static SWAuManager manager; + private RtcEngine mRtcEngine; + private FrameLayout audienceContainer; //主播视图 + private FrameLayout pkContainer1; //pk主播视图1 + private FrameLayout pkContainer2; //pk主播视图2 + private FrameLayout pkContainer3; //pk主播视图3 + private FrameLayout linkUserContainer;//连麦用户视图 + + public SWAuManager(Context context) { + super(context); + } + + /** + * 获取单列 + * + * @return + */ + public static SWAuManager get() { + if (null == manager) { + manager = new SWAuManager(CommonAppContext.sInstance.getBaseContext()); + } + return manager; + } + + /** + * 初始化声网SDK + */ + public void initRtcEngine(Activity mContext) { + this.mContext = mContext; + try { + // 创建 RtcEngineConfig 对象,并进行配置 + RtcEngineConfig config = new RtcEngineConfig(); + config.mContext = mContext; + config.mAppId = SWAuManager.shengwang_appId; + config.mEventHandler = mRtcEventHandler; + // 创建并初始化 RtcEngine + mRtcEngine = RtcEngine.create(config); + } catch (Exception e) { + throw new RuntimeException("Check the error."); + } + mRtcEngine.setChannelProfile(Constants.CHANNEL_PROFILE_LIVE_BROADCASTING); // 直播模式,引擎級別 + // 启用视频模块 + mRtcEngine.enableVideo(); + // 开启本地预览 + //mRtcEngine.startPreview(); + } + + /** + * guanzhong + * 加入房间 + */ + public void joinRoom(String strUid, String token, String channelName) { + int uid; + if (StringUtil.isEmpty(strUid)) { + uid = 0; + } else { + uid = Integer.parseInt(strUid); + } + // 创建一个 SurfaceView 对象,并将其作为 FrameLayout 的子对象 + SurfaceView surfaceView = new SurfaceView(mContext); + audienceContainer.addView(surfaceView); + + // 创建 ChannelMediaOptions 对象,并进行配置 + ChannelMediaOptions options = new ChannelMediaOptions(); + // 根据场景将用户角色设置为 AUDIENCE (观众) + options.clientRoleType = Constants.CLIENT_ROLE_AUDIENCE; + // 直播场景下,设置频道场景为 BROADCASTING (直播场景) + options.audienceLatencyLevel = Constants.AUDIENCE_LATENCY_LEVEL_LOW_LATENCY; // 觀眾走極速直播 + + // 使用临时 Token 加入频道,自行指定用户 ID 并确保其在频道内的唯一性 + mRtcEngine.joinChannel(token, channelName, uid, options); + } + + //远程监听 + private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() { + @Override + // 监听频道内的远端用户,获取用户的 uid 信息 + public void onUserJoined(int uid, int elapsed) { + mContext.runOnUiThread(new Runnable() { + @Override + public void run() { + // 获取 uid 后,设置远端视频视图 + setupRemoteVideo(uid); + } + }); + } + }; + + //设置对方主播视图 + public void setupRemoteVideo(int uid) { + SurfaceView surfaceView = new SurfaceView(mContext); + surfaceView.setZOrderMediaOverlay(true); + audienceContainer.addView(surfaceView); + // 将 SurfaceView 对象传入声网实时互动 SDK,设置远端视图 + mRtcEngine.setupRemoteVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_HIDDEN, uid)); + } + + public void setAudienceContainer(FrameLayout audienceContainer) { + this.audienceContainer = audienceContainer; + } + + public void setPkContainer1(FrameLayout pkContainer1) { + this.pkContainer1 = pkContainer1; + } + + public void setPkContainer2(FrameLayout pkContainer2) { + this.pkContainer2 = pkContainer2; + } + + public void setPkContainer3(FrameLayout pkContainer3) { + this.pkContainer3 = pkContainer3; + } + + public void setLinkUserContainer(FrameLayout linkUserContainer) { + this.linkUserContainer = linkUserContainer; + } +} diff --git a/common/src/main/java/com/yunbao/common/manager/SWManager.java b/common/src/main/java/com/yunbao/common/manager/SWManager.java new file mode 100644 index 000000000..a97d85b9b --- /dev/null +++ b/common/src/main/java/com/yunbao/common/manager/SWManager.java @@ -0,0 +1,207 @@ +package com.yunbao.common.manager; + +import android.app.Activity; +import android.content.Context; +import android.view.SurfaceView; +import android.widget.FrameLayout; + +import com.yunbao.common.CommonAppContext; +import com.yunbao.common.manager.base.BaseCacheManager; +import com.yunbao.common.utils.StringUtil; +import com.yunbao.common.utils.ToastUtil; + +import cn.rongcloud.rtc.base.RCRTCParamsType; +import io.agora.rtc2.ChannelMediaOptions; +import io.agora.rtc2.Constants; +import io.agora.rtc2.IRtcEngineEventHandler; +import io.agora.rtc2.RtcEngine; +import io.agora.rtc2.RtcEngineConfig; +import io.agora.rtc2.video.VideoCanvas; +import io.agora.rtc2.video.VideoEncoderConfiguration; + +/** + * 声网主播管理类 + */ +public class SWManager extends BaseCacheManager { + + // 填写项目的 App ID,可在声网控制台中生成 + public static final String shengwang_appId = "4cf0376582d742ac8a96778b25b1079e"; + // 填写频道名 + public static final String shengwang_channelName = "12"; + // 填写声网控制台中生成的临时 Token + public static final String shengwang_token = "007eJxTYOD6Iv3buTHm6666BKY1Cr7mUZU3tY0eHH5qbF4jv5nNukqBwSQ5zcDY3MzUwijF3MQoMdki0dLM3Nwiycg0ydDA3DL1xX/RtIZARgb+3ExWRgYIBPGZGAyNGBgAhDMb8Q=="; + private Activity mContext; + public static SWManager manager; + private RtcEngine mRtcEngine; + private int uid; + VideoEncoderConfiguration cfg; + private FrameLayout anchorContainer; //主播视图 + private FrameLayout pkContainer1; //pk主播视图1 + private FrameLayout pkContainer2; //pk主播视图2 + private FrameLayout pkContainer3; //pk主播视图3 + private FrameLayout linkUserContainer;//连麦用户视图 + private onRtcEngineListener onRtcEngineListener; + + public void setOnRtcEngineListener(SWManager.onRtcEngineListener onRtcEngineListener) { + this.onRtcEngineListener = onRtcEngineListener; + } + + public SWManager(Context context) { + super(context); + } + + /** + * 获取单列 + * + * @return + */ + public static SWManager get() { + if (null == manager) { + manager = new SWManager(CommonAppContext.sInstance.getBaseContext()); + } + return manager; + } + + /** + * 初始化声网SDK + */ + public void initRtcEngine(Activity mContext, String strUid) { + this.mContext = mContext; + if (StringUtil.isEmpty(strUid)) { + uid = 0; + } else { + uid = Integer.parseInt(strUid); + } + try { + // 创建 RtcEngineConfig 对象,并进行配置 + RtcEngineConfig config = new RtcEngineConfig(); + config.mContext = mContext; + config.mAppId = SWManager.shengwang_appId; + config.mEventHandler = mRtcEventHandler; + // 创建并初始化 RtcEngine + mRtcEngine = RtcEngine.create(config); + } catch (Exception e) { + throw new RuntimeException("Check the error."); + } + mRtcEngine.setChannelProfile(Constants.CHANNEL_PROFILE_LIVE_BROADCASTING); + // 启用视频模块 + mRtcEngine.enableVideo(); + // 开启本地预览 + mRtcEngine.startPreview(); + + cfg = new VideoEncoderConfiguration(); + //设置默认分辨率 + switch (IMLoginManager.get(mContext).getSelectClarity()) { + case 0: + cfg.dimensions = VideoEncoderConfiguration.VD_840x480; + break; + case 1: + cfg.dimensions = VideoEncoderConfiguration.VD_1280x720; + break; + case 2: + cfg.dimensions = VideoEncoderConfiguration.VD_1920x1080; + break; + } + cfg.frameRate = 24; + cfg.bitrate = 0; + cfg.mirrorMode = VideoEncoderConfiguration.MIRROR_MODE_TYPE.MIRROR_MODE_ENABLED; //镜像 + mRtcEngine.setVideoEncoderConfiguration(cfg); + + // 创建一个 SurfaceView 对象,并将其作为 FrameLayout 的子对象 + SurfaceView surfaceView = new SurfaceView(mContext); + anchorContainer.addView(surfaceView); + // 设置视图 + mRtcEngine.setupLocalVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_HIDDEN, uid)); + } + + public void setDimensions(int selectClarity) { + if (cfg != null && mRtcEngine != null) { + switch (selectClarity) { + case 0: + cfg.dimensions = VideoEncoderConfiguration.VD_840x480; + break; + case 1: + cfg.dimensions = VideoEncoderConfiguration.VD_1280x720; + break; + case 2: + cfg.dimensions = VideoEncoderConfiguration.VD_1920x1080; + break; + } + mRtcEngine.setVideoEncoderConfiguration(cfg); + } + } + + + /** + * 创建房间 + */ + public void createRoom(String token, String channelName) { + ChannelMediaOptions options = new ChannelMediaOptions(); + // 设置角色 BROADCASTER (主播) 或 AUDIENCE (观众) + options.clientRoleType = Constants.CLIENT_ROLE_BROADCASTER; + // 加入频道 + mRtcEngine.joinChannel(token, channelName, uid, options); + } + + //远程监听 + private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() { + @Override + // 监听频道内的远端用户,获取用户的 uid 信息 + public void onUserJoined(int uid, int elapsed) { + mContext.runOnUiThread(new Runnable() { + @Override + public void run() { + // 获取 uid 后,设置远端视频视图 + setupRemoteVideo(uid); + } + }); + } + + @Override + public void onJoinChannelSuccess(String channel, int uid, int elapsed) { + super.onJoinChannelSuccess(channel, uid, elapsed); + if (onRtcEngineListener != null) { + onRtcEngineListener.onOpenSuccess(channel, uid); + } + } + + @Override + public void onError(int err) { + super.onError(err); + ToastUtil.show("onError:" + err); + } + }; + + //设置对方主播视图 + private void setupRemoteVideo(int uid) { + SurfaceView surfaceView = new SurfaceView(mContext); + surfaceView.setZOrderMediaOverlay(true); + pkContainer1.addView(surfaceView); + // 将 SurfaceView 对象传入声网实时互动 SDK,设置远端视图 + mRtcEngine.setupRemoteVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_FIT, uid)); + } + + public void setAnchorContainer(FrameLayout anchorContainer) { + this.anchorContainer = anchorContainer; + } + + public interface onRtcEngineListener { + void onOpenSuccess(String channel, int uid); + } + + public void setPkContainer1(FrameLayout pkContainer1) { + this.pkContainer1 = pkContainer1; + } + + public void setPkContainer2(FrameLayout pkContainer2) { + this.pkContainer2 = pkContainer2; + } + + public void setPkContainer3(FrameLayout pkContainer3) { + this.pkContainer3 = pkContainer3; + } + + public void setLinkUserContainer(FrameLayout linkUserContainer) { + this.linkUserContainer = linkUserContainer; + } +} diff --git a/live/src/main/AndroidManifest.xml b/live/src/main/AndroidManifest.xml index 1af89a691..6c664cb33 100644 --- a/live/src/main/AndroidManifest.xml +++ b/live/src/main/AndroidManifest.xml @@ -124,6 +124,10 @@ + + \ No newline at end of file diff --git a/live/src/main/java/com/yunbao/live/activity/NewLiveActivity.java b/live/src/main/java/com/yunbao/live/activity/NewLiveActivity.java new file mode 100644 index 000000000..6dfb2bbf5 --- /dev/null +++ b/live/src/main/java/com/yunbao/live/activity/NewLiveActivity.java @@ -0,0 +1,139 @@ +package com.yunbao.live.activity; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import android.Manifest; +import android.content.pm.PackageManager; +import android.view.SurfaceView; +import android.widget.FrameLayout; + +import android.os.Bundle; + +import com.yunbao.common.manager.SWManager; +import com.yunbao.live.R; + +import io.agora.rtc2.ChannelMediaOptions; +import io.agora.rtc2.Constants; +import io.agora.rtc2.IRtcEngineEventHandler; +import io.agora.rtc2.RtcEngine; +import io.agora.rtc2.RtcEngineConfig; +import io.agora.rtc2.video.VideoCanvas; + + +public class NewLiveActivity extends AppCompatActivity { + private RtcEngine mRtcEngine; + + private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() { + @Override + // 监听频道内的远端用户,获取用户的 uid 信息 + public void onUserJoined(int uid, int elapsed) { + runOnUiThread(new Runnable() { + @Override + public void run() { + // 获取 uid 后,设置远端视频视图 + setupRemoteVideo(uid); + } + }); + } + }; + + private void initializeAndJoinChannel() { + try { + // 创建 RtcEngineConfig 对象,并进行配置 + RtcEngineConfig config = new RtcEngineConfig(); + config.mContext = getBaseContext(); + config.mAppId = SWManager.shengwang_appId; + config.mEventHandler = mRtcEventHandler; + // 创建并初始化 RtcEngine + mRtcEngine = RtcEngine.create(config); + } catch (Exception e) { + throw new RuntimeException("Check the error."); + } + // 启用视频模块 + mRtcEngine.enableVideo(); + // 开启本地预览 + mRtcEngine.startPreview(); + + // 创建一个 SurfaceView 对象,并将其作为 FrameLayout 的子对象 + FrameLayout container = findViewById(R.id.local_video_view_container); + SurfaceView surfaceView = new SurfaceView(getBaseContext()); + container.addView(surfaceView); + // 将 SurfaceView 对象传入声网实时互动 SDK,设置本地视图 + mRtcEngine.setupLocalVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_FIT, 0)); + + // 创建 ChannelMediaOptions 对象,并进行配置 + ChannelMediaOptions options = new ChannelMediaOptions(); + // 根据场景将用户角色设置为 BROADCASTER (主播) 或 AUDIENCE (观众) + options.clientRoleType = Constants.CLIENT_ROLE_BROADCASTER; + // 直播场景下,设置频道场景为 BROADCASTING (直播场景) + options.channelProfile = Constants.CHANNEL_PROFILE_LIVE_BROADCASTING; + + // 使用临时 Token 加入频道,自行指定用户 ID 并确保其在频道内的唯一性 + mRtcEngine.joinChannel(SWManager.shengwang_token, SWManager.shengwang_channelName, 0, options); + } + + private void setupRemoteVideo(int uid) { + FrameLayout container = findViewById(R.id.remote_video_view_container); + SurfaceView surfaceView = new SurfaceView(getBaseContext()); + surfaceView.setZOrderMediaOverlay(true); + container.addView(surfaceView); + // 将 SurfaceView 对象传入声网实时互动 SDK,设置远端视图 + mRtcEngine.setupRemoteVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_FIT, uid)); + } + + private static final int PERMISSION_REQ_ID = 22; + + // 获取体验实时音视频互动所需的录音、摄像头等权限 + private String[] getRequiredPermissions() { + // 判断 targetSDKVersion 31 及以上时所需的权限 + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { + return new String[]{ + Manifest.permission.RECORD_AUDIO, // 录音权限 + Manifest.permission.CAMERA, // 摄像头权限 + Manifest.permission.READ_PHONE_STATE, // 读取电话状态权限 + Manifest.permission.BLUETOOTH_CONNECT // 蓝牙连接权限 + }; + } else { + return new String[]{ + Manifest.permission.RECORD_AUDIO, + Manifest.permission.CAMERA + }; + } + } + + private boolean checkPermissions() { + for (String permission : getRequiredPermissions()) { + int permissionCheck = ContextCompat.checkSelfPermission(this, permission); + if (permissionCheck != PackageManager.PERMISSION_GRANTED) { + return false; + } + } + return true; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.acticity_new_live); + // 如果已经授权,则初始化 RtcEngine 并加入频道 + initializeAndJoinChannel(); + if (checkPermissions()) { + initializeAndJoinChannel(); + } else { + ActivityCompat.requestPermissions(this, getRequiredPermissions(), PERMISSION_REQ_ID); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + // 停止本地视频预览 + mRtcEngine.stopPreview(); + + // 离开频道 + mRtcEngine.leaveChannel(); + } +} diff --git a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java index c40b07bf1..5863c3b91 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java @@ -44,6 +44,7 @@ import com.yunbao.common.interfaces.CommonCallback; import com.yunbao.common.interfaces.ImageResultCallback; import com.yunbao.common.interfaces.OnItemClickListener; import com.yunbao.common.manager.IMLoginManager; +import com.yunbao.common.manager.SWManager; import com.yunbao.common.utils.Bus; import com.yunbao.common.utils.DialogUitl; import com.yunbao.common.utils.L; @@ -327,7 +328,10 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl if (liveOpenCustomPopup != null) { liveOpenCustomPopup.setSelectClarity(selectClarity); } - //設置開播分辨率 + SWManager.get().setDimensions(selectClarity); + + + /*//設置開播分辨率 RCRTCParamsType.RCRTCVideoResolution rcrtcVideoResolution = RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_480_848; int minRate = 200; int maxRate = 900; @@ -355,7 +359,7 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl .setVideoFps(RCRTCParamsType.RCRTCVideoFps.Fps_15) .setVideoResolution(rcrtcVideoResolution) .build(); - RCRTCEngine.getInstance().getDefaultVideoStream().setVideoConfig(config); + RCRTCEngine.getInstance().getDefaultVideoStream().setVideoConfig(config);*/ Log.e("切换分辨率", "时间戳" + System.currentTimeMillis()); //重新发布一下流 Bus.get().post(new LivePushRyEvent()); diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 126ec891c..5c4b48ab3 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -3,6 +3,7 @@ package com.yunbao.live.views; import static com.lzy.okgo.utils.HttpUtils.runOnUiThread; import android.Manifest; +import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.graphics.Color; @@ -36,6 +37,7 @@ import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; import com.yunbao.common.interfaces.OnItemClickListener; import com.yunbao.common.manager.IMLoginManager; +import com.yunbao.common.manager.SWAuManager; import com.yunbao.common.utils.Bus; import com.yunbao.common.utils.DialogUitl; import com.yunbao.common.utils.DpUtil; @@ -97,6 +99,8 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { private RelativeLayout mPkContainer; public StyledPlayerView mVideoView; + private FrameLayout playFrameLayout; + private View mLoading, mLoading2; private ImageView mCover; private boolean mPaused;//是否切后台了 @@ -122,6 +126,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { //0未申请1申请中2连麦中 RCRTCRoom rcrtcRoom; String purl, srcUrl; + SWAuManager swAuManager; public int getLandscape() { return landscape; @@ -146,6 +151,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { EventBus.getDefault().register(this); Bus.getOn(this); mRoot = (ViewGroup) findViewById(R.id.root); + playFrameLayout = (FrameLayout) findViewById(R.id.playView); mSmallContainer = (ViewGroup) findViewById(R.id.small_container); mLeftContainer = (ViewGroup) findViewById(R.id.left_container); mRightContainer = (ViewGroup) findViewById(R.id.right_container); @@ -167,6 +173,13 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { mPlayer = new LiveExoPlayerManager(mContext); mPlayer.setMainView(mVideoView); mPlayer.setListener(new ExoPlayerListener()); + + swAuManager = SWAuManager.get(); + swAuManager.setAudienceContainer(playFrameLayout); + swAuManager.initRtcEngine((Activity) mContext); + swAuManager.setupRemoteVideo(11); + swAuManager.joinRoom("9999", SWAuManager.shengwang_token, SWAuManager.shengwang_channelName); + debugView = new TextView(mContext); debugView.setBackgroundColor(Color.WHITE); diff --git a/live/src/main/java/com/yunbao/live/views/LivePlaySwViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlaySwViewHolder.java new file mode 100644 index 000000000..f421d920f --- /dev/null +++ b/live/src/main/java/com/yunbao/live/views/LivePlaySwViewHolder.java @@ -0,0 +1,1374 @@ +package com.yunbao.live.views; + +import static com.lzy.okgo.utils.HttpUtils.runOnUiThread; + +import android.Manifest; +import android.app.Dialog; +import android.content.Context; +import android.graphics.Color; +import android.media.AudioManager; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import android.text.TextUtils; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.google.android.exoplayer2.PlaybackException; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.ui.StyledPlayerView; +import com.google.android.exoplayer2.video.VideoSize; +import com.lxj.xpopup.XPopup; +import com.lxj.xpopup.core.BasePopupView; +import com.lxj.xpopup.interfaces.XPopupCallback; +import com.lzf.easyfloat.EasyFloat; +import com.lzy.okserver.OkDownload; +import com.yunbao.common.bean.EnterRoomNewModel; +import com.yunbao.common.dialog.LiveFontSizeSettingDialog; +import com.yunbao.common.http.HttpCallback; +import com.yunbao.common.http.HttpClient; +import com.yunbao.common.interfaces.OnItemClickListener; +import com.yunbao.common.manager.IMLoginManager; +import com.yunbao.common.utils.Bus; +import com.yunbao.common.utils.DialogUitl; +import com.yunbao.common.utils.DpUtil; +import com.yunbao.common.utils.L; +import com.yunbao.common.utils.MicStatusManager; +import com.yunbao.common.utils.ScreenDimenUtil; +import com.yunbao.common.utils.SpUtil; +import com.yunbao.common.utils.ToastUtil; +import com.yunbao.common.utils.WordUtil; +import com.yunbao.common.views.LiveClarityCustomPopup; +import com.yunbao.live.R; +import com.yunbao.live.activity.LiveActivity; +import com.yunbao.live.activity.LiveAudienceActivity; +import com.yunbao.live.event.LiveAudienceEvent; +import com.yunbao.live.utils.LiveExoPlayerManager; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import cn.rongcloud.rtc.api.RCRTCEngine; +import cn.rongcloud.rtc.api.RCRTCRemoteUser; +import cn.rongcloud.rtc.api.RCRTCRoom; +import cn.rongcloud.rtc.api.RCRTCRoomConfig; +import cn.rongcloud.rtc.api.callback.IRCRTCResultCallback; +import cn.rongcloud.rtc.api.callback.IRCRTCResultDataCallback; +import cn.rongcloud.rtc.api.callback.IRCRTCRoomEventsListener; +import cn.rongcloud.rtc.api.callback.IRCRTCSwitchRoleCallback; +import cn.rongcloud.rtc.api.callback.IRCRTCSwitchRoleDataCallback; +import cn.rongcloud.rtc.api.callback.IRCRTCVideoInputFrameListener; +import cn.rongcloud.rtc.api.stream.RCRTCInputStream; +import cn.rongcloud.rtc.api.stream.RCRTCLiveInfo; +import cn.rongcloud.rtc.api.stream.RCRTCOutputStream; +import cn.rongcloud.rtc.api.stream.RCRTCVideoInputStream; +import cn.rongcloud.rtc.api.stream.RCRTCVideoStreamConfig; +import cn.rongcloud.rtc.api.stream.RCRTCVideoView; +import cn.rongcloud.rtc.base.RCRTCLiveRole; +import cn.rongcloud.rtc.base.RCRTCMediaType; +import cn.rongcloud.rtc.base.RCRTCParamsType; +import cn.rongcloud.rtc.base.RCRTCRemoteVideoFrame; +import cn.rongcloud.rtc.base.RCRTCRoomType; +import cn.rongcloud.rtc.base.RCRTCStreamType; +import cn.rongcloud.rtc.base.RTCErrorCode; +import cn.rongcloud.rtc.core.RendererCommon; + +public class LivePlaySwViewHolder extends LiveRoomPlayViewHolder { + + private static final String TAG = "LivePlayViewHolder"; + private ViewGroup mRoot; + private ViewGroup mSmallContainer; + private ViewGroup mLeftContainer; + private ViewGroup mRightContainer; + private RelativeLayout mPkContainer; + public StyledPlayerView mVideoView; + + private View mLoading, mLoading2; + private ImageView mCover; + private boolean mPaused;//是否切后台了 + private boolean mStarted;//是否开始了播放 + private boolean mEnd;//是否结束了播放 + public static ImageView leave; + + private boolean mPausedPlay;//是否被动暂停了播放 + public int landscape; //1h 2s + public Context contexts; + public FrameLayout ry_view; + + private static final int VIDEO_VERTICAL = 2; + private static final int VIDEO_HORIZONTAL = 1; + int videoLandscape = -1; // 视频方向,2=竖屏,1=横屏 + + static int vHeight;//视频高 + private TextView debugView; + private LiveExoPlayerManager mPlayer; + private boolean isPk = false; + private boolean userJoinLinkMic = false;//用户是否已加入房间 + + //0未申请1申请中2连麦中 + RCRTCRoom rcrtcRoom; + String purl, srcUrl; + + public int getLandscape() { + return landscape; + } + + public LivePlaySwViewHolder(Context context, ViewGroup parentView, int landscapes) { + super(context, parentView); + contexts = context; + landscape = landscapes; + Log.i("收收收", landscape + ""); + } + + + @Override + protected int getLayoutId() { + return R.layout.view_live_play_ksy; + } + + @Override + public void init() { + Log.i(TAG, "init: 初始化播放器ViewHolder"); + EventBus.getDefault().register(this); + Bus.getOn(this); + mRoot = (ViewGroup) findViewById(R.id.root); + mSmallContainer = (ViewGroup) findViewById(R.id.small_container); + mLeftContainer = (ViewGroup) findViewById(R.id.left_container); + mRightContainer = (ViewGroup) findViewById(R.id.right_container); + mPkContainer = (RelativeLayout) findViewById(R.id.pk_container); + mVideoView = (StyledPlayerView) findViewById(R.id.video_view); + ry_view = (FrameLayout) findViewById(R.id.ry_view); + leave = (ImageView) findViewById(R.id.leave); + mLoading = findViewById(R.id.loading); + mLoading2 = findViewById(R.id.loading2); + mCover = (ImageView) findViewById(R.id.cover); + ScreenDimenUtil util = ScreenDimenUtil.getInstance(); + int mScreenWdith = util.getScreenWdith(); + vHeight = mScreenWdith * 720 / 960; + + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mPkContainer.getLayoutParams(); + params.height = vHeight; + mPkContainer.requestLayout(); + + mPlayer = new LiveExoPlayerManager(mContext); + mPlayer.setMainView(mVideoView); + mPlayer.setListener(new ExoPlayerListener()); + debugView = new TextView(mContext); + debugView.setBackgroundColor(Color.WHITE); + + } + + @Override + public void hideCover() { +// if (mCover != null) { +// if (mCover.getVisibility()==View.VISIBLE){ +//// new Handler().postDelayed(new Runnable() { +//// @Override +//// public void run() { +//// +//// } +//// },200); +// mCover.setVisibility(View.GONE); +// mLoading2.setVisibility(View.GONE); +// } +// +// +// } + } + + @Override + public void setCover(String coverUrl) { +// if (mCover != null) { +// mCover.setVisibility(View.VISIBLE); +// mLoading2.setVisibility(View.VISIBLE); +// ImgLoader.displayBlurLive(mContext, coverUrl, mCover, 400, 600); +// +// } + }// + + @Override + public synchronized void setLiveBeanLandscape(int landscape) { +// landscape=1; + Log.i(TAG, "setLiveBeanLandscape: " + landscape + " isPk: " + isPk); + this.landscape = landscape; + this.videoLandscape = landscape; + if (mPlayer != null) { + mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); + } + + if (landscape == 2) { + Log.i(TAG, "还原9:16"); + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); + params.height = RelativeLayout.LayoutParams.MATCH_PARENT; + params.topMargin = 0; + mVideoView.setLayoutParams(params); + mVideoView.requestLayout(); + + RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams) ry_view.getLayoutParams(); + params1.height = RelativeLayout.LayoutParams.MATCH_PARENT; + params1.topMargin = 0; + ry_view.setLayoutParams(params1); + ry_view.requestLayout(); + RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams) mCover.getLayoutParams(); + params2.height = RelativeLayout.LayoutParams.MATCH_PARENT; + params2.topMargin = 0; + mCover.setLayoutParams(params2); + mCover.requestLayout(); + + } else { + Log.i(TAG, "还原16:9"); + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); + params.height = vHeight; + params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); + params.addRule(RelativeLayout.ALIGN_TOP); + mVideoView.setLayoutParams(params); + mVideoView.requestLayout(); + + RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams) ry_view.getLayoutParams(); + params1.height = vHeight; + params1.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); + params1.addRule(RelativeLayout.ALIGN_TOP); + ry_view.setLayoutParams(params1); + ry_view.requestLayout(); + RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams) mCover.getLayoutParams(); + params2.height = DpUtil.dp2px(270); + params2.topMargin = DpUtil.dp2px(120); + mCover.setLayoutParams(params2); + mCover.requestLayout(); + } + } + + @Override + public void setLiveEnterRoomNewModel(EnterRoomNewModel data) { + super.setLiveEnterRoomNewModel(data); + isPk = data.getEnterRoomInfo().getIsconnection().equals("1"); + if (isPk) { + setLiveBeanLandscape(1); + } + } + + /** + * 暂停播放 + */ + @Override + public void pausePlay() { + + } + + /** + * 暂停播放后恢复 + */ + @Override + public void resumePlay() { + if (!mPlayer.isPlaying()) { + new Handler(Looper.getMainLooper()) + .postDelayed(() -> { + mPlayer.replay(); + // ToastUtil.show("强制播放" + val); + }, 100); + } + } + + /** + * 开始播放 + * + * @param url 流地址 + */ + @Override + public void play(String url, int playModel) { + srcUrl = url; + PLAY_MODEL = playModel; + waitNextUrl = null; + Log.i(TAG, "play" + " url:" + url + " playModel: " + playModel + " landscape: " + landscape + " videoLandscape" + videoLandscape); + if (playModel != PLAY_MODEL_DEF && !url.contains(videoFps[0] + ".flv")) { + mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); + if (landscape == VIDEO_VERTICAL && !isPk) { + url = url.replace(".flv", videoRatioVertical[playModel] + videoFps[0] + ".flv"); + } else if (landscape == VIDEO_HORIZONTAL || isPk) { + url = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); + } + } else if (!url.contains(videoFps[0] + ".flv")) { + mPlayer.setViewResizeMode(false); + } + Log.e("purl121", url); + + if (TextUtils.isEmpty(url) || mVideoView == null) { + return; + } + + if (TextUtils.isEmpty(url) || mVideoView == null) { + return; + } + if (mPlayer.isPlaying()) { + mPlayer.stop(); + mPlayer.clearUrl(); + } + mPlayer.startUrl(url); + purl = url; + onPrepared(); + } + + @Override + public void switchStream(String url, int playModel) { + srcUrl = url; + PLAY_MODEL = playModel; + Log.i(TAG, "switchStream: " + " url:" + url + " playModel: " + playModel + " landscape: " + landscape + " videoLandscape = " + videoLandscape + " ispk = " + isPk + " bean = " + roomModel.getEnterRoomInfo().getIsconnection()); + if (playModel != PLAY_MODEL_DEF && !url.contains(videoFps[0] + ".flv")) { + mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); + if (landscape == VIDEO_VERTICAL && !isPk) { + url = url.replace(".flv", videoRatioVertical[playModel] + videoFps[0] + ".flv"); + } else if (landscape == VIDEO_HORIZONTAL || isPk) { + url = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); + } + } else if (!url.contains(videoFps[0] + ".flv")) { + mPlayer.setViewResizeMode(false); + } + Log.e("purl121", url); + + if (TextUtils.isEmpty(url) || mVideoView == null) { + return; + } + + + if (TextUtils.isEmpty(url) || mVideoView == null) { + return; + } + mPlayer.switchUrl(url); + purl = url; + } + + boolean tmpPk = false; + String waitNextUrl = null; + + @Override + public void switchStreamPk(boolean isPk) { + super.switchStreamPk(isPk); + Log.i(TAG, "switchStreamPk: isPk1" + isPk + " tmp = " + !tmpPk + " isPk2 = " + this.isPk); + if (this.isPk && tmpPk) return; + if (isPk && !tmpPk || this.isPk) { + mPlayer.setViewResizeMode(false); + String url; + if (PLAY_MODEL != -1) { + url = srcUrl.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); + } else { + url = srcUrl.replace(".flv", videoRatioHorizontal[1] + videoFps[0] + ".flv"); + } + if (!tmpPk) { + waitNextUrl = url; + } + mPlayer.switchUrl(srcUrl); + tmpPk = true; + } else if (!isPk) { + tmpPk = false; + if (landscape == VIDEO_VERTICAL && PLAY_MODEL != -1) { + waitNextUrl = srcUrl.replace(".flv", videoRatioVertical[PLAY_MODEL] + videoFps[0] + ".flv"); + } else if (landscape == VIDEO_HORIZONTAL && PLAY_MODEL != -1) { + waitNextUrl = srcUrl.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); + } else { + waitNextUrl = null; + } + mPlayer.switchUrl(srcUrl); + } + } + + @Override + public void clearFrame() { + super.clearFrame(); + mPlayer.clearFrame(); + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); + params.height = ViewGroup.LayoutParams.WRAP_CONTENT; + params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); + params.addRule(RelativeLayout.ALIGN_TOP); + mVideoView.setLayoutParams(params); + mVideoView.requestLayout(); + + RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams) ry_view.getLayoutParams(); + params1.height = ViewGroup.LayoutParams.WRAP_CONTENT; + params1.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); + params1.addRule(RelativeLayout.ALIGN_TOP); + ry_view.setLayoutParams(params1); + ry_view.requestLayout(); + RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams) mCover.getLayoutParams(); + params2.height = DpUtil.dp2px(270); + params2.topMargin = DpUtil.dp2px(120); + mCover.setLayoutParams(params2); + mCover.requestLayout(); + } + + @Override + public void release() { + mEnd = true; + mStarted = false; + if (mPlayer != null) { + mPlayer.stop(); + mPlayer.release(); + } + Bus.getOff(this); + EventBus.getDefault().unregister(this); + L.e(TAG, "release------->"); + } + + @Override + public void stopPlay() { + Log.i(TAG, "stopPlay: "); + if (mCover != null) { + mCover.setAlpha(1f); + if (mCover.getVisibility() != View.VISIBLE) { + mCover.setVisibility(View.VISIBLE); + } + } + if (mPlayer != null) { + mPlayer.stop(); + } + stopPlay2(); + } + + @Override + public void stopPlay2() { + + } + + @Override + public void setViewUP(int i) { + if (mVideoView == null) return; + Log.e("PK状态", "" + i); + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); + params.height = vHeight; + params.topMargin = contexts.getResources().getDimensionPixelOffset(R.dimen.live_top); + params.addRule(RelativeLayout.ALIGN_TOP); + mVideoView.requestLayout(); + + RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams) ry_view.getLayoutParams(); + params1.height = vHeight; + params1.topMargin = contexts.getResources().getDimensionPixelOffset(R.dimen.live_top); + params1.addRule(RelativeLayout.ALIGN_TOP); + ry_view.requestLayout(); + isPk = true; + if (mPlayer.getUrl().contains("848_24.flv") || mPlayer.getUrl().contains("1280_24.flv")) { + tmpPk = false; + switchStreamPk(true); + } + } + + /** + * 播放开始 + */ + public void onPrepared() { + if (mEnd) { + release(); + return; + } + int height; + if (videoLandscape == VIDEO_VERTICAL) { + height = ViewGroup.LayoutParams.MATCH_PARENT; + } else { + height = ViewGroup.LayoutParams.WRAP_CONTENT; + } + mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); + if (landscape == 2) { + Log.i(TAG, "onPrepared:还原9:16 land=" + videoLandscape); + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); + params.height = height; + params.topMargin = 0; + params.addRule(RelativeLayout.ALIGN_TOP); + mVideoView.setLayoutParams(params); + mVideoView.requestLayout(); + + RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams) ry_view.getLayoutParams(); + params1.height = height; + params1.topMargin = 0; + ry_view.setLayoutParams(params1); + ry_view.requestLayout(); + RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams) mCover.getLayoutParams(); + params2.height = height; + params2.topMargin = 0; + mCover.setLayoutParams(params2); + mCover.requestLayout(); + } else { + Log.i(TAG, "onPrepared:还原16:9"); + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); + params.height = height; + params.topMargin = 0; + if (videoLandscape == VIDEO_HORIZONTAL) { + params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); + } + params.addRule(RelativeLayout.ALIGN_TOP); + mVideoView.setLayoutParams(params); + mVideoView.requestLayout(); + + RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams) ry_view.getLayoutParams(); + params1.height = height; + params1.topMargin = 0; + params1.addRule(RelativeLayout.ALIGN_TOP); + if (videoLandscape == VIDEO_HORIZONTAL) { + params1.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); + } + ry_view.setLayoutParams(params1); + ry_view.requestLayout(); + RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams) mCover.getLayoutParams(); + params2.height = height; + params2.topMargin = DpUtil.dp2px(120); + mCover.setLayoutParams(params2); + mCover.requestLayout(); + } + } + + @Override + public void setPkview() { + Log.i("收到socket--->", "变成16:9"); + String url = srcUrl; + isPk = true; + switchStreamPk(true); + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); + params.height = vHeight; + params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); + params.addRule(RelativeLayout.ALIGN_TOP); + mVideoView.requestLayout(); + } + + @Override + public synchronized void setPkEndview() { + + Log.i("收收收", landscape + ""); + isPk = false; + tmpPk = false; + switchStreamPk(false); + if (landscape == 2) { + Log.i("收到socket--->", "还原9:16"); + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); + params.height = RelativeLayout.LayoutParams.MATCH_PARENT; + params.topMargin = 0; + mVideoView.requestLayout(); + + } else { + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); + params.height = vHeight; + params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); + params.addRule(RelativeLayout.ALIGN_TOP); + mVideoView.requestLayout(); + } +// if (detailsView != null) { +// mVideoView.removeView(detailsView); +// detailsView = null; +// } + } + + public void removeDetailView() { +// if (detailsView != null) { +// mVideoView.removeView(detailsView); +// detailsView = null; +// } + } + + @Override + public ViewGroup getSmallContainer() { + return mSmallContainer; + } + + + @Override + public ViewGroup getRightContainer() { + return mRightContainer; + } + + @Override + public ViewGroup getPkContainer() { + return mPkContainer; + } + + @Override + public void changeToLeft() { + if (mVideoView != null) { + + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); + params.height = vHeight; +// params.height = mContext.getResources().getDimensionPixelOffset(R.dimen.live_view); + params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); + params.addRule(RelativeLayout.ALIGN_TOP); + mVideoView.requestLayout(); + + } + if (mLoading != null && mLeftContainer != null) { + ViewParent viewParent = mLoading.getParent(); + if (viewParent != null) { + ((ViewGroup) viewParent).removeView(mLoading); + } + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(DpUtil.dp2px(24), DpUtil.dp2px(24)); + params.gravity = Gravity.CENTER; + mLoading.setLayoutParams(params); + mLeftContainer.addView(mLoading); + } + } + + @Override + public void changeToBig() { + if (mVideoView != null) { + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + mVideoView.setLayoutParams(params); + + } + if (mLoading != null && mRoot != null) { + ViewParent viewParent = mLoading.getParent(); + if (viewParent != null) { + ((ViewGroup) viewParent).removeView(mLoading); + } + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(DpUtil.dp2px(24), DpUtil.dp2px(24)); + params.addRule(RelativeLayout.CENTER_IN_PARENT); + mLoading.setLayoutParams(params); + mRoot.addView(mLoading); + } + } + + @Override + public void onResume() { + if (!mPausedPlay && mPaused && mVideoView != null) { +// mVideoView.runInForeground(); +// mVideoView.start(); + } + mPaused = false; +// if (mPlayer.isPlaying() == 1) { +// mPlayer.resumeVideo(); +// mPlayer.resumeAudio(); +// } + } + + @Override + public void onPause() { +// if (!mPausedPlay && mVideoView != null) { +// mVideoView.runInBackground(false); +// } +// mPaused = true; +// mPlayer.pauseVideo(); +// mPlayer.pauseAudio(); + } + + @Override + public void onDestroy() { + release(); + } + + //全屏 + @Override + public void fullScreen() { + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); + params.height = RelativeLayout.LayoutParams.MATCH_PARENT; + params.topMargin = 0; + params.addRule(RelativeLayout.ALIGN_TOP); + mVideoView.requestLayout(); + } + + //小屏 + @Override + public void smallScreen() { + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); + params.height = vHeight; + params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); + // mPlayer.setRenderRotation(V2TXLiveDef.V2TXLiveRotation.V2TXLiveRotation0); + params.addRule(RelativeLayout.ALIGN_TOP); + mVideoView.requestLayout(); + } + + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onUpdata(String str) { + if ("UsertoRY".equals(str)) { + DialogUitl.showSimpleDialog(mContext, mContext.getString(R.string.mic_tag), new DialogUitl.SimpleCallback() { + @Override + public void onConfirmClick(Dialog dialog, String content) { + UsertoRY(); + dialog = null; + } + }); + + } else if ("inviteMic".equals(str)) { + String content = "邀請您進行語音連麥"; + String confirm = "接受"; + String cancel = "拒絕"; + if (!WordUtil.isNewZh()) { + content = "You are invited to join the voice connection"; + confirm = "accept"; + cancel = "cancel"; + } + DialogUitl.Builder builder = new DialogUitl.Builder(mContext) + .setContent(content) + .setTitle(mLiveBean.getUserNiceName()) + .setConfirmString(confirm) + .setCancelString(cancel) + .setView(R.layout.dialog_live_mic_invite) + .setClickCallback(new DialogUitl.SimpleCallback() { + @Override + public void onConfirmClick(Dialog dialog, String content) { + String[] permissions; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + permissions = new String[]{ + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.RECORD_AUDIO + }; + } else { + permissions = new String[]{ + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.RECORD_AUDIO + }; + } + LiveAudienceActivity.mProcessResultUtil.requestPermissions(permissions, new Runnable() { + @Override + public void run() { + UsertoRY(); + + } + }); + } + }); + builder.build().show(); + + } else if ("endMic".equals(str)) { + if (rcrtcRoom != null) { + // 开始切换为观众身份 + RCRTCEngine.getInstance().getRoom().getLocalUser().switchToAudience(new IRCRTCSwitchRoleCallback() { + + /** + * 当切换失败且SDK处于无法回退状态时回调,该角色已经无法使用当前角色继续进行音视频。 + * SDK内部会退出房间并清理所有资源,该用户只能重新加入房间才能继续音视频。 + */ + @Override + public void onKicked() { + + } + + @Override + public void onSuccess() { + Log.e("ry", "下麦成功"); + // 该用户切换为观众成功,可以以观众身份进行音视频 + //退出rtc播放 + leaveRoom(); + } + + /** + * 当切换失败且不影响当前角色继续音视频时回调 + * @param errorCode 失败错误码 + */ + @Override + public void onFailed(RTCErrorCode errorCode) { + Log.e("ry", "下麦失败" + errorCode); + leaveRoom(); + } + + private void leaveRoom() { + RCRTCEngine.getInstance().leaveRoom(new IRCRTCResultCallback() { + @Override + public void onSuccess() { + userJoinLinkMic = false; + Log.e("ry", "退出多人房间成功"); + new Handler(Looper.getMainLooper()).post(new Runnable() { + public void run() { + if (WordUtil.isNewZh()) { + ToastUtil.show("已成功退出語音連麥"); + } else { + ToastUtil.show("You have successfully exited the voice connection"); + } + if (mPlayer.getNowPlayer() != null) { + mPlayer.play(); + Log.e("ry", mPlayer.isPlaying() + "purl" + purl); + if (!mPlayer.isPlaying()) { + mPlayer.switchUrl(purl); + } + ry_view.removeAllViews(); + ry_view.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; + onPrepared(); + rcrtcRoom = null; + MicStatusManager.getInstance().clear(); + + resumePlay(); + } + + if (onMicCallback != null) { + onMicCallback.onMikUpdate(); + } + } + }); + } + + @Override + public void onFailed(RTCErrorCode errorCode) { + Log.e("ry", errorCode + "退出多人房间成功"); + userJoinLinkMic = false; + } + }); + + } + }); + } + } else if ("Debug".equals(str)) { + if (EasyFloat.isShow("Debug")) { + EasyFloat.dismiss("Debug"); + return; + } + EasyFloat.with(mContext) + .setDragEnable(true) + .setTag("Debug") + .setLayout(debugView) + .show(); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onOpenDrawer(LiveAudienceEvent event) { + if (event.getType() == LiveAudienceEvent.LiveAudienceType.LIVE_VIDEO) { + int ban = 0;//全模式都可以选择 + switch (roomModel.getClarityType() - 1) { + case PLAY_MODEL_720://仅允许720(高清),ban掉1080(超高清)模式 + ban = LiveClarityCustomPopup.BAN_1080; + break; + case -1://没有该字段 + case PLAY_MODEL_480://仅允许480(流畅),ban掉1080(超高清)和720(高清)模式 + ban = LiveClarityCustomPopup.BAN_720; + break; + + } + LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, + IMLoginManager.get(mContext).getInt(PLAY_MODEL_KEY, PLAY_MODEL_ANCHOR), + ban, + true); + new XPopup.Builder(mContext) + .setPopupCallback(new XPopupCallback() { + @Override + public void onCreated(BasePopupView popupView) { + + } + + @Override + public void beforeShow(BasePopupView popupView) { + + } + + @Override + public void onShow(BasePopupView popupView) { + + } + + @Override + public void onDismiss(BasePopupView popupView) { + int selectClarity = liveClarityCustomPopup.getSelectClarity(); + if (selectClarity == PLAY_MODEL || selectClarity == IMLoginManager.get(mContext).getInt(LiveRoomPlayViewHolder.PLAY_MODEL_KEY, PLAY_MODEL_ANCHOR)) + return; + if (selectClarity == PLAY_MODEL_ANCHOR) { + switchStream(srcUrl, PLAY_MODEL_DEF); + setAudiencePlayModel(selectClarity); + } else { + switchStream(srcUrl, selectClarity); + } + IMLoginManager.get(mContext).put(LiveRoomPlayViewHolder.PLAY_MODEL_KEY, selectClarity); + showToast(); + } + + private void showToast() { + if (WordUtil.isNewZh()) { + DialogUitl.showToast(mContext, "設置成功\n" + + "正在為你轉換中", 3000); + } else { + DialogUitl.showToast(mContext, "successful\n" + + "It's being converted for you", 3000); + } + } + + @Override + public void beforeDismiss(BasePopupView popupView) { + + } + + @Override + public boolean onBackPressed(BasePopupView popupView) { + return false; + } + + @Override + public void onKeyBoardStateChanged(BasePopupView popupView, int height) { + + } + + @Override + public void onDrag(BasePopupView popupView, int value, float percent, boolean upOrLeft) { + + } + + @Override + public void onClickOutside(BasePopupView popupView) { + + } + }) + .asCustom(liveClarityCustomPopup) + .show(); + } else if (event.getType() == LiveAudienceEvent.LiveAudienceType.FONT_SIZE) { + int fount = 0; + try { + fount = Integer.parseInt(SpUtil.getStringValue("pd_live_room_fount_size")); + } catch (Exception ignored) { + + } + new LiveFontSizeSettingDialog(mContext, fount).setOnItemClickListener(new OnItemClickListener() { + @Override + public void onItemClick(Integer bean, int position) { + EventBus.getDefault().post(new LiveAudienceEvent() + .setNums(bean) + .setType(LiveAudienceEvent.LiveAudienceType.LIVE_FONT_SIZE)); + } + }).showDialog(); + } + } + + /** + * 把观众转换成主播 + */ + public List userinputStreamList = new ArrayList<>(); + + + public void UsertoRY() { + userinputStreamList.clear(); + Log.e("ry", "主播同意了UsertoRY"); + if (userJoinLinkMic) {//已经在房间内,不再joinRoom直接去连麦 + subscribeMic(rcrtcRoom); + return; + } + RCRTCRoomConfig roomConfig = RCRTCRoomConfig.Builder.create() + // 根据实际场景,选择音视频直播:LIVE_AUDIO_VIDEO 或音频直播:LIVE_AUDIO + .setRoomType(RCRTCRoomType.LIVE_AUDIO_VIDEO) + .setLiveRole(RCRTCLiveRole.AUDIENCE) + .build(); + RCRTCEngine.getInstance().joinRoom(LiveActivity.mLiveUid, roomConfig, new IRCRTCResultDataCallback() { + + + @Override + public void onSuccess(RCRTCRoom data) { + userJoinLinkMic = true; + rcrtcRoom = data; + subscribeMic(data); + + } + + @Override + public void onFailed(RTCErrorCode errorCode) { + Log.e("ry", LiveActivity.mLiveUid + errorCode + ""); + if (errorCode.getValue() == 50007) {//userJoinLinkMic可能失效,直接leaveRoom + userJoinLinkMic = false; + RCRTCEngine.getInstance().leaveRoom(new IRCRTCResultCallback() { + + @Override + public void onFailed(RTCErrorCode errorCode) { + + } + + @Override + public void onSuccess() { + UsertoRY(); + } + }); + } else { + ToastUtil.show("房间失败" + errorCode); + } + + } + }); + + + } + + private void subscribeMic(RCRTCRoom data) { + runOnUiThread(new Runnable() { + @Override + public void run() { + RCRTCEngine.getInstance().enableSpeaker(true); + //遍历远端用户发布的资源列表 + Log.i(TAG, "软件资源数量:" + data.getLiveStreams().size()); + for (RCRTCInputStream stream : data.getLiveStreams()) { + Log.i(TAG, "资源流 type: " + stream.getMediaType()); + if (stream.getMediaType() == RCRTCMediaType.VIDEO) { + //暂停播放 + mPlayer.stop(); + //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 + + //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 + RCRTCVideoView remoteView = new RCRTCVideoView(contexts); + ((RCRTCVideoInputStream) stream).setVideoView(remoteView); + //todo 本demo只演示添加1个远端用户的视图 + remoteView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + remoteView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT); + ry_view.addView(remoteView); + Log.e("ry", stream.getMediaType() + "rcrtcOtherRoom成功 :" + data.getLiveStreams().size()); + } + userinputStreamList.add(stream); + } + rcrtcRoom.getLocalUser().subscribeStreams(userinputStreamList, new IRCRTCResultCallback() { + + @Override + public void onFailed(RTCErrorCode errorCode) { + Log.e("ry", userinputStreamList.size() + LiveActivity.mLiveUid + "订阅失败" + errorCode.toString()); + ToastUtil.show(mContext.getString(R.string.live_pk_link_error)); + } + + @Override + public void onSuccess() { + Log.e("ry", "订阅资源成功"); +// new Handler().postDelayed(new Runnable() { +// @Override +// public void run() { + toMic(); +// } +// }, 3000); + + } + }); + } + }); + } + + /** + * 主房间事件监听 + * 详细说明请参考文档:https://www.rongcloud.cn/docs/api/android/rtclib_v4/cn/rongcloud/rtc/api/callback/IRCRTCRoomEventsListener.html + */ + public IRCRTCRoomEventsListener roomEventsListener = new IRCRTCRoomEventsListener() { + @Override + public void onRemoteUserPublishResource(RCRTCRemoteUser rcrtcRemoteUser, List list) { + Log.e("ry", "远端来了" + list.size()); + //TODO 按需在此订阅远端用户发布的资源 + rcrtcRoom.getLocalUser().subscribeStreams(list, new IRCRTCResultCallback() { + @Override + public void onSuccess() { + Log.e("ry", "远端成功" + list.size()); + + } + + @Override + public void onFailed(RTCErrorCode rtcErrorCode) { + Log.e("ry", "远端失败" + list.size()); + ToastUtil.show(mContext.getString(R.string.live_pk_link_error)); + } + }); + } + + @Override + public void onRemoteUserMuteAudio(RCRTCRemoteUser remoteUser, RCRTCInputStream stream, boolean mute) { + + } + + @Override + public void onRemoteUserMuteVideo(RCRTCRemoteUser remoteUser, RCRTCInputStream stream, boolean mute) { + + } + + @Override + public void onRemoteUserUnpublishResource(RCRTCRemoteUser remoteUser, List streams) { + + } + + @Override + public void onUserJoined(RCRTCRemoteUser remoteUser) { + + } + + @Override + public void onUserLeft(RCRTCRemoteUser remoteUser) { + + } + + @Override + public void onUserOffline(RCRTCRemoteUser remoteUser) { + + } + + @Override + public void onPublishLiveStreams(List streams) { + + } + + @Override + public void onUnpublishLiveStreams(List streams) { + + } + }; + + + public List userinputStreamList1 = new ArrayList<>(); + public List userinputStreamList2 = new ArrayList<>(); + + public void toMic() { + RCRTCEngine.getInstance().getDefaultAudioStream().setAudioQuality(RCRTCParamsType.AudioQuality.MUSIC, RCRTCParamsType.AudioScenario.MUSIC_CLASSROOM); + userinputStreamList1.clear(); + userinputStreamList2.clear(); + RCRTCParamsType.RCRTCVideoResolution rcrtcVideoResolution = RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_480_848; + int minRate = 200; + int maxRate = 900; + switch (IMLoginManager.get(mContext).getSelectClarity()) { + case 0: + rcrtcVideoResolution = landscape == 1 ? RCRTCParamsType.RCRTCVideoResolution.parseVideoResolution(960, 720) : RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_480_848; + minRate = landscape == 1 ? 900 : 200; + maxRate = landscape == 1 ? 700 : 900; + break; + case 1: + rcrtcVideoResolution = landscape == 1 ? RCRTCParamsType.RCRTCVideoResolution.parseVideoResolution(960, 720) : RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_720_1280; + minRate = landscape == 1 ? 900 : 250; + maxRate = landscape == 1 ? 700 : 2200; + break; + case 2: + rcrtcVideoResolution = landscape == 1 ? RCRTCParamsType.RCRTCVideoResolution.parseVideoResolution(960, 720) : RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_1080_1920; + minRate = landscape == 1 ? 900 : 400; + maxRate = landscape == 1 ? 700 : 4000; + break; + } + // 示例代码使用480x640分辨率演示 + RCRTCVideoStreamConfig config = RCRTCVideoStreamConfig + .Builder.create() + //设置分辨率 + .setVideoResolution(rcrtcVideoResolution) + //设置帧率 + .setVideoFps(RCRTCParamsType.RCRTCVideoFps.Fps_24) + //设置最小码率,480P下推荐200 + .setMinRate(minRate) + //设置最大码率,480P下推荐900 + .setMaxRate(maxRate) + .build(); + RCRTCEngine.getInstance().getDefaultVideoStream().setVideoConfig(config); +// 创建视图渲染视图 +// RCRTCVideoView videoView = new RCRTCVideoView(contexts); +// RCRTCEngine.getInstance().getDefaultVideoStream().setVideoView(videoView); +//TODO 示例代码使用获取本地默认视频流、音频流演示 + ArrayList streams = new ArrayList<>(); +// streams.add(RCRTCEngine.getInstance().getDefaultVideoStream()); + streams.add(RCRTCEngine.getInstance().getDefaultAudioStream()); + if (landscape == 1) { + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + setLiveBeanLandscape(1); + } + }); + + } +// 开启摄像头 +// RCRTCEngine.getInstance().getDefaultVideoStream().startCamera(null); +// 开始切换为主播身份 + RCRTCEngine.getInstance().getRoom().getLocalUser().switchToBroadcaster(streams, new IRCRTCSwitchRoleDataCallback() { + /** + * 当切换失败且SDK处于无法回退状态时回调,该角色已经无法使用当前角色继续进行音视频。 + * SDK内部会退出房间并清理所有资源,该用户只能重新加入房间才能继续音视频。 + */ + @Override + public void onKicked() { + Log.e("ry", "切换onKicked"); + + } + + @Override + public void onSuccess(RCRTCLiveInfo data) { + rcrtcRoom.registerRoomListener(roomEventsListener); + //该用户切换为主播成功,可以以主播身份进行音视频 + Log.e("ry", "切换成功"); + new Handler(Looper.getMainLooper()).post(new Runnable() { + public void run() { + if (onMicCallback != null) { + onMicCallback.onMikUpdate(); + } + //遍历远端用户列表 + for (int i = 0; i < rcrtcRoom.getRemoteUsers().size(); i++) { + Log.e("ry", rcrtcRoom.getRemoteUsers().get(i).getUserId() + "收到rcrtcOtherRoom" + rcrtcRoom.getRemoteUsers().size()); + //遍历远端用户发布的资源列表 + for (RCRTCInputStream stream : rcrtcRoom.getRemoteUsers().get(i).getStreams()) { + Log.e("ry", i + "收到" + stream.getMediaType() + "实打实打算" + rcrtcRoom.getRemoteUsers().get(i).getUserId()); + if (stream.getMediaType() == RCRTCMediaType.VIDEO) { + if (userinputStreamList1.size() == 0) { + + //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 + RCRTCVideoView remoteView = new RCRTCVideoView(contexts); + ((RCRTCVideoInputStream) stream).setStreamType(RCRTCStreamType.NORMAL); + ((RCRTCVideoInputStream) stream).setVideoView(remoteView); + ((RCRTCVideoInputStream) stream).setVideoFrameListener(new IRCRTCVideoInputFrameListener() { + @Override + public void onFrame(RCRTCRemoteVideoFrame videoFrame) { + String debugText = " 2、安卓主播开播, 安卓用户申请连麦后 ,安卓用户这边底部画面不全 :" + videoFrame.getFrameType().name() + "\n" + + "rotation:" + videoFrame.getRotation() + "\n" + + "timestampNs:" + videoFrame.getTimestampNs() + "\n" + + "分辨率:" + videoFrame.getBuffer().getHeight() + "x" + videoFrame.getBuffer().getWidth() + "\n" + + "当前时间:" + new SimpleDateFormat("HH:mm:ss", Locale.CHINA).format(new Date()) + "\n"; + //Log.d("ry", "onFrame: " + debugText); + new Handler(Looper.getMainLooper()).post(() -> { + debugView.setText(debugText); + + }); + } + }); + //todo 本demo只演示添加1个远端用户的视图 + ry_view.removeAllViews(); + remoteView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + remoteView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL); + ry_view.addView(remoteView); + } + userinputStreamList1.add(stream); + } + userinputStreamList2.add(stream); + } + } + //开始订阅资源 + rcrtcRoom.getLocalUser().subscribeStreams(userinputStreamList2, new IRCRTCResultCallback() { + @Override + public void onSuccess() { + Log.e("ry", "订阅资源成功"); + MicStatusManager.getInstance().setMicData(MicStatusManager.MIC_TYPE_OPEN, LiveActivity.mLiveUid); + AudioManager audioManager = (AudioManager) contexts.getSystemService(Context.AUDIO_SERVICE); + RCRTCEngine.getInstance().enableSpeaker(true); + audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); + audioManager.setSpeakerphoneOn(true); + + HttpClient.getInstance().get("live.joinDrLm", "live.joinDrLm") + .params("roomid", LiveActivity.mLiveUid) + .execute(new HttpCallback() { + @Override + public void onSuccess(int code, String msg, String[] info) { + Log.e("ry", code + "热热热"); + } + }); + } + + @Override + public void onFailed(RTCErrorCode rtcErrorCode) { + Log.e("ry", "订阅资源失败: " + rtcErrorCode.getReason()); + ToastUtil.show(mContext.getString(R.string.live_pk_link_error)); + } + }); + } + }); + + + } + + /** + * 当切换失败且不影响当前角色继续音视频时回调 + * @param errorCode 失败错误码 + */ + @Override + public void onFailed(RTCErrorCode errorCode) { + Log.e("ry", errorCode + "切换失败"); + + } + }); + } + + @Override + public void setLoadViewListener(LoadingListener listener) { + super.setLoadViewListener(listener); + } + + private void showLoadingDialog() { + if (PLAY_MODEL == PLAY_MODEL_480) return; + + new DialogUitl.Builder(mContext) + .setTitle("網絡提示") + .setContent("系統監測到您的網絡不穩定,對此將清晰度變成了流暢,您可以在側邊菜單中的「清晰度」選擇調回。") + .setView(R.layout.dialog_simple_tip) + .setClickCallback(new DialogUitl.SimpleCallback() { + @Override + public void onConfirmClick(Dialog dialog, String content) { + dialog.dismiss(); + } + }).build().show(); + PLAY_MODEL = PLAY_MODEL_480; + String url = srcUrl; + if (videoLandscape == VIDEO_VERTICAL) { + url = url.replace(".flv", videoRatioVertical[PLAY_MODEL_480] + videoFps[0] + ".flv"); + } else if (videoLandscape == VIDEO_HORIZONTAL) { + url = url.replace(".flv", videoRatioHorizontal[PLAY_MODEL_480] + videoFps[0] + ".flv"); + } + mPlayer.switchUrl(url); + } + + private class ExoPlayerListener implements Player.Listener { + String TAG = "播放流"; + + @Override + public void onPlayerError(PlaybackException error) { + Player.Listener.super.onPlayerError(error); + debugView.setText("播放出错code=" + error.errorCode + " msg=" + error.getErrorCodeName()); + } + + @Override + public void onVideoSizeChanged(VideoSize videoSize) { + Player.Listener.super.onVideoSizeChanged(videoSize); + Log.i(TAG, "onVideoSizeChanged: width = " + videoSize.width + " height = " + videoSize.height); + //ToastUtil.show("分辨率: 宽 = " + videoSize.width + " 高 = " + videoSize.height); + if (videoSize.height > videoSize.width) { + videoLandscape = VIDEO_VERTICAL; + } else { + videoLandscape = VIDEO_HORIZONTAL; + } + } + + @Override + public void onPlaybackStateChanged(int playbackState) { + Player.Listener.super.onPlaybackStateChanged(playbackState); + if (playbackState == Player.STATE_BUFFERING) { + //showLoadingDialog(); + mLoading.setVisibility(View.VISIBLE); + OkDownload.getInstance().pauseAll(); + Log.i(TAG, "onPlaybackStateChanged: 缓存中"); + } else { + mLoading.setVisibility(View.INVISIBLE); + Log.i(TAG, "onPlaybackStateChanged: 播放中"); + } + } + + @Override + public void onIsPlayingChanged(boolean isPlaying) { + Player.Listener.super.onIsPlayingChanged(isPlaying); + if (isPlaying) { + hideCover(); + mLoading.setVisibility(View.INVISIBLE); + Log.i(TAG, "onIsPlayingChanged: 开始播放 | waitNextUrl = " + waitNextUrl); + OkDownload.getInstance().startAll(); + if (loadingListener != null) { + loadingListener.onPlayer(); + } + if (waitNextUrl != null) { + mPlayer.switchUrl(waitNextUrl); + waitNextUrl = null; + } + } + } + } + + private int mPkTimeCount = 0; + + + public interface PlayViewLayoutInterface { + void playViewLayout(int width, int height); + } + + private PlayViewLayoutInterface layoutInterface; + + public void setLayoutInterface(PlayViewLayoutInterface layoutInterface) { + mVideoView.post(new Runnable() { + @Override + public void run() { + int width = mVideoView.getMeasuredWidth(); + int height = mVideoView.getMeasuredHeight(); + if (layoutInterface != null) { + layoutInterface.playViewLayout(width, height); + } + } + }); + } + + +} diff --git a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java index 9b50cfc7f..0e7d75410 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java @@ -9,8 +9,8 @@ import static com.yunbao.live.event.LiveAudienceEvent.LiveAudienceType.LIVE_PK_I import static com.yunbao.live.presenter.LiveRyLinkMicPkPresenter.inputStreamList; import static com.yunbao.live.presenter.LiveRyLinkMicPkPresenter.inputStreamList1; import static com.yunbao.live.presenter.LiveRyLinkMicPkPresenter.mPkUid; -import static cn.rongcloud.rtc.base.RCRTCLiveRole.BROADCASTER; +import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.res.Resources; @@ -46,6 +46,7 @@ import com.yunbao.common.http.live.LiveNetManager; import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.manager.IMRTCManager; import com.yunbao.common.manager.RandomPkManager; +import com.yunbao.common.manager.SWManager; import com.yunbao.common.utils.Bus; import com.yunbao.common.utils.DialogUitl; import com.yunbao.common.utils.DpUtil; @@ -70,26 +71,19 @@ import org.greenrobot.eventbus.ThreadMode; import java.util.ArrayList; import java.util.List; -import cn.rongcloud.rtc.api.RCRTCConfig; import cn.rongcloud.rtc.api.RCRTCEngine; import cn.rongcloud.rtc.api.RCRTCMixConfig; import cn.rongcloud.rtc.api.RCRTCRemoteUser; import cn.rongcloud.rtc.api.RCRTCRoom; -import cn.rongcloud.rtc.api.RCRTCRoomConfig; -import cn.rongcloud.rtc.api.callback.IRCRTCEngineEventListener; import cn.rongcloud.rtc.api.callback.IRCRTCResultCallback; import cn.rongcloud.rtc.api.callback.IRCRTCResultDataCallback; import cn.rongcloud.rtc.api.callback.IRCRTCRoomEventsListener; import cn.rongcloud.rtc.api.stream.RCRTCInputStream; import cn.rongcloud.rtc.api.stream.RCRTCLiveInfo; -import cn.rongcloud.rtc.api.stream.RCRTCVideoStreamConfig; -import cn.rongcloud.rtc.api.stream.RCRTCVideoView; import cn.rongcloud.rtc.base.RCRTCParamsType; -import cn.rongcloud.rtc.base.RCRTCRoomType; -import cn.rongcloud.rtc.base.RCRTCVideoEventCode; import cn.rongcloud.rtc.base.RTCErrorCode; import cn.rongcloud.rtc.core.CameraVideoCapturer; -import cn.rongcloud.rtc.core.RendererCommon; +import io.agora.rtc2.RtcEngine; import io.rong.imlib.IRongCallback; import io.rong.imlib.RongIMClient; import io.rong.imlib.model.Conversation; @@ -101,13 +95,12 @@ import io.rong.message.TextMessage; */ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITXLivePushListener { - + private RtcEngine mRtcEngine; private int mMeiBaiVal;//基础美颜 美白 private int mMoPiVal;//基础美颜 磨皮 private int mHongRunVal;//基础美颜 红润 private String mBgmPath;//背景音乐路径 private Bitmap mFilterBmp; - private TXDeviceManager mTXDeviceManager; private TRTCCloudDef.TRTCParams mTRTCParams; private Handler mMainHandler; @@ -117,7 +110,6 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX public LinearLayout dr_pk_view; public static RCRTCRoom rtcRoom; public static RCRTCLiveInfo rcrtcLiveInfo; - private ViewGroup liveActivityContainer; public FrameLayout timeTitle; public TextView textTime; @@ -126,6 +118,7 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX private LinearLayout goto_room_view; private boolean isPk = false; private boolean isNeedOpenCamera = false; + private SWManager swManager; //修改上面主播的头像 @Subscribe(threadMode = ThreadMode.MAIN) @@ -139,7 +132,6 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX goto_room_view.setVisibility(View.VISIBLE); } else { goto_room_view.setVisibility(View.GONE); - } } } @@ -414,7 +406,7 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX @Override public void onError(String error) { - ToastUtil.show(WordUtil.isNewZh()?"抱歉!出錯了!":"i \\'m sorry! An error occurred"); + ToastUtil.show(WordUtil.isNewZh() ? "抱歉!出錯了!" : "i \\'m sorry! An error occurred"); } }); @@ -470,7 +462,6 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX } }; - @Override public void init() { super.init(); @@ -615,8 +606,9 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX }); } }); + initRtcEngine(); - // 构建 RoomConfig,指定房间类型和主播身份: + /* // 构建 RoomConfig,指定房间类型和主播身份: RCRTCRoomConfig roomConfig = RCRTCRoomConfig.Builder.create() // 根据实际场景,选择音视频直播:LIVE_AUDIO_VIDEO 或音频直播:LIVE_AUDIO .setRoomType(RCRTCRoomType.LIVE_AUDIO_VIDEO) @@ -772,9 +764,24 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX } - }); + });*/ } + /** + * 初始化声网SDK + */ + private void initRtcEngine() { + swManager = SWManager.get(); + swManager.setAnchorContainer(mPreView); + swManager.initRtcEngine((Activity) mContext, "11"); + swManager.setOnRtcEngineListener(new SWManager.onRtcEngineListener() { + @Override + public void onOpenSuccess(String channel, int uid) { + //开播成功 + + } + }); + } @Override public void changeToLeft() { @@ -847,6 +854,10 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX */ @Override public void startPush(String pushUrl) { + //开播成功,创建频道 + if (swManager != null) { + swManager.createRoom(SWManager.shengwang_token, SWManager.shengwang_channelName); + } if (rcrtcLiveInfo != null) { rcrtcLiveInfo.addPublishStreamUrl(pushUrl, new IRCRTCResultDataCallback() { @Override @@ -946,7 +957,7 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX public void onResume() { mPaused = false; Log.i("摄像头", "onResume: " + isNeedOpenCamera); - if(isNeedOpenCamera){ + if (isNeedOpenCamera) { RCRTCEngine.getInstance().getDefaultVideoStream().startCamera(new IRCRTCResultDataCallback() { @Override public void onSuccess(Boolean data) { diff --git a/live/src/main/res/layout/acticity_new_live.xml b/live/src/main/res/layout/acticity_new_live.xml new file mode 100644 index 000000000..886d43dcd --- /dev/null +++ b/live/src/main/res/layout/acticity_new_live.xml @@ -0,0 +1,37 @@ + + + + + + + + + + diff --git a/live/src/main/res/layout/view_live_play_ksy.xml b/live/src/main/res/layout/view_live_play_ksy.xml index 91b5d0346..b602c6757 100644 --- a/live/src/main/res/layout/view_live_play_ksy.xml +++ b/live/src/main/res/layout/view_live_play_ksy.xml @@ -12,8 +12,14 @@ android:layout_width="match_parent" app:surface_type="texture_view" app:use_controller="false" + android:visibility="gone" android:layout_height="match_parent" /> + +