55import android .content .Context ;
66import android .os .Bundle ;
77import android .os .Handler ;
8+ import android .text .TextUtils ;
89import android .util .Log ;
910import android .view .LayoutInflater ;
1011import android .view .View ;
@@ -51,7 +52,7 @@ public class JoinChannelAudioByToken extends BaseFragment implements View.OnClic
5152 private static final String TAG = JoinChannelAudioByToken .class .getSimpleName ();
5253 private Spinner audioProfileInput ;
5354 private Spinner audioScenarioInput ;
54- private EditText et_channel , et_token ;
55+ private EditText et_app_id , et_channel , et_token ;
5556 private Button mute , join , speaker ;
5657 private SeekBar record , playout , inear ;
5758 private Switch inEarSwitch ;
@@ -63,6 +64,9 @@ public class JoinChannelAudioByToken extends BaseFragment implements View.OnClic
6364 private SeekBar .OnSeekBarChangeListener seekBarChangeListener = new SeekBar .OnSeekBarChangeListener () {
6465 @ Override
6566 public void onProgressChanged (SeekBar seekBar , int progress , boolean fromUser ) {
67+ if (engine == null ){
68+ return ;
69+ }
6670 if (seekBar .getId () == record .getId ()){
6771 engine .adjustRecordingSignalVolume (progress );
6872 }
@@ -111,6 +115,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
111115 {
112116 super .onViewCreated (view , savedInstanceState );
113117 join = view .findViewById (R .id .btn_join );
118+ et_app_id = view .findViewById (R .id .et_app_id );
114119 et_channel = view .findViewById (R .id .et_channel );
115120 et_token = view .findViewById (R .id .et_token );
116121 audioProfileInput = view .findViewById (R .id .audio_profile_spinner );
@@ -143,6 +148,9 @@ record = view.findViewById(R.id.recordingVol);
143148 inear .setOnSeekBarChangeListener (seekBarChangeListener );
144149 inEarSwitch = view .findViewById (R .id .inEarMonitorSwitch );
145150 inEarSwitch .setOnCheckedChangeListener ((buttonView , isChecked ) -> {
151+ if (engine == null ){
152+ return ;
153+ }
146154 engine .enableInEarMonitoring (isChecked );
147155 inear .setEnabled (isChecked );
148156 });
@@ -161,27 +169,18 @@ record = view.findViewById(R.id.recordingVol);
161169 );
162170 }
163171
164- @ Override
165- public void onActivityCreated (@ Nullable Bundle savedInstanceState )
166- {
167- super .onActivityCreated (savedInstanceState );
168- // Check if the context is valid
169- Context context = getContext ();
170- if (context == null )
171- {
172- return ;
173- }
172+ private boolean createRtcEngine (String appId ) {
174173 try
175174 {
176175 RtcEngineConfig config = new RtcEngineConfig ();
177176 /**
178177 * The context of Android Activity
179178 */
180- config .mContext = context .getApplicationContext ();
179+ config .mContext = requireContext () .getApplicationContext ();
181180 /**
182181 * The App ID issued to you by Agora. See <a href="https://docs.agora.io/en/Agora%20Platform/token#get-an-app-id"> How to get the App ID</a>
183182 */
184- config .mAppId = getString ( R . string . agora_app_id ) ;
183+ config .mAppId = appId ;
185184 /** Sets the channel profile of the Agora RtcEngine.
186185 CHANNEL_PROFILE_COMMUNICATION(0): (Default) The Communication profile.
187186 Use this profile in one-on-one calls or group calls, where all users can talk freely.
@@ -211,25 +210,32 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState)
211210 + "}" );
212211 /* setting the local access point if the private cloud ip was set, otherwise the config will be invalid.*/
213212 engine .setLocalAccessPoint (((MainApplication ) getActivity ().getApplication ()).getGlobalSettings ().getPrivateCloudConfig ());
213+
214+ return true ;
214215 }
215216 catch (Exception e )
216217 {
217- e .printStackTrace ();
218- getActivity ().onBackPressed ();
218+ showAlert (e .getMessage ());
219219 }
220+
221+ return false ;
220222 }
221223
222- @ Override
223- public void onDestroy ()
224- {
225- super .onDestroy ();
224+ private void destroyRtcEngine (){
226225 /**leaveChannel and Destroy the RtcEngine instance*/
227226 if (engine != null )
228227 {
229228 engine .leaveChannel ();
229+ RtcEngine .destroy ();
230+ engine = null ;
230231 }
231- handler .post (RtcEngine ::destroy );
232- engine = null ;
232+ }
233+
234+ @ Override
235+ public void onDestroy ()
236+ {
237+ super .onDestroy ();
238+ destroyRtcEngine ();
233239 }
234240
235241 @ Override
@@ -241,47 +247,23 @@ public void onClick(View v)
241247 {
242248 CommonUtil .hideInputBoard (getActivity (), et_channel );
243249 // call when join button hit
250+ String appId = et_app_id .getText ().toString ();
244251 String channelId = et_channel .getText ().toString ();
245252 String token = et_token .getText ().toString ();
246- // Check permission
247- if (AndPermission .hasPermissions (this , Permission .Group .STORAGE , Permission .Group .MICROPHONE , Permission .Group .CAMERA ))
248- {
249- joinChannel (channelId , token );
250- audioProfileInput .setEnabled (false );
253+
254+ if (TextUtils .isEmpty (appId )){
255+ showLongToast (getString (R .string .app_id_empty ));
251256 return ;
252257 }
253- // Request permission
254- AndPermission .with (this ).runtime ().permission (
255- Permission .Group .STORAGE ,
256- Permission .Group .MICROPHONE
257- ).onGranted (permissions ->
258- {
259- // Permissions Granted
258+
259+ if (createRtcEngine (appId )) {
260260 joinChannel (channelId , token );
261261 audioProfileInput .setEnabled (false );
262- }). start ();
262+ }
263263 }
264264 else
265265 {
266266 joined = false ;
267- /**After joining a channel, the user must call the leaveChannel method to end the
268- * call before joining another channel. This method returns 0 if the user leaves the
269- * channel and releases all resources related to the call. This method call is
270- * asynchronous, and the user has not exited the channel when the method call returns.
271- * Once the user leaves the channel, the SDK triggers the onLeaveChannel callback.
272- * A successful leaveChannel method call triggers the following callbacks:
273- * 1:The local client: onLeaveChannel.
274- * 2:The remote client: onUserOffline, if the user leaving the channel is in the
275- * Communication channel, or is a BROADCASTER in the Live Broadcast profile.
276- * @returns 0: Success.
277- * < 0: Failure.
278- * PS:
279- * 1:If you call the destroy method immediately after calling the leaveChannel
280- * method, the leaveChannel process interrupts, and the SDK does not trigger
281- * the onLeaveChannel callback.
282- * 2:If you call the leaveChannel method during CDN live streaming, the SDK
283- * triggers the removeInjectStreamUrl method.*/
284- engine .leaveChannel ();
285267 join .setText (getString (R .string .join ));
286268 speaker .setText (getString (R .string .speaker ));
287269 speaker .setEnabled (false );
@@ -294,17 +276,24 @@ public void onClick(View v)
294276 inEarSwitch .setEnabled (false );
295277 inEarSwitch .setChecked (false );
296278 audioSeatManager .downAllSeats ();
279+ destroyRtcEngine ();
297280 }
298281 }
299282 else if (v .getId () == R .id .microphone )
300283 {
284+ if (engine == null ){
285+ return ;
286+ }
301287 mute .setActivated (!mute .isActivated ());
302288 mute .setText (getString (mute .isActivated () ? R .string .openmicrophone : R .string .closemicrophone ));
303289 /**Turn off / on the microphone, stop / start local audio collection and push streaming.*/
304290 engine .muteLocalAudioStream (mute .isActivated ());
305291 }
306292 else if (v .getId () == R .id .btn_speaker )
307293 {
294+ if (engine == null ){
295+ return ;
296+ }
308297 speaker .setActivated (!speaker .isActivated ());
309298 speaker .setText (getString (speaker .isActivated () ? R .string .speaker : R .string .earpiece ));
310299 /**Turn off / on the speaker and change the audio playback route.*/
0 commit comments