Receive a screen share

When another participant starts, pauses, resumes, or stops sharing, the Video SDK for Android fires onUserShareStatusChanged on your ZoomVideoSDKDelegate. Render the incoming share by attaching a ZoomVideoSDKVideoView to your layout and subscribing it to the share canvas.

Confirmation that the local user's own share started successfully comes from the return value of startShareScreen and the onFailedToStartShare callback.

Add a share view to your layout

Place a ZoomVideoSDKVideoView in the layout you want to render shares into.

<FrameLayout
    android:id="@+id/share_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

You'll attach a ZoomVideoSDKVideoView to this container at runtime when a share starts, and remove it when the share stops.

Listen for share status changes

The callback receives the user whose share state changed and a ZoomVideoSDKShareAction describing the change.

private val shareViews = mutableMapOf<String, ZoomVideoSDKVideoView>()
override fun onUserShareStatusChanged(
    shareHelper: ZoomVideoSDKShareHelper,
    userInfo: ZoomVideoSDKUser,
    shareAction: ZoomVideoSDKShareAction
) {
    val container = findViewById<FrameLayout>(R.id.share_container)
    val userId = userInfo.userID
    when (shareAction.shareStatus) {
        ZoomVideoSDKShareStatus.ZoomVideoSDKShareStatus_Start -> {
            val videoView = ZoomVideoSDKVideoView(this)
            container.addView(videoView)
            shareViews[userId] = videoView
            shareAction.shareCanvas.subscribe(
                videoView,
                ZoomVideoSDKVideoAspect.ZoomVideoSDKVideoAspect_Original,
                ZoomVideoSDKVideoResolution.ZoomVideoSDKResolution_Auto
            )
        }
        ZoomVideoSDKShareStatus.ZoomVideoSDKShareStatus_Stop -> {
            shareViews.remove(userId)?.let {
                shareAction.shareCanvas.unSubscribe(it)
                container.removeView(it)
            }
        }
        ZoomVideoSDKShareStatus.ZoomVideoSDKShareStatus_Pause,
        ZoomVideoSDKShareStatus.ZoomVideoSDKShareStatus_Resume,
        ZoomVideoSDKShareStatus.ZoomVideoSDKShareStatus_None -> {
            // No subscription change — see the table below.
        }
    }
}
private final Map<String, ZoomVideoSDKVideoView> shareViews = new HashMap<>();
@Override
public void onUserShareStatusChanged(
    ZoomVideoSDKShareHelper shareHelper,
    ZoomVideoSDKUser userInfo,
    ZoomVideoSDKShareAction shareAction
) {
    FrameLayout container = findViewById(R.id.share_container);
    String userId = userInfo.getUserID();
    switch (shareAction.getShareStatus()) {
        case ZoomVideoSDKShareStatus_Start: {
            ZoomVideoSDKVideoView videoView = new ZoomVideoSDKVideoView(this);
            container.addView(videoView);
            shareViews.put(userId, videoView);
            shareAction.getShareCanvas().subscribe(
                videoView,
                ZoomVideoSDKVideoAspect.ZoomVideoSDKVideoAspect_Original,
                ZoomVideoSDKVideoResolution.ZoomVideoSDKResolution_Auto
            );
            break;
        }
        case ZoomVideoSDKShareStatus_Stop: {
            ZoomVideoSDKVideoView videoView = shareViews.remove(userId);
            if (videoView != null) {
                shareAction.getShareCanvas().unSubscribe(videoView);
                container.removeView(videoView);
            }
            break;
        }
        case ZoomVideoSDKShareStatus_Pause:
        case ZoomVideoSDKShareStatus_Resume:
        case ZoomVideoSDKShareStatus_None:
            // No subscription change — see the table below.
            break;
    }
}

Tracking views in a per-user map makes it easy to attach and detach them as users start and stop sharing, and to find them later in the lifecycle callbacks covered below.

Share status values

The onUserShareStatusChanged callback reports the share state as a ZoomVideoSDKShareStatus value. Each value tells you whether to subscribe the view, keep it, or tear it down.

StatusWhen it firesWhat to do
ZoomVideoSDKShareStatus_StartThe user began sharing.Subscribe the share canvas to a ZoomVideoSDKVideoView and add the view to your layout.
ZoomVideoSDKShareStatus_PauseThe user paused the share.Optionally dim or overlay the view. The last frame stays on screen. Keep the subscription.
ZoomVideoSDKShareStatus_ResumeThe user resumed a paused share.Clear any pause overlay you applied. Keep the subscription.
ZoomVideoSDKShareStatus_StopThe user stopped sharing, either programmatically or via the system Media Projection notification.Unsubscribe the view and remove it from your layout.
ZoomVideoSDKShareStatus_NoneThere is no active share for this user.No action needed. This is typically the initial state.

Aspect mode and resolution

The subscribe call takes two enums that control how the share renders:

  • ZoomVideoSDKVideoAspect_Original keeps the source aspect ratio with letterboxing if the view doesn't match. This is the safest default and what this topic uses.
  • ZoomVideoSDKVideoAspect_Full_Filled fills the view, cropping if the aspect ratios disagree.
  • ZoomVideoSDKVideoAspect_LetterBox and ZoomVideoSDKVideoAspect_PanAndScan give finer control. See the video best practices for guidance on choosing an aspect mode.

ZoomVideoSDKResolution_Auto lets the SDK pick the streaming resolution based on view size and network conditions. Force a specific resolution only if you have a clear reason. Pinning low when you have screen real estate hurts quality, and pinning high when you don't wastes bandwidth.

React to dimension changes

When the sharer resizes their window, rotates their device, or otherwise changes the content dimensions, the SDK fires onShareContentSizeChanged. Read the new dimensions from the share action and re-layout your container if the aspect ratio is now different.

override fun onShareContentSizeChanged(shareAction: ZoomVideoSDKShareAction) {
    val size = shareAction.shareSourceContentSize  // ZoomVideoSDKViewSize
    // Resize your container or the share view to match the new aspect.
}
@Override
public void onShareContentSizeChanged(ZoomVideoSDKShareAction shareAction) {
    ZoomVideoSDKViewSize size = shareAction.getShareSourceContentSize();
    // Resize your container or the share view to match the new aspect.
}

Handle subscription failures

If a share canvas subscription can't be established (for example, the share has already stopped between callback and subscribe, or the SDK hits a resource limit), the delegate fires onShareCanvasSubscribeFail. Surface the error to the user, remove the orphaned view from your layout, and consider retrying once.

override fun onShareCanvasSubscribeFail(
    failReason: ZoomVideoSDKVideoSubscribeFailReason,
    user: ZoomVideoSDKUser,
    view: ZoomVideoSDKVideoView
) {
    // Remove the view from your layout and surface the failure.
}
@Override
public void onShareCanvasSubscribeFail(
    ZoomVideoSDKVideoSubscribeFailReason failReason,
    ZoomVideoSDKUser user,
    ZoomVideoSDKVideoView view
) {
    // Remove the view from your layout and surface the failure.
}

Identify the share source

A share may be a screen, a camera, or a pure-audio stream. Read getShareType() on the action to identify which.

when (shareAction.shareType) {
    ZoomVideoSDKShareType.ZoomVideoSDKShareType_Normal -> {
        // Screen, application window, or external source.
    }
    ZoomVideoSDKShareType.ZoomVideoSDKShareType_Camera -> {
        // The user is sharing a camera as content.
    }
    ZoomVideoSDKShareType.ZoomVideoSDKShareType_PureAudio -> {
        // Audio-only share — no video frames, no canvas to subscribe.
    }
    ZoomVideoSDKShareType.ZoomVideoSDKShareType_None -> {}
}
switch (shareAction.getShareType()) {
    case ZoomVideoSDKShareType_Normal:
        // Screen, application window, or external source.
        break;
    case ZoomVideoSDKShareType_Camera:
        // The user is sharing a camera as content.
        break;
    case ZoomVideoSDKShareType_PureAudio:
        // Audio-only share — no video frames, no canvas to subscribe.
        break;
    case ZoomVideoSDKShareType_None:
        break;
}

Skip the canvas subscription when shareType is ZoomVideoSDKShareType_PureAudio. There are no frames to render.

The SDK also fires onShareContentChanged when a sharer switches between source types (for example, from camera share to screen share) without stopping the share. Treat it as a signal to refresh anything you cached based on share type.

Unsubscribe when your view goes away

Activity rotation, navigation, or tearing down a video tile all destroy ZoomVideoSDKVideoView instances. Always unSubscribe from the share canvas before the view is detached. Otherwise the SDK keeps holding a reference and you leak memory and bandwidth.

override fun onDestroy() {
    val container = findViewById<FrameLayout>(R.id.share_container)
    shareViews.forEach { (userId, view) ->
        // Find the user and unsubscribe from their share canvas.
        ZoomVideoSDK.getInstance().session.remoteUsers
            .firstOrNull { it.userID == userId }
            ?.shareActionList
            ?.firstOrNull()
            ?.shareCanvas
            ?.unSubscribe(view)
        container.removeView(view)
    }
    shareViews.clear()
    super.onDestroy()
}
@Override
protected void onDestroy() {
    FrameLayout container = findViewById(R.id.share_container);
    for (Map.Entry<String, ZoomVideoSDKVideoView> entry : shareViews.entrySet()) {
        ZoomVideoSDKUser user = findUserById(entry.getKey());
        if (user != null) {
            List<ZoomVideoSDKShareAction> actions = user.getShareActionList();
            if (!actions.isEmpty()) {
                actions.get(0).getShareCanvas().unSubscribe(entry.getValue());
            }
        }
        container.removeView(entry.getValue());
    }
    shareViews.clear();
    super.onDestroy();
}

For the same reason, prefer keeping share-related state in a ViewModel so configuration changes (such as device rotation) don't tear down the share UI alongside the Activity. For the pattern, see the Lifecycle in the video best practices.

Check whether anyone is sharing

Outside of the callback, you can also query whether any other participant is currently sharing, useful when joining a session in progress.

val otherSharing = ZoomVideoSDK.getInstance().shareHelper.isOtherSharing
boolean otherSharing = ZoomVideoSDK.getInstance().getShareHelper().isOtherSharing();

If multiple users may be sharing at the same time, see Handle Multiple Screen Shares for how to pick which share to subscribe to. To draw on a share you're viewing, see Annotation.