3838
3939/**
4040 * This demo demonstrates how to make a one-to-one video call
41+ *
42+ * By default, Everyone is a host, entered a channel will see yourself in the background( the big one ).
43+ * click the frame will switch the position.
44+ * When turn the Co-host on, others will see you.
4145 */
4246@ Example (
4347 index = 23 ,
4953public class LiveStreaming extends BaseFragment implements View .OnClickListener {
5054 private static final String TAG = LiveStreaming .class .getSimpleName ();
5155
56+ // foreground is the small one
57+ // background is the large one
5258 private FrameLayout foreGroundVideo , backGroundVideo ;
5359 private Button join , publish ;
5460 private Switch cloudGameMode ;
@@ -60,11 +66,13 @@ public class LiveStreaming extends BaseFragment implements View.OnClickListener
6066 private boolean isHost = false ;
6167 private boolean isLocalVideoForeground = false ;
6268
69+ private SurfaceView localView ;
70+ private SurfaceView remoteView ;
71+
6372 @ Nullable
6473 @ Override
6574 public View onCreateView (@ NonNull LayoutInflater inflater , @ Nullable ViewGroup container , @ Nullable Bundle savedInstanceState ) {
66- View view = inflater .inflate (R .layout .fragment_live_streaming , container , false );
67- return view ;
75+ return inflater .inflate (R .layout .fragment_live_streaming , container , false );
6876 }
6977
7078 @ Override
@@ -73,13 +81,14 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
7381 join = view .findViewById (R .id .btn_join );
7482 publish = view .findViewById (R .id .btn_publish );
7583 et_channel = view .findViewById (R .id .et_channel );
84+ foreGroundVideo = view .findViewById (R .id .foreground_video );
85+ backGroundVideo = view .findViewById (R .id .background_video );
7686 cloudGameMode = view .findViewById (R .id .cloudGameMode );
7787 publish .setEnabled (false );
78- view .findViewById (R .id .btn_join ).setOnClickListener (this );
79- view .findViewById (R .id .btn_publish ).setOnClickListener (this );
80- view .findViewById (R .id .foreground_video ).setOnClickListener (this );
81- foreGroundVideo = view .findViewById (R .id .background_video );
82- backGroundVideo = view .findViewById (R .id .foreground_video );
88+ publish .setOnClickListener (this );
89+ join .setOnClickListener (this );
90+ foreGroundVideo .setOnClickListener (this );
91+ backGroundVideo .setOnClickListener (this );
8392 }
8493
8594 @ Override
@@ -90,7 +99,7 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
9099 @ Override
91100 public void onDestroy () {
92101 super .onDestroy ();
93- /** leaveChannel and Destroy the RtcEngine instance*/
102+ /*leaveChannel and Destroy the RtcEngine instance*/
94103 if (engine != null ) {
95104 engine .leaveChannel ();
96105 }
@@ -127,15 +136,14 @@ public void onClick(View v) {
127136 engine = RtcEngine .create (rtcEngineConfig );
128137 if (cloudGameMode .isChecked ()){
129138 engine .disableAudio ();
130- }
131- else {
139+ } else {
132140 engine .enableAudio ();
133141 }
134142 } catch (Exception e ) {
143+ requireActivity ().onBackPressed ();
135144 e .printStackTrace ();
136- getActivity ().onBackPressed ();
137145 }
138- CommonUtil .hideInputBoard (getActivity (), et_channel );
146+ CommonUtil .hideInputBoard (requireActivity (), et_channel );
139147 // call when join button hit
140148 String channelId = et_channel .getText ().toString ();
141149 // Check permission
@@ -188,45 +196,54 @@ public void onClick(View v) {
188196 publish .setEnabled (false );
189197 publish .setText (isHost ? getString (R .string .disnable_publish ) : getString (R .string .enable_publish ));
190198
191- } else if (v .getId () == R .id .foreground_video ) {
199+ } else if (v .getId () == R .id .foreground_video || v . getId () == R . id . background_video ) {
192200 isLocalVideoForeground = !isLocalVideoForeground ;
193- if (foreGroundVideo .getChildCount () > 0 ) {
194- foreGroundVideo .removeAllViews ();
195- }
196- if (backGroundVideo .getChildCount () > 0 ) {
197- backGroundVideo .removeAllViews ();
198- }
199- // Create render view by RtcEngine
200- SurfaceView localView = new SurfaceView (getContext ());
201- SurfaceView remoteView = new SurfaceView (getContext ());
202- if (isLocalVideoForeground ){
203- // Add to the local container
204- foreGroundVideo .addView (localView , new FrameLayout .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT ));
205- // Add to the remote container
206- backGroundVideo .addView (remoteView , new FrameLayout .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT ));
207- // Setup remote video to render
208- engine .setupRemoteVideo (new VideoCanvas (remoteView , RENDER_MODE_HIDDEN , remoteUid ));
209- // Setup local video to render your local camera preview
210- engine .setupLocalVideo (new VideoCanvas (localView , RENDER_MODE_HIDDEN , 0 ));
211- engine .startPreview ();
212- remoteView .setZOrderMediaOverlay (true );
213- remoteView .setZOrderOnTop (true );
214- }
215- else {
216- // Add to the local container
217- foreGroundVideo .addView (remoteView , new FrameLayout .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT ));
218- // Add to the remote container
219- backGroundVideo .addView (localView , new FrameLayout .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT ));
220- // Setup local video to render your local camera preview
221- engine .setupLocalVideo (new VideoCanvas (localView , RENDER_MODE_HIDDEN , 0 ));
222- engine .startPreview ();
223- // Setup remote video to render
224- engine .setupRemoteVideo (new VideoCanvas (remoteView , RENDER_MODE_HIDDEN , remoteUid ));
225- localView .setZOrderMediaOverlay (true );
226- localView .setZOrderOnTop (true );
227- }
201+ switchPreview ();
202+ }
203+
204+ }
205+
206+ /**
207+ * Total 3 steps
208+ * Step 1: remove all view
209+ * Step 2: config and add new view
210+ * Step 3: setup engine
211+ */
212+ private void switchPreview () {
213+ // Step 1
214+ if (foreGroundVideo .getChildCount () > 0 ) {
215+ foreGroundVideo .removeAllViews ();
216+ }
217+ if (backGroundVideo .getChildCount () > 0 ) {
218+ backGroundVideo .removeAllViews ();
228219 }
229220
221+ // Step 2
222+ // Create render view by RtcEngine
223+ SurfaceView localView = new SurfaceView (getContext ());
224+ SurfaceView remoteView = new SurfaceView (getContext ());
225+ if (isLocalVideoForeground ){
226+ // Add to the local container
227+ foreGroundVideo .addView (localView , new FrameLayout .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT ));
228+ // Add to the remote container
229+ backGroundVideo .addView (remoteView , new FrameLayout .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT ));
230+ localView .setZOrderMediaOverlay (true );
231+ }
232+ else {
233+ // Add to the local container
234+ foreGroundVideo .addView (remoteView , new FrameLayout .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT ));
235+ // Add to the remote container
236+ backGroundVideo .addView (localView , new FrameLayout .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT ));
237+ remoteView .setZOrderMediaOverlay (true );
238+ }
239+
240+ // Step 3
241+
242+ // Setup remote video to render
243+ engine .setupRemoteVideo (new VideoCanvas (remoteView , RENDER_MODE_HIDDEN , remoteUid ));
244+ // Setup local video to render your local camera preview
245+ engine .setupLocalVideo (new VideoCanvas (localView , RENDER_MODE_HIDDEN , 0 ));
246+ engine .startPreview ();
230247 }
231248
232249 private void joinChannel (String channelId ) {
@@ -238,11 +255,17 @@ private void joinChannel(String channelId) {
238255
239256 // Create render view by RtcEngine
240257 SurfaceView surfaceView = new SurfaceView (context );
241- if (foreGroundVideo .getChildCount () > 0 ) {
258+
259+ if (backGroundVideo .getChildCount () > 0 )
260+ backGroundVideo .removeAllViews ();
261+ if (foreGroundVideo .getChildCount () > 0 )
242262 foreGroundVideo .removeAllViews ();
243- }
244- // Add to the local container
245- foreGroundVideo .addView (surfaceView , new FrameLayout .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT ));
263+
264+ // Add to the container
265+ if (isLocalVideoForeground )
266+ foreGroundVideo .addView (surfaceView , new FrameLayout .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT ));
267+ else
268+ backGroundVideo .addView (surfaceView , new FrameLayout .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT ));
246269 // Setup local video to render your local camera preview
247270 engine .setupLocalVideo (new VideoCanvas (surfaceView , RENDER_MODE_HIDDEN , 0 ));
248271 engine .startPreview ();
@@ -401,15 +424,17 @@ public void onUserJoined(int uid, int elapsed) {
401424 handler .post (() ->
402425 {
403426 /**Display remote video stream*/
404- SurfaceView surfaceView = null ;
405- if (backGroundVideo .getChildCount () > 0 ) {
406- backGroundVideo .removeAllViews ();
407- }
427+ SurfaceView surfaceView ;
428+
408429 // Create render view by RtcEngine
409430 surfaceView = new SurfaceView (context );
410- surfaceView .setZOrderMediaOverlay (true );
411431 // Add to the remote container
412- backGroundVideo .addView (surfaceView , new FrameLayout .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT ));
432+ if (isLocalVideoForeground ) {
433+ backGroundVideo .addView (surfaceView , new FrameLayout .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT ));
434+ } else {
435+ foreGroundVideo .addView (surfaceView , new FrameLayout .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT ));
436+ surfaceView .setZOrderMediaOverlay (true );
437+ }
413438
414439 // Setup remote video to render
415440 engine .setupRemoteVideo (new VideoCanvas (surfaceView , RENDER_MODE_HIDDEN , remoteUid ));
@@ -430,12 +455,14 @@ public void onUserJoined(int uid, int elapsed) {
430455 public void onUserOffline (int uid , int reason ) {
431456 Log .i (TAG , String .format ("user %d offline! reason:%d" , uid , reason ));
432457 showLongToast (String .format ("user %d offline! reason:%d" , uid , reason ));
458+ if (uid == remoteUid )
433459 handler .post (new Runnable () {
434460 @ Override
435461 public void run () {
436462 /**Clear render view
437463 Note: The video will stay at its last frame, to completely remove it you will need to
438464 remove the SurfaceView from its parent*/
465+ remoteUid = 0 ;
439466 engine .setupRemoteVideo (new VideoCanvas (null , RENDER_MODE_HIDDEN , uid ));
440467 }
441468 });
0 commit comments