2017-03-27 28 views
0

我使用Vidyo.io服務將視頻會議集成到我的Android應用程序中。我已經能夠使用android-vidyo-sdk附帶的VidyoConnector示例應用成功實施視頻會議。 但是,我想了解更多關於會議室和參與者的信息。使用Android Vidyo SDK跟蹤Vidyo會議參與者

,我想象中的工作流程如下:

  1. 用戶1希望讓從Android設備Vidyo的電話會議。因此,User1會詢問並使用api從後端服務器獲取新令牌。
  2. 然後,用戶1將向其他參與者發送邀請,加入使用在步驟1中獲得的令牌和相應的vidyo會議室resourceId獲得的會議電話。
  3. 其他參與者將在步驟2中使用從用戶1獲得的信息,並能夠加入會議室。

到目前爲止,我已引用VidyoConnector示例應用來創建活動通過進行一些修改原VidyoConnector示例應用程序的MainActivity稱爲VideoChatActivityVideoChatActivity將通過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, 
                   "[email protected] [email protected] 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的狀態來計時。當用戶1的Android客戶端接到方法VidyoConnector.IConnect接口的方法(在通過VidyoConnector.Connect啓動到vidyo會議室的連接時),我啓動一個定時器,並且當用戶1的Android客戶端接收到對OnDisconnected的呼叫時,我停止定時器獲取會話的總時間。

現在的問題是,我無法找到一種方法來區分創建房間的用戶和稍後加入房間的參與者。現在每個人都被描述爲參與者。我還注意到的另一件事是,只要會議室中有人在場,即使創建會議室的用戶離開會議室,該會議室也會保持活動狀態。 所以我的問題是:

  1. 是否有辦法誰創造了房間,後來加入了房間內的其他ParticipantsUser區分?

  2. 當創建房間的用戶退出時,是否有辦法摧毀房間並將所有參與者踢出房間?

據我所知,有可能跟蹤我的後端服務器上的所有這些信息,但我想知道是否有可能在Android客戶端上這樣做。

謝謝。

回答

4

應爲每個用戶生成令牌。所以你的工作流程應該如下 -

  1. 用戶1想從android設備進行vidyo電話會議。因此,User1會詢問並使用api從後端服務器獲取新令牌。
  2. 然後,用戶1將向其他參與者發送邀請,以加入電話會議,並在連接呼叫中使用「資源Id」
  3. 每個參與者都將獲得自己的令牌,但將使用Connect方法中由User1共享的「資源ID」。

要區分用戶和參與者,您必須在Android應用程序中添加代碼。當user1獲得「OnParticipantJoined」時,它可以調用「GetUserId」來檢查它是否與它自己的userId相匹配,或者它是不同的參與者。 關於引導參與者,在當前版本的Vidyo.io中無法從您的房間中踢出參與者。在你的應用程序代碼中實現這一點的一種方式是包裝聊天方法。因此,如果User1離開自己的房間,它可以使用「SendChatMessage」向所有其他參與者發送「離開」消息。在字符串中添加一些祕密前綴,如「xyz_Leave」,以便參與者端的應用程序代碼知道不顯示此消息,但要對其執行操作。