0

我正在使用Vidyo.io服务将视频会议集成到我的 android 应用程序中。我已经能够VidyoConnector使用android-vidyo-sdk. 但是,我想了解有关会议室和加入会议室的参与者的更多信息。

我想象的工作流程如下:

  1. 用户 1 想从 Android 设备进行 vidyo 电话会议。因此,User1 将请求并使用 api 从我的后端服务器获取一个新令牌。
  2. 然后,User1 将使用在步骤 1 中获得的令牌和相应的 vidyo 会议室资源 ID 向其他参与者发送加入电话会议的邀请。
  3. 其他与会者将使用在步骤 2 中从 User1 获得的信息,并能够加入会议室。

到目前为止,我已经引用VidyoConnector了示例应用程序来创建一个VideoChatActivity通过对原始VidyoConnector示例应用程序的MainActivity. 将VideoChatActivity通过Intent我的应用程序中的另一个活动调用它,其中包含启动 vidyo 连接所需的所有信息,如令牌、resourceId、用户名等。为了跟踪每个参与者的状态,我已经实现了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(通过 启动与 vidyo 会议室的连接时VidyoConnector.Connect),我启动一个计时器,当 User1 的 android 客户端收到对我的调用时,OnDisconnected我停止计时器以获取总时间的会议。

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

  1. 有没有办法区分User创建房间的人和Participants后来加入房间的人?

  2. 当创建房间的用户退出时,有没有办法破坏房间并将所有参与者踢出房间?

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

谢谢。

4

1 回答 1

4

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

  1. 用户 1 想从 Android 设备进行 vidyo 电话会议。因此,User1 将请求并使用 api 从我的后端服务器获取一个新令牌。
  2. 然后,用户 1 将使用 Connect 呼叫中使用的“资源 ID”向其他参与者发送加入电话会议的邀请。
  3. 每个参与者都将获得自己的令牌,但将在 Connect 方法中使用 User1 共享的“资源 ID”。

为了区分用户和参与者,您必须在您的 android 应用程序中添加代码。当 user1 获得“OnParticipantJoined”时,它可以调用“GetUserId”来检查它是否与自己的 userId 匹配,或者它是否是不同的参与者。关于踢出参与者,在当前版本的 Vidyo.io 中,无法将参与者踢出您的房间。在您的应用程序代码中实现此功能的一种方法是包装聊天方法。因此,如果 User1 离开自己的房间,它可以使用“SendChatMessage”向所有其他参与者发送“离开”消息。在字符串中添加一些秘密前缀,例如“xyz_Leave”,以便参与者端的应用程序代码知道不显示此消息而是对其进行操作。

于 2017-04-11T00:27:25.963 回答