44import android .content .Context ;
55import android .os .Bundle ;
66import android .os .Handler ;
7+ import android .os .Looper ;
78import android .os .Message ;
89import android .util .Log ;
910import android .view .LayoutInflater ;
11+ import android .view .SurfaceView ;
1012import android .view .View ;
1113import android .view .ViewGroup ;
1214import android .widget .Button ;
15+ import android .widget .FrameLayout ;
1316import android .widget .TextView ;
1417import android .widget .Toast ;
1518
2831import io .agora .rtc .IRtcEngineEventHandler ;
2932import io .agora .rtc .RtcEngine ;
3033import io .agora .rtc .internal .LastmileProbeConfig ;
34+ import io .agora .rtc .models .EchoTestConfiguration ;
3135
3236import static io .agora .api .example .common .model .Examples .ADVANCED ;
3337
@@ -43,18 +47,18 @@ public class PreCallTest extends BaseFragment implements View.OnClickListener {
4347
4448 private RtcEngine engine ;
4549 private int myUid ;
46- private Button btn_lastmile , btn_echo ;
50+ private Button btn_lastmile , btn_echo , btn_echoVideo ;
51+ private FrameLayout preview ;
4752 private StatisticsInfo statisticsInfo ;
4853 private TextView lastmileQuality , lastmileResult ;
4954 private static final Integer MAX_COUNT_DOWN = 8 ;
5055 private int num ;
51- private Timer timer ;
52- private TimerTask task ;
56+ private boolean echoTesting = false ;
57+ private Thread countDownThread ;
5358
5459 @ Override
5560 public void onCreate (@ Nullable Bundle savedInstanceState ) {
5661 super .onCreate (savedInstanceState );
57- handler = new Handler ();
5862 }
5963
6064 @ Nullable
@@ -81,8 +85,7 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
8185 * The SDK uses this class to report to the app on SDK runtime events.*/
8286 String appId = getString (R .string .agora_app_id );
8387 engine = RtcEngine .create (getContext ().getApplicationContext (), appId , iRtcEngineEventHandler );
84- }
85- catch (Exception e ) {
88+ } catch (Exception e ) {
8689 e .printStackTrace ();
8790 getActivity ().onBackPressed ();
8891 }
@@ -94,40 +97,23 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
9497 statisticsInfo = new StatisticsInfo ();
9598 btn_echo = view .findViewById (R .id .btn_echo );
9699 btn_echo .setOnClickListener (this );
100+ btn_echoVideo = view .findViewById (R .id .btn_echoVideoTest );
101+ btn_echoVideo .setOnClickListener (this );
97102 btn_lastmile = view .findViewById (R .id .btn_lastmile );
98103 btn_lastmile .setOnClickListener (this );
99104 lastmileQuality = view .findViewById (R .id .lastmile_quality );
100105 lastmileResult = view .findViewById (R .id .lastmile_result );
101- task = new TimerTask (){
102- public void run () {
103- num ++;
104- if (num >= MAX_COUNT_DOWN * 2 ){
105- handler .post (() -> {
106- btn_echo .setEnabled (true );
107- btn_echo .setText ("Start" );
108- });
109- engine .stopEchoTest ();
110- timer .cancel ();
111- task .cancel ();
112- }
113- else if (num >= MAX_COUNT_DOWN ) {
114- handler .post (() -> btn_echo .setText ("PLaying with " + (MAX_COUNT_DOWN * 2 - num ) + "Seconds" ));
115- }
116- else {
117- handler .post (() -> btn_echo .setText ("Recording with " + (MAX_COUNT_DOWN - num ) + "Seconds" ));
118- }
119- }
120- };
106+ preview = view .findViewById (R .id .echoTestView );
121107 }
122108
123109 @ Override
124110 public void onClick (View v ) {
125- if (v .getId () == R .id .btn_lastmile )
126- {
111+ if (v .getId () == R .id .btn_lastmile ) {
127112 // Configure a LastmileProbeConfig instance.
128- LastmileProbeConfig config = new LastmileProbeConfig (){};
113+ LastmileProbeConfig config = new LastmileProbeConfig () {
114+ };
129115 // Probe the uplink network quality.
130- config .probeUplink = true ;
116+ config .probeUplink = true ;
131117 // Probe the downlink network quality.
132118 config .probeDownlink = true ;
133119 // The expected uplink bitrate (bps). The value range is [100000, 5000000].
@@ -138,14 +124,34 @@ public void onClick(View v) {
138124 engine .startLastmileProbeTest (config );
139125 btn_lastmile .setEnabled (false );
140126 btn_lastmile .setText ("Testing ..." );
141- }
142- else if (v .getId () == R .id .btn_echo ){
127+ } else if (v .getId () == R .id .btn_echo ) {
143128 num = 0 ;
144129 engine .startEchoTest (MAX_COUNT_DOWN );
145130 btn_echo .setEnabled (false );
146- btn_echo .setText ("Recording on Microphone ..." );
147- timer = new Timer (true );
148- timer .schedule (task , 1000 , 1000 );
131+ btn_echo .setText (R .string .recording_start );
132+ countDownThread = new Thread (new CountDownTask ());
133+ countDownThread .start ();
134+ } else if (v .getId () == R .id .btn_echoVideoTest ) {
135+ if (!echoTesting ) {
136+ SurfaceView surfaceView = RtcEngine .CreateRendererView (getContext ());
137+ // Add to the local container
138+ preview .addView (surfaceView , new FrameLayout .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT ));
139+ EchoTestConfiguration config = new EchoTestConfiguration ();
140+ config .enableAudio = true ;
141+ config .enableVideo = true ;
142+ config .channelId = "randomChannel" ;
143+ config .view = surfaceView ;
144+ engine .startEchoTest (config );
145+ echoTesting = true ;
146+ btn_echoVideo .setText (getText (R .string .stop_echo_video_audio_test ));
147+ } else {
148+ engine .stopEchoTest ();
149+ if (preview .getChildCount () > 0 ) {
150+ preview .removeAllViews ();
151+ }
152+ echoTesting = false ;
153+ btn_echoVideo .setText (getText (R .string .start_echo_video_audio_test ));
154+ }
149155 }
150156 }
151157
@@ -263,7 +269,7 @@ public void onUserOffline(int uid, int reason) {
263269 * @param quality
264270 */
265271 @ Override
266- public void onLastmileQuality (int quality ){
272+ public void onLastmileQuality (int quality ) {
267273 statisticsInfo .setLastMileQuality (quality );
268274 updateLastMileResult ();
269275 }
@@ -281,20 +287,80 @@ public void onLastmileProbeResult(LastmileProbeResult lastmileProbeResult) {
281287 updateLastMileResult ();
282288 handler .post (() -> {
283289 btn_lastmile .setEnabled (true );
284- btn_lastmile .setText ("Start" );
290+ btn_lastmile .setText (getString ( R . string . start ) );
285291 });
286292 }
287293 };
288294
289295 private void updateLastMileResult () {
290296 handler .post (() -> {
291- if (statisticsInfo .getLastMileQuality () != null ){
297+ if (statisticsInfo .getLastMileQuality () != null ) {
292298 lastmileQuality .setText ("Quality: " + statisticsInfo .getLastMileQuality ());
293299 }
294- if (statisticsInfo .getLastMileResult () != null ){
300+ if (statisticsInfo .getLastMileResult () != null ) {
295301 lastmileResult .setText (statisticsInfo .getLastMileResult ());
296302 }
297303 });
298304 }
299305
300- }
306+
307+ @ Override
308+ public void onDestroy () {
309+ /**leaveChannel and Destroy the RtcEngine instance*/
310+ if (engine != null ) {
311+ /**After joining a channel, the user must call the leaveChannel method to end the
312+ * call before joining another channel. This method returns 0 if the user leaves the
313+ * channel and releases all resources related to the call. This method call is
314+ * asynchronous, and the user has not exited the channel when the method call returns.
315+ * Once the user leaves the channel, the SDK triggers the onLeaveChannel callback.
316+ * A successful leaveChannel method call triggers the following callbacks:
317+ * 1:The local client: onLeaveChannel.
318+ * 2:The remote client: onUserOffline, if the user leaving the channel is in the
319+ * Communication channel, or is a BROADCASTER in the Live Broadcast profile.
320+ * @returns 0: Success.
321+ * < 0: Failure.
322+ * PS:
323+ * 1:If you call the destroy method immediately after calling the leaveChannel
324+ * method, the leaveChannel process interrupts, and the SDK does not trigger
325+ * the onLeaveChannel callback.
326+ * 2:If you call the leaveChannel method during CDN live streaming, the SDK
327+ * triggers the removeInjectStreamUrl method.*/
328+ engine .leaveChannel ();
329+ }
330+ handler .post (RtcEngine ::destroy );
331+ engine = null ;
332+ super .onDestroy ();
333+ }
334+
335+ class CountDownTask implements Runnable {
336+
337+ private void updateCountDown () {
338+ if (num > MAX_COUNT_DOWN * 2 )
339+ return ;
340+ try {
341+ Thread .sleep (1000 );
342+ } catch (InterruptedException e ) {
343+ e .printStackTrace ();
344+ }
345+ if (num == MAX_COUNT_DOWN * 2 ) {
346+ handler .post (() -> {
347+ btn_echo .setText (getString (R .string .start_echo_audio_test ));
348+ btn_echo .setEnabled (true );
349+ });
350+ engine .stopEchoTest ();
351+ } else if (num >= MAX_COUNT_DOWN ) {
352+ handler .post (() -> btn_echo .setText (getString (R .string .echo_playing_countdown ) + " " + (MAX_COUNT_DOWN * 2 - num + 1 )));
353+ } else {
354+ handler .post (() -> btn_echo .setText (getString (R .string .echo_record_countdown ) + " " + (MAX_COUNT_DOWN - num + 1 )));
355+ }
356+ num ++;
357+ updateCountDown ();
358+ }
359+
360+ @ Override
361+ public void run () {
362+ updateCountDown ();
363+ }
364+ }
365+
366+ }
0 commit comments