如何在视频通话中检查远程用户或用户互联网是否断开连接

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

我正在制作视频通话应用。我想像 whatsapp 一样重新连接场景,即如果用户或远程用户互联网在等待 10-15 秒后断开连接,两者的呼叫都应该结束。这是我的代码:

  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);
    }
};

如有任何帮助,我们将不胜感激。在上面的代码中有一个问题,我在 onUserOffline 方法中使用了一个处理程序,它将在用户离线 10 秒后结束调用,但是如果用户在 10 秒内重新连接,处理程序仍然有效并且调用在 10 秒后结束。

我更希望您使用 CountDownTimer,而不是使用处理程序。在此,您也可以在中间停止它。您可以参考以下代码:

//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();