Skip to content

Commit bfa68ea

Browse files
author
Xia Ning
committed
make join video basic layout support 1v5 group video call
1 parent c3cc2e7 commit bfa68ea

25 files changed

Lines changed: 258 additions & 76 deletions

Android/APIExample/app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
<application
1212
android:name=".MainApplication"
1313
android:allowBackup="true"
14-
android:icon="@mipmap/ic_launcher"
14+
android:icon="@drawable/icon1024"
1515
android:label="@string/app_name"
16-
android:roundIcon="@mipmap/ic_launcher_round"
16+
android:roundIcon="@drawable/icon1024"
1717
android:supportsRtl="true"
1818
android:theme="@style/AppTheme">
1919

Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/VideoQuickSwitch.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@
3636
import static io.agora.api.example.common.model.Examples.ADVANCED;
3737
import static io.agora.rtc.Constants.REMOTE_VIDEO_STATE_DECODING;
3838
import static io.agora.rtc.video.VideoCanvas.RENDER_MODE_HIDDEN;
39-
import static io.agora.rtc.video.VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_15;
40-
import static io.agora.rtc.video.VideoEncoderConfiguration.ORIENTATION_MODE.ORIENTATION_MODE_ADAPTIVE;
4139
import static io.agora.rtc.video.VideoEncoderConfiguration.STANDARD_BITRATE;
42-
import static io.agora.rtc.video.VideoEncoderConfiguration.VD_640x360;
4340

4441
/**---------------------------------------Important!!!----------------------------------------------
4542
* This example demonstrates how audience can quickly switch channels. The following points need to be noted:
@@ -248,7 +245,7 @@ private final void joinChannel(String channelId)
248245
an audience can only receive streams.*/
249246
engine.setChannelProfile(Constants.CHANNEL_PROFILE_LIVE_BROADCASTING);
250247
/**In the demo, the default is to enter as the broadcaster.*/
251-
engine.setClientRole(IRtcEngineEventHandler.ClientRole.CLIENT_ROLE_AUDIENCE);
248+
engine.setClientRole(IRtcEngineEventHandler.ClientRole.CLIENT_ROLE_BROADCASTER);
252249
// Enable video module
253250
engine.enableVideo();
254251
// Setup video encoding configs

Android/APIExample/app/src/main/java/io/agora/api/example/examples/basic/JoinChannelVideo.java

Lines changed: 100 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,20 @@
1414

1515
import androidx.annotation.NonNull;
1616
import androidx.annotation.Nullable;
17+
import androidx.appcompat.widget.AppCompatTextView;
1718

1819
import com.yanzhenjie.permission.AndPermission;
1920
import com.yanzhenjie.permission.runtime.Permission;
2021

22+
import java.util.HashMap;
23+
import java.util.Map;
24+
import java.util.concurrent.ConcurrentHashMap;
25+
2126
import io.agora.api.example.MainApplication;
2227
import io.agora.api.example.R;
2328
import io.agora.api.example.annotation.Example;
2429
import io.agora.api.example.common.BaseFragment;
30+
import io.agora.api.example.common.model.StatisticsInfo;
2531
import io.agora.api.example.utils.CommonUtil;
2632
import io.agora.rtc.Constants;
2733
import io.agora.rtc.IRtcEngineEventHandler;
@@ -48,12 +54,15 @@ public class JoinChannelVideo extends BaseFragment implements View.OnClickListen
4854
{
4955
private static final String TAG = JoinChannelVideo.class.getSimpleName();
5056

51-
private FrameLayout fl_local, fl_remote;
57+
private FrameLayout fl_local, fl_remote, fl_remote_2, fl_remote_3, fl_remote_4, fl_remote_5;
5258
private Button join;
5359
private EditText et_channel;
54-
private RtcEngine engine;
60+
private io.agora.rtc.RtcEngine engine;
5561
private int myUid;
5662
private boolean joined = false;
63+
private Map<Integer, ViewGroup> remoteViews = new ConcurrentHashMap<Integer, ViewGroup>();
64+
private AppCompatTextView localStats, remoteStats;
65+
private StatisticsInfo statisticsInfo;
5766

5867
@Nullable
5968
@Override
@@ -70,8 +79,25 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
7079
join = view.findViewById(R.id.btn_join);
7180
et_channel = view.findViewById(R.id.et_channel);
7281
view.findViewById(R.id.btn_join).setOnClickListener(this);
73-
fl_local = view.findViewById(R.id.fl_local);
74-
fl_remote = view.findViewById(R.id.fl_remote);
82+
fl_local = view.findViewById(R.id.fl_local_video);
83+
fl_remote = view.findViewById(R.id.fl_remote_video);
84+
fl_remote_2 = view.findViewById(R.id.fl_remote2);
85+
fl_remote_3 = view.findViewById(R.id.fl_remote3);
86+
fl_remote_4 = view.findViewById(R.id.fl_remote4);
87+
fl_remote_5 = view.findViewById(R.id.fl_remote5);
88+
localStats = view.findViewById(R.id.local_stats);
89+
localStats.bringToFront();
90+
remoteStats = view.findViewById(R.id.remote_stats);
91+
remoteStats.bringToFront();
92+
statisticsInfo = new StatisticsInfo();
93+
}
94+
95+
private void updateLocalStats(){
96+
localStats.setText(statisticsInfo.getLocalVideoStats());
97+
}
98+
99+
private void updateRemoteStats(){
100+
remoteStats.setText(statisticsInfo.getRemoteVideoStats());
75101
}
76102

77103
@Override
@@ -391,23 +417,25 @@ public void onUserJoined(int uid, int elapsed)
391417
if (context == null) {
392418
return;
393419
}
394-
handler.post(() ->
395-
{
396-
/**Display remote video stream*/
397-
SurfaceView surfaceView = null;
398-
if (fl_remote.getChildCount() > 0)
420+
if(remoteViews.containsKey(uid)){
421+
return;
422+
}
423+
else{
424+
handler.post(() ->
399425
{
400-
fl_remote.removeAllViews();
401-
}
402-
// Create render view by RtcEngine
403-
surfaceView = RtcEngine.CreateRendererView(context);
404-
surfaceView.setZOrderMediaOverlay(true);
405-
// Add to the remote container
406-
fl_remote.addView(surfaceView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
407-
408-
// Setup remote video to render
409-
engine.setupRemoteVideo(new VideoCanvas(surfaceView, RENDER_MODE_HIDDEN, uid));
410-
});
426+
/**Display remote video stream*/
427+
SurfaceView surfaceView = null;
428+
// Create render view by RtcEngine
429+
surfaceView = RtcEngine.CreateRendererView(context);
430+
surfaceView.setZOrderMediaOverlay(true);
431+
ViewGroup view = getAvailableView();
432+
remoteViews.put(uid, view);
433+
// Add to the remote container
434+
view.addView(surfaceView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
435+
// Setup remote video to render
436+
engine.setupRemoteVideo(new VideoCanvas(surfaceView, RENDER_MODE_HIDDEN, uid));
437+
});
438+
}
411439
}
412440

413441
/**Occurs when a remote user (Communication)/host (Live Broadcast) leaves the channel.
@@ -432,8 +460,60 @@ public void run() {
432460
Note: The video will stay at its last frame, to completely remove it you will need to
433461
remove the SurfaceView from its parent*/
434462
engine.setupRemoteVideo(new VideoCanvas(null, RENDER_MODE_HIDDEN, uid));
463+
remoteViews.get(uid).removeAllViews();
464+
remoteViews.remove(uid);
435465
}
436466
});
437467
}
468+
469+
@Override
470+
public void onRemoteAudioStats(io.agora.rtc.IRtcEngineEventHandler.RemoteAudioStats remoteAudioStats) {
471+
statisticsInfo.setRemoteAudioStats(remoteAudioStats);
472+
updateRemoteStats();
473+
}
474+
475+
@Override
476+
public void onLocalAudioStats(io.agora.rtc.IRtcEngineEventHandler.LocalAudioStats localAudioStats) {
477+
statisticsInfo.setLocalAudioStats(localAudioStats);
478+
updateLocalStats();
479+
}
480+
481+
@Override
482+
public void onRemoteVideoStats(io.agora.rtc.IRtcEngineEventHandler.RemoteVideoStats remoteVideoStats) {
483+
statisticsInfo.setRemoteVideoStats(remoteVideoStats);
484+
updateRemoteStats();
485+
}
486+
487+
@Override
488+
public void onLocalVideoStats(io.agora.rtc.IRtcEngineEventHandler.LocalVideoStats localVideoStats) {
489+
statisticsInfo.setLocalVideoStats(localVideoStats);
490+
updateLocalStats();
491+
}
492+
493+
@Override
494+
public void onRtcStats(io.agora.rtc.IRtcEngineEventHandler.RtcStats rtcStats) {
495+
statisticsInfo.setRtcStats(rtcStats);
496+
}
438497
};
498+
499+
private ViewGroup getAvailableView() {
500+
if(fl_remote.getChildCount() == 0){
501+
return fl_remote;
502+
}
503+
else if(fl_remote_2.getChildCount() == 0){
504+
return fl_remote_2;
505+
}
506+
else if(fl_remote_3.getChildCount() == 0){
507+
return fl_remote_3;
508+
}
509+
else if(fl_remote_4.getChildCount() == 0){
510+
return fl_remote_4;
511+
}
512+
else if(fl_remote_5.getChildCount() == 0){
513+
return fl_remote_5;
514+
}
515+
else{
516+
return fl_remote;
517+
}
518+
}
439519
}
408 KB
Loading

Android/APIExample/app/src/main/res/layout/fragment_joinchannel_video.xml

Lines changed: 96 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,105 @@
66
android:fitsSystemWindows="true"
77
tools:context=".examples.basic.JoinChannelVideo">
88

9-
<FrameLayout
10-
android:id="@+id/fl_local"
9+
10+
<LinearLayout
11+
android:id="@+id/video_container"
1112
android:layout_width="match_parent"
1213
android:layout_height="match_parent"
13-
android:layout_above="@+id/ll_join" />
14-
15-
<FrameLayout
16-
android:id="@+id/fl_remote"
17-
android:layout_width="150dp"
18-
android:layout_height="200dp"
1914
android:layout_alignParentTop="true"
20-
android:layout_alignParentEnd="true" />
15+
android:layout_marginBottom="50dp"
16+
android:orientation="vertical">
17+
<LinearLayout
18+
android:id="@+id/video_container_row1"
19+
android:layout_width="match_parent"
20+
android:layout_height="0dp"
21+
android:layout_weight="0.5"
22+
android:orientation="horizontal">
23+
24+
<FrameLayout
25+
android:id="@+id/fl_local"
26+
android:layout_width="0dp"
27+
android:layout_weight="0.34"
28+
android:layout_height="match_parent">
29+
<FrameLayout
30+
android:id="@+id/fl_local_video"
31+
android:layout_width="match_parent"
32+
android:layout_height="match_parent"
33+
/>
34+
<TextView
35+
android:id="@+id/local_stats"
36+
android:layout_width="match_parent"
37+
android:layout_height="wrap_content"
38+
android:layout_marginStart="16dp"
39+
android:layout_marginTop="16dp"
40+
android:maxLines="9"
41+
android:text="Local Video Stats"
42+
android:textColor="#FFFFFF" />
43+
</FrameLayout>
44+
45+
<FrameLayout
46+
android:id="@+id/fl_remote"
47+
android:layout_width="0dp"
48+
android:layout_weight="0.34"
49+
android:layout_height="match_parent">
50+
<FrameLayout
51+
android:id="@+id/fl_remote_video"
52+
android:layout_width="match_parent"
53+
android:layout_height="match_parent"
54+
/>
55+
<TextView
56+
android:id="@+id/remote_stats"
57+
android:layout_width="match_parent"
58+
android:layout_height="wrap_content"
59+
android:layout_marginStart="16dp"
60+
android:layout_marginTop="16dp"
61+
android:maxLines="9"
62+
android:text="Remote Video Stats"
63+
android:textColor="#FFFFFF" />
64+
</FrameLayout>
65+
66+
</LinearLayout>
67+
<LinearLayout
68+
android:id="@+id/video_container_row2"
69+
android:layout_width="match_parent"
70+
android:layout_height="0dp"
71+
android:layout_weight="0.5"
72+
android:orientation="horizontal">
73+
74+
<FrameLayout
75+
android:id="@+id/fl_remote2"
76+
android:layout_width="0dp"
77+
android:layout_weight="0.33"
78+
android:layout_height="match_parent"/>
79+
80+
<FrameLayout
81+
android:id="@+id/fl_remote3"
82+
android:layout_width="0dp"
83+
android:layout_weight="0.33"
84+
android:layout_height="match_parent" />
85+
86+
</LinearLayout>
87+
<LinearLayout
88+
android:id="@+id/video_container_row3"
89+
android:layout_width="match_parent"
90+
android:layout_height="0dp"
91+
android:layout_weight="0.5"
92+
android:orientation="horizontal">
93+
94+
<FrameLayout
95+
android:id="@+id/fl_remote4"
96+
android:layout_width="0dp"
97+
android:layout_weight="0.33"
98+
android:layout_height="match_parent"/>
99+
100+
<FrameLayout
101+
android:id="@+id/fl_remote5"
102+
android:layout_width="0dp"
103+
android:layout_weight="0.33"
104+
android:layout_height="match_parent" />
105+
106+
</LinearLayout>
107+
</LinearLayout>
21108

22109
<LinearLayout
23110
android:id="@+id/ll_join"

0 commit comments

Comments
 (0)