Search code examples
javaandroidandroid-studioagora.io

How to check if remote user or user internet disconnects or not in video call


I am making a video call app. I want to make a reconnection scenario just like whatsapp i.e. if the user or remote user internet disconnects after waiting for 10-15 seconds call should end for both. here is my code:

  private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {
    @Override
    public void onJoinChannelSuccess(String channel, final int uid, int elapsed) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (AppSharedPreferences.getUser(context).getUserTypeId() == 2) {
                    updateDoctorStatus("3");
                }
                Log.e("Agora", "Join channel success, uid: " + (uid & 0xFFFFFFFFL));
            }
        });
    }

    @Override
    public void onFirstRemoteVideoDecoded(final int uid, int width, int height, int elapsed) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.e("Agora", "First remote video decoded, uid: " + (uid & 0xFFFFFFFFL));
                reconnectingView.setVisibility(View.GONE);
                timerRunning = true;
                appointmentStarted = true;
                if (reconnecting) {
                    timeLeftInMillis = AppSharedPreferences.getCallTimer(VideoChatViewActivity.this);
                    countDownTimer.cancel();
                }
                callingView.setVisibility(View.GONE);
                handler.removeCallbacks(runnableCode);
                callHandler.removeCallbacks(runnableforCalling);
                startMeeting();
                updateAppointmentStatus();
                setupRemoteVideo(uid);
            }
        });
    }

    @Override
    public void onUserOffline(final int uid, final int reason) {
        Log.e("Agora", "User offline, reason: " + reason);
        ConnectivityManager cm = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo nInfo = cm.getActiveNetworkInfo();
        boolean connected = nInfo != null && nInfo.isAvailable() && nInfo.isConnected();
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.e("Agora", "User offline, uid: " + (uid & 0xFFFFFFFFL));
                if (reason == 0) {
                    onRemoteUserLeft();
                    endCall();
                } else {
                    timerRunning = false;
                    reconnecting = true;
                    reconnectingView.setVisibility(View.VISIBLE);
                    reconnectingText.setText("Reconnecting....");
                    Toast.makeText(VideoChatViewActivity.this, "Doctor internet disconnected", Toast.LENGTH_LONG).show();
                    reconnectingHandler.postDelayed(() -> {
                        if (reconnecting) {
                            onRemoteUserLeft();
                            endCall();
                        }
                    }, 10000);
                }
            }
        });
    }

    @Override
    public void onUserMuteVideo(final int uid, final boolean muted) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.e("Agora", "User Muted, uid: " + (uid & 0xFFFFFFFFL));
                Log.e("Agora", "User Muted,: " + muted);
                if (muted)
                    remote_off.setVisibility(View.VISIBLE);
                else
                    remote_off.setVisibility(View.GONE);
            }
        });
    }

    @Override
    public void onRejoinChannelSuccess(String channel, int uid, int elapsed) {
        super.onRejoinChannelSuccess(channel, uid, elapsed);
        reconnecting = false;
        
        Toast.makeText(VideoChatViewActivity.this, "Reconnected", Toast.LENGTH_LONG).show();
    }

    @Override
    public void onNetworkQuality(int uid, final int txQuality, final int rxQuality) {
        runOnUiThread(() -> {
            // Log.e("Quality", rxQuality + "");
            if (rxQuality == Quality.VBAD) {
                signals.setImageDrawable(getResources().getDrawable(R.drawable.signal1));
            }
            if (rxQuality == Quality.BAD) {
                signals.setImageDrawable(getResources().getDrawable(R.drawable.signal2));
            }
            if (rxQuality == Quality.POOR) {
                signals.setImageDrawable(getResources().getDrawable(R.drawable.signal3));
            }
            if (rxQuality == Quality.GOOD) {
                signals.setImageDrawable(getResources().getDrawable(R.drawable.signal4));
            }
            if (rxQuality == Quality.EXCELLENT) {
                signals.setImageDrawable(getResources().getDrawable(R.drawable.signal5));
            }
        });
    }

    @Override
    public void onConnectionStateChanged(int state, int reason) {
        Log.d(TAG, "Connection state changes to "
                + state + " reason: " + reason);
    }
};

Any help will be appreciated. In the code above there is a problem, I have used a handler in onUserOffline method which will end call after 10 seconds of user offline, but if the user reconnects within 10 seconds the handler still works and the call ends after 10 seconds.


Solution

  • Instead of using handler, I'd prefer you to use CountDownTimer. In this, you can also stop it in the middle. You can refer the code below:

    //In your class
    CountDownTimer mCountDownTimer;
    
    //when the network goes
    mCountDownTimer = new CountDownTimer((10 * 1000), (1 * 1000)){ // multiple the number of seconds by thousand to get the appropriate results. Here 10 * 1000 = 10000(10 seconds) and 1 * 1000 = 1000(1 second)
       @Override
       public void onTick(long millisInFuture){}
       
       @Override
       public void onFinish(){
          //10 seconds have finished. Drop the call.
       }
    }.start();
    
    //If the internet comes back
    if(mCountDownTimer != null)
       mCountDownTimer.cancel();