使用Android Vidyo SDK跟踪`Vidyo`会议参与者

时间:2017-03-27 21:04:34

标签: java android sdk video-conferencing

我正在使用Vidyo.io服务在我的Android应用中集成视频会议。我已经能够使用VidyoConnector附带的android-vidyo-sdk示例应用成功实施视频会议。 但是,我想获得有关会议室和加入会议室的参与者的更多信息。

我想象的工作流程如下:

  1. User1想要从Android设备进行vidyo电话会议。所以User1将要求,并使用api从我的后端服务器获取新令牌。
  2. 然后,User1将向其他参与者发送邀请,以使用在步骤1中获得的令牌和相应的vidyo会议室resourceId加入电话会议。
  3. 其他参与者将使用从步骤2中的User1获得的信息,并且可以加入会议室。
  4. 到目前为止,我已引用VidyoConnector示例应用,通过对原始VideoChatActivity示例应用VidyoConnector进行一些修改来创建名为MainActivity的活动。 VideoChatActivity将通过Intent从我的应用中的其他活动调用,其中包含启动vidyo连接的所有必要信息,例如令牌,资源ID,用户名等。要跟踪我已实施的每个参与者的状态VidyoConnector.IRegisterParticipantEventListener。请参考下面的代码:

    public class VideoChatActivity extends Activity
            implements VidyoConnector.IConnect,
            VidyoConnector.IRegisterParticipantEventListener {
    
        private enum VIDYO_CONNECTOR_STATE {
            VC_CONNECTED,
            VC_DISCONNECTED,
            VC_DISCONNECTED_UNEXPECTED,
            VC_CONNECTION_FAILURE
        }
    
        private static final String TAG = "VideoChatActivity";
    
        private VIDYO_CONNECTOR_STATE mVidyoConnectorState = VIDYO_CONNECTOR_STATE.VC_DISCONNECTED;
        private boolean mVidyoConnectorConstructed = false;
        private boolean mVidyoClientInitialized = false;
        private VidyoConnector mVidyoConnector = null;
        private ToggleButton mToggleConnectButton;
        private ProgressBar mConnectionSpinner;
        private LinearLayout mToolbarLayout;
        private String mHost;
        private String mDisplayName;
        private String mToken;
        private String mResourceId;
        private TextView mToolbarStatus;
        private FrameLayout mVideoFrame;
        private boolean mAutoJoin = false;
        private boolean mAllowReconnect = true;
        private String mReturnURL = null;
    
    
        /*
         *  Operating System Events
         */
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            Log.d(TAG, "onCreate");
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.activity_video_chat);
    
            // Initialize the member variables
            mToggleConnectButton = (ToggleButton) findViewById(R.id.video_chat_toggleConnectButton);
            mToolbarLayout = (LinearLayout) findViewById(R.id.video_chat_toolbarLayout);
            mVideoFrame = (FrameLayout) findViewById(R.id.video_chat_videoFrame);
            mToolbarStatus = (TextView) findViewById(R.id.video_chat_toolbarStatusText);
            mConnectionSpinner = (ProgressBar) findViewById(R.id.video_chat_connectionSpinner);
    
            // Initialize the VidyoClient
            Connector.SetApplicationUIContext(this);
            mVidyoClientInitialized = Connector.Initialize();
        }
    
        @Override
        protected void onNewIntent(Intent intent) {
            Log.d(TAG, "onNewIntent");
            super.onNewIntent(intent);
    
            // New intent was received so set it to use in onStart()
            setIntent(intent);
        }
    
        @Override
        protected void onStart() {
            Log.d(TAG, "onStart");
            super.onStart();
    
            // If the app was launched by a different app, then get any parameters; otherwise use default settings
            Intent intent = getIntent();
            mHost = intent.hasExtra("host") ? intent.getStringExtra("host") : "prod.vidyo.io";
            mToken = intent.hasExtra("token") ? intent.getStringExtra("token") : "";
            mDisplayName = intent.hasExtra("displayName") ? intent.getStringExtra("displayName") : "";
            mResourceId = intent.hasExtra("resourceId") ? intent.getStringExtra("resourceId") : "";
            mReturnURL = intent.hasExtra("returnURL") ? intent.getStringExtra("returnURL") : null;
            mAutoJoin = intent.getBooleanExtra("autoJoin", false);
            mAllowReconnect = intent.getBooleanExtra("allowReconnect", true);
    
            Log.d(TAG, "onStart: autoJoin = " + mAutoJoin + ", allowReconnect = " + mAllowReconnect);
    
            if (mDisplayName.equals("")) {
                Profile myProfile = getMyProfile();
                if (myProfile != null && myProfile.getDisplayName() != null) {
                    mDisplayName = myProfile.getDisplayName();
                }
            }
    
            // Enable toggle connect button
            mToggleConnectButton.setEnabled(true);
        }
    
        @Override
        protected void onResume() {
            Log.d(TAG, "onResume");
            super.onResume();
            ViewTreeObserver viewTreeObserver = mVideoFrame.getViewTreeObserver();
            if (viewTreeObserver.isAlive()) {
                viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        mVideoFrame.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    
                        // If the vidyo connector was not previously successfully constructed then construct it
    
                        if (!mVidyoConnectorConstructed) {
    
                            if (mVidyoClientInitialized) {
    
    
                                mVidyoConnector = new VidyoConnector(mVideoFrame,
                                                                     VidyoConnector.VidyoConnectorViewStyle.VIDYO_CONNECTORVIEWSTYLE_Default,
                                                                     16,
                                                                     "info@VidyoClient info@VidyoConnector warning",
                                                                     "",
                                                                     0);
    
                                if (mVidyoConnector != null) {
                                    mVidyoConnectorConstructed = true;
                                    // Set initial position
                                    RefreshUI();
                                } else {
                                    Log.d(TAG, "VidyoConnector Construction failed - cannot " +
                                            "connect...");
                                }
                            } else {
                                Log.d(TAG, "ERROR: VidyoClientInitialize failed - not constructing " +
                                        "VidyoConnector ...");
                            }
    
                            Log.d(TAG, "onResume: mVidyoConnectorConstructed => " +
                                    (mVidyoConnectorConstructed ? "success" : "failed"));
                        }
    
                        // If configured to auto-join, then simulate a click of the toggle connect button
                        if (mVidyoConnectorConstructed && mAutoJoin) {
                            mToggleConnectButton.performClick();
                        }
                    }
                });
            }
        }
    
        @Override
        protected void onPause() {
            Log.d(TAG, "onPause");
            super.onPause();
        }
    
        @Override
        protected void onRestart() {
            Log.d(TAG, "onRestart");
            super.onRestart();
            if (mVidyoConnector != null) {
                mVidyoConnector.SetMode(VidyoConnector.VidyoConnectorMode.VIDYO_CONNECTORMODE_Foreground);
            }
        }
    
        @Override
        protected void onStop() {
            Log.d(TAG, "onStop");
            if (mVidyoConnector != null) {
                mVidyoConnector.SetMode(VidyoConnector.VidyoConnectorMode.VIDYO_CONNECTORMODE_Background);
            }
            super.onStop();
        }
    
        @Override
        protected void onDestroy() {
            Log.d(TAG, "onDestroy");
            Connector.Uninitialize();
            super.onDestroy();
        }
    
        /*
         *  Connector Events
         */
    
        // Handle successful connection.
        @Override
        public void OnSuccess() {
            Log.d(TAG, "OnSuccess: connection successful");
            ConnectorStateUpdated(VIDYO_CONNECTOR_STATE.VC_CONNECTED, "Connected");
        }
    
        // Handle attempted connection failure.
        @Override
        public void OnFailure(VidyoConnector.VidyoConnectorFailReason reason) {
            Log.d(TAG, "onFailure: connection failure reason : " + reason.toString());
    
            // Update UI to reflect connection failed
            ConnectorStateUpdated(VIDYO_CONNECTOR_STATE.VC_CONNECTION_FAILURE, "Connection failed");
        }
    
        // Handle an existing session being disconnected.
        @Override
        public void OnDisconnected(VidyoConnector.VidyoConnectorDisconnectReason reason) {
            Log.d(TAG, "OnDisconnected: disconnect reason : " + reason.toString());
            if (reason == VidyoConnector.VidyoConnectorDisconnectReason.VIDYO_CONNECTORDISCONNECTREASON_Disconnected) {
                ConnectorStateUpdated(VIDYO_CONNECTOR_STATE.VC_DISCONNECTED, "Disconnected");
            } else {
                ConnectorStateUpdated(VIDYO_CONNECTOR_STATE.VC_DISCONNECTED_UNEXPECTED, "Unexpected disconnection");
            }
        }
    
        @Override
        public void OnParticipantJoined(final VidyoParticipant vidyoParticipant) {
            Log.d(TAG, "joined participant id : " + vidyoParticipant.GetId());
            Log.d(TAG, "joined participant name : " + vidyoParticipant.GetName());
            Log.d(TAG, "joined participant userId : " + vidyoParticipant.GetUserId());
            Log.d(TAG, "joined participant object ptr : " + vidyoParticipant.GetObjectPtr());
            Log.d(TAG, "joined participant isHidden : " + vidyoParticipant.IsHidden());
            Log.d(TAG, "joined participant isLocal : " + vidyoParticipant.IsLocal());
            Log.d(TAG, "joined participant isRecording : " + vidyoParticipant.IsRecording());
            Log.d(TAG, "joined participant isSelectable : " + vidyoParticipant.IsSelectable());
        }
    
        @Override
        public void OnParticipantLeft(VidyoParticipant vidyoParticipant) {
            Log.d(TAG, "left participant id : " + vidyoParticipant.GetId());
            Log.d(TAG, "left participant name : " + vidyoParticipant.GetName());
            Log.d(TAG, "left participant userId : " + vidyoParticipant.GetUserId());
            Log.d(TAG, "left participant object ptr : " + vidyoParticipant.GetObjectPtr());
            Log.d(TAG, "left participant isHidden : " + vidyoParticipant.IsHidden());
            Log.d(TAG, "left participant isLocal : " + vidyoParticipant.IsLocal());
            Log.d(TAG, "left participant isRecording : " + vidyoParticipant.IsRecording());
            Log.d(TAG, "left participant isSelectable : " + vidyoParticipant.IsSelectable());
        }
    
        @Override
        public void OnDynamicParticipantChanged(ArrayList<VidyoParticipant> arrayList, ArrayList<VidyoRemoteCamera> arrayList1) {
            for (VidyoParticipant participant : arrayList) {
                Log.d(TAG, "Participant : " + participant.GetName());
            }
    
            for (VidyoRemoteCamera remoteCamera : arrayList1) {
                Log.d(TAG, "remote camera : " + remoteCamera.GetName());
            }
        }
    
        @Override
        public void OnLoudestParticipantChanged(VidyoParticipant vidyoParticipant, boolean b) {
            Log.d(TAG, "loudest participant id : " + vidyoParticipant.GetId());
            Log.d(TAG, "loudest participant name : " + vidyoParticipant.GetName());
            Log.d(TAG, "loudest participant userId : " + vidyoParticipant.GetUserId());
            Log.d(TAG, "loudest participant object ptr : " + vidyoParticipant.GetObjectPtr());
            Log.d(TAG, "loudest participant isHidden : " + vidyoParticipant.IsHidden());
            Log.d(TAG, "loudest participant isLocal : " + vidyoParticipant.IsLocal());
            Log.d(TAG, "loudest participant isRecording : " + vidyoParticipant.IsRecording());
            Log.d(TAG, "loudest participant isSelectable : " + vidyoParticipant.IsSelectable());
    
            Log.d(TAG, "boolean : " + b);
        }
    
        /*
         * Private Utility Functions
         */
        // Refresh the UI
        private void RefreshUI() {
            // Refresh the rendering of the video
            mVidyoConnector.ShowViewAt(mVideoFrame, 0, 0, mVideoFrame.getWidth(), mVideoFrame.getHeight());
            Log.d(TAG, "VidyoConnectorShowViewAt: x = 0, y = 0, w = " + mVideoFrame.getWidth() + ", h = " + mVideoFrame.getHeight());
        }
    
        // The state of the VidyoConnector connection changed, reconfigure the UI.
        // If connected, dismiss the controls layout
        private void ConnectorStateUpdated(VIDYO_CONNECTOR_STATE state, final String statusText) {
            Log.d(TAG, "ConnectorStateUpdated, state = " + state.toString());
    
            mVidyoConnectorState = state;
    
            // Execute this code on the main thread since it is updating the UI layout
    
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
    
                    // Update the toggle connect button to either start call or end call image
                    mToggleConnectButton.setChecked(mVidyoConnectorState == VIDYO_CONNECTOR_STATE.VC_CONNECTED);
    
                    // Set the status text in the toolbar
                    mToolbarStatus.setText(statusText);
    
                    if (mVidyoConnectorState == VIDYO_CONNECTOR_STATE.VC_CONNECTED) {
                        // Enable the toggle toolbar control
    
                    } else {
                        // VidyoConnector is disconnected
    
                        // Disable the toggle toolbar control
    
                        // If a return URL was provided as an input parameter, then return to that application
                        if (mReturnURL != null) {
                            // Provide a callstate of either 0 or 1, depending on whether the call was successful
                            Intent returnApp = getPackageManager().getLaunchIntentForPackage(mReturnURL);
                            returnApp.putExtra("callstate", (mVidyoConnectorState == VIDYO_CONNECTOR_STATE.VC_DISCONNECTED) ? 1 : 0);
                            startActivity(returnApp);
                        }
    
                        // If the allow-reconnect flag is set to false and a normal (non-failure) disconnect occurred,
                        // then disable the toggle connect button, in order to prevent reconnection.
                        if (!mAllowReconnect && (mVidyoConnectorState == VIDYO_CONNECTOR_STATE.VC_DISCONNECTED)) {
                            mToggleConnectButton.setEnabled(false);
                            mToolbarStatus.setText("Call ended");
                        }
                    }
    
                    // Hide the spinner animation
                    mConnectionSpinner.setVisibility(View.INVISIBLE);
                }
            });
        }
    
        /*
         * Button Event Callbacks
         */
    
        // The Connect button was pressed.
        // If not in a call, attempt to connect to the backend service.
        // If in a call, disconnect.
        public void ToggleConnectButtonPressed(View v) {
            if (mToggleConnectButton.isChecked()) {
                mToolbarStatus.setText("Connecting...");
    
                // Display the spinner animation
                mConnectionSpinner.setVisibility(View.VISIBLE);
    
                final boolean status = mVidyoConnector.Connect(
                        mHost,
                        mToken,
                        mDisplayName,
                        mResourceId,
                        this);
                if (!status) {
                    // Hide the spinner animation
                    mConnectionSpinner.setVisibility(View.INVISIBLE);
    
                    ConnectorStateUpdated(VIDYO_CONNECTOR_STATE.VC_CONNECTION_FAILURE, "Connection failed");
                }
                Log.d(TAG, "VidyoConnectorConnect status = " + status);
                mVidyoConnector.RegisterParticipantEventListener(this);
            } else {
                // The button just switched to the callStart image: The user is either connected to a resource
                // or is in the process of connecting to a resource; call VidyoConnectorDisconnect to either disconnect
                // or abort the connection attempt.
                // Change the button back to the callEnd image because do not want to assume that the Disconnect
                // call will actually end the call. Need to wait for the callback to be received
                // before swapping to the callStart image.
                mToggleConnectButton.setChecked(true);
    
                mToolbarStatus.setText("Disconnecting...");
    
                mVidyoConnector.UnregisterParticipantEventListener();
    
                mVidyoConnector.Disconnect();
            }
        }
    
        // Toggle the microphone privacy
        public void MicrophonePrivacyButtonPressed(View v) {
            mVidyoConnector.SetMicrophonePrivacy(((ToggleButton) v).isChecked());
        }
    
        // Toggle the camera privacy
        public void CameraPrivacyButtonPressed(View v) {
            mVidyoConnector.SetCameraPrivacy(((ToggleButton) v).isChecked());
        }
    
        // Handle the camera swap button being pressed. Cycle the camera.
        public void CameraSwapButtonPressed(View v) {
            mVidyoConnector.CycleCamera();
        }
    }
    

    我想做的是参加每个vidyo会议。为此,我需要区分创建房间的用户(本例中为User1)和稍后加入房间的其他参与者。通过了解这一点,我可以根据User1的状态计算会话时间。当User1的android客户端收到OnSuccess接口的VidyoConnector.IConnect方法调用时(通过VidyoConnector.Connect启动与vidyo会议室的连接),我启动一个计时器,当android客户端User1接收到OnDisconnected的呼叫我停止计时器以获得会话的总时间。

    现在的问题是我找不到区分创建房间的用户和稍后加入房间的参与者的方法。现在每个人都被描述为参与者。我注意到的另一件事是,只要会议室里有人,即使创建房间的用户离开房间,房间也会保持活力。 所以我的问题是:

    1. 有没有办法区分创建会议室的User和稍后加入会议室的其他Participants

    2. 当创建房间的用户退出时,有没有办法摧毁房间并从房间中踢出所有参与者?

    3. 我知道有可能在我的后端服务器上跟踪所有这些信息,但我想知道是否可以在Android客户端上这样做。

      感谢。

1 个答案:

答案 0 :(得分:4)

应为每个用户生成令牌。所以你的工作流程应该如下 -

  1. User1想要从Android设备进行vidyo电话会议。所以User1将要求,并使用api从我的后端服务器获取新令牌。
  2. 然后,User1将向其他参与者发送邀请,以使用Connect呼叫中使用的“资源ID”加入电话会议。
  3. 每个参与者都将获得自己的令牌,但会在Connect方法中使用User1共享的“资源ID”。
  4. 要区分用户和参与者,您必须在Android应用中添加代码。当user1获得“OnParticipantJoined”时,它可以调用“GetUserId”来检查它是否与其自己的userId匹配,或者它是否是不同的参与者。 关于引导参与者,在当前版本的Vidyo.io中,无法从您的房间中踢出参与者。在您的应用程序代码中实现此功能的一种方法是包装聊天方法。因此,如果User1离开自己的房间,它可以使用“SendChatMessage”向所有其他参与者发送“离开”消息。在字符串中添加一些秘密前缀,如“xyz_Leave”,以便参与者端的应用代码知道不显示此消息,而是对其进行操作。