Implement Screen Sharing for Android

This tutorial guides how to implement screen sharing in a conference application.

Start sharing a screen

Layout modification

1. To modify the layout, edit the main_activity.xml file, adding the following content for Step 5:

<LinearLayout ...>

    ...

    <!-- Step 5. Put the layout changes for the screen sharing step here -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/startScreenShare"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="start screenshare" />

        <!-- Step 5.2. This layout will be upgraded in the stop screen sharing step -->
    </LinearLayout>

    <!-- Step 6. ...

</LinearLayout>

2. Modify the interface linking in the MainActivity class in MainActivity.java:

  • New method for MainActivity:
public void onStartScreenShare() {

}

// add onClickListener for onStartScreenShare()
@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...
    binding.startScreenShare.setOnClickListener(_view -> onStartScreenShare());
}
  • Add the following code to the onCreate method:
@Override
protected void onCreate(Bundle savedInstanceState) {
    ...

    //adding the startScreenShare in the flow
    add(views, R.id.startScreenShare);
    add(buttonsInConference, R.id.startScreenShare);
    add(buttonsNotInOwnScreenShare, R.id.startScreenShare);
}

3. Add the following logic to the application:

  • In updateViews, enable and disable buttons based on the own video state.
private void updateViews() {
    ...

    if (null != current) {
        if (current.isScreenShareOn()) {
            setEnabled(buttonsInOwnScreenShare, true);
            setEnabled(buttonsNotInOwnScreenShare, false);
        } else {
            setEnabled(buttonsInOwnScreenShare, false);
            setEnabled(buttonsNotInOwnScreenShare, true);
        }
    }
}
  • In updateStreams, use a screen share stream in preference to a video stream:
private void updateStreams() {
    ...

    // Screen shares take precedence over videos
    for (Participant user : VoxeetSDK.conference().getParticipants()) {
        boolean isLocal = user.getId().equals(VoxeetSDK.session().getParticipantId());
        MediaStream stream = user.streamsHandler().getFirst(MediaStreamType.ScreenShare);

        VideoView video = isLocal ? this.binding.video : this.binding.videoOther;

        if (null != stream && !stream.videoTracks().isEmpty()) {
            video.setVisibility(View.VISIBLE);
            video.attach(user.getId(), stream);
        }
    }
}
  • Use the following implementation onStartScreenShare:
public void onStartScreenShare() {
    VoxeetSDK.screenShare().sendRequestStartScreenShare();
}
  • Add a handler for the RequestScreenSharePermissionEvent.
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(RequestScreenSharePermissionEvent event) {
    VoxeetSDK.screenShare().sendUserPermissionRequest(this);
}
  • Add a handler for activity results with an override of onActivityResult.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    boolean managed = false;

    if (null != VoxeetSDK.screenShare()) {
        managed = VoxeetSDK.screenShare().onActivityResult(requestCode, resultCode, data);
    }

    if (!managed) {
        super.onActivityResult(requestCode, resultCode, data);
    }
}
  • Add the following import:
import com.voxeet.sdk.services.screenshare.ScreenCapturerService;

  • Modify onResume to consuming the result of the screen sharing request.
@Override
protected void onResume() {
    ...
    ScreenCapturerService.register(this);
    VoxeetSDK.screenShare().consumeRightsToScreenShare();
}
  • Add the onDestroy function.
@Override
protected void onDestroy() {
    ScreenCapturerService.unregisterActivity();

    super.onDestroy();
}

After the screenshare is started, UserStreamUpdated is triggered.

Stop sharing a screen

Layout modification

1. To modify the layout, edit the main_activity.xml file, adding the following content for Step 5.2:

<LinearLayout ...>
    ...
    <LinearLayout ...>
        ...

        <!-- Step 5.2. This layout will be upgraded in the stop screen sharing step -->
        <Button
            android:id="@+id/stopScreenShare"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="stop screenshare" />

    </LinearLayout>

    <!-- Step 6. ...

</LinearLayout>

2. Modify the interface linking in the MainActivity class in MainActivity.java:

  • New method for MainActivity:
public void onStopScreenShare() {

}

// add onClickListener for onStopScreenShare()
@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...
    binding.stopScreenShare.setOnClickListener(_view -> onStopScreenShare());
}
  • Add the following code to the onCreate method:
@Override
protected void onCreate(Bundle savedInstanceState) {
    ...

    //adding the stopScreenShare in the flow
    add(views, R.id.stopScreenShare);
    add(buttonsInConference, R.id.stopScreenShare);
    add(buttonsInOwnScreenShare, R.id.stopScreenShare);
}

3. Add the following logic to the application:

  • Use the following implementation for onStopScreenShare:
public void onStopScreenShare() {
    VoxeetSDK.screenShare().stopScreenShare()
        .then((result, solver) -> {
            // screenshare has been stopped locally and remotely
            updateViews();
        }).error(error -> {
            // screenshare has been stopped locally but a network error occurred
        });
}

After the screenshare is stopped, UserStreamUpdated is triggered.