Skip to main content
Version: 2.x.x

Screen Share - React Native

This feature enables hosts to start or stop sharing their screen with other hosts and audience members during the live stream. Only hosts (in SEND_AND_RECV mode) can broadcast their screen, while audience members (in RECV_ONLY mode) can view it in real time.

note

This page uses the following asynchronous methods. Refer to their API reference for the errors each Promise may reject with, and handle these rejections appropriately based on your use case.

Android Setup​

Screen sharing on Android needs no extra setup in your app. The SDK adds the FOREGROUND_SERVICE and FOREGROUND_SERVICE_MEDIA_PROJECTION permissions and its own screen share foreground service to your app's manifest, and it shows its own notification while you share.

caution

If your app used v1.x.x of the SDK, remove the live.videosdk.rnwebrtc.MediaProjectionService and live.videosdk.rnwebrtc.MediaProjectionServiceTask services and the live.videosdk.rnwebrtc meta-data entries from your AndroidManifest.xml. Those classes no longer exist. Learn more in the Migration Guide.


System Audio with Screen Share (Android Only)​

  • You can share the device's audio along with the screen.

  • withAudio: In the createScreenShareVideoTrack() method, withAudio is a flag that controls whether system audio is shared. Set it to true to include system audio with the screen share, or false (the default) to share only the screen without audio. Then pass the track to enableScreenShare(). On iOS, the flag has no effect.

  • If you call enableScreenShare() without a track, Android shares the system audio too. To share only the screen, pass a track created with withAudio set to false.

  • System audio capture needs the android.permission.RECORD_AUDIO permission, which your app also needs for the microphone.

  • Devices running Android 9 (API Level 28) or below will not support the System Audio sharing feature.

  • Apps that do not allow their audio to be captured are not heard in the share.

note

The system audio is mixed into the host's microphone track. It will only be shared if the microphone is enabled. If the microphone is muted, the system audio will also be muted.


iOS Setup​

On iOS, your app needs a Broadcast Upload Extension, and your app's Info.plist needs the RTCScreenSharingExtension and RTCAppGroupIdentifier keys. To set them up, follow the dedicated guide:

enableScreenShare() shows the system broadcast picker itself. You do not need VideosdkRPK or any other code of your own to show it.


Screen Share Controls​

enableScreenShare()​

  • By using the enableScreenShare() function of the useRoom hook, the host can share their device screen to other hosts and audience members.

  • Create the screen share track first with createScreenShareVideoTrack(), and pass it to enableScreenShare(). Its encoderConfig sets the resolution and frame rate: h360p_30fps, h480p_15fps, h480p_30fps, h720p_5fps, h720p_15fps (the default), h720p_30fps, h1080p_15fps or h1080p_30fps. Learn more in Custom Screen Share Track.

  • A stopped or released track is refused with ERROR_INVALID_CUSTOM_VIDEO_TRACK (3029).

  • On Android, createScreenShareVideoTrack() shows the screen capture consent dialog. If the user declines, it rejects with 3016 ERROR_GET_DISPLAY_MEDIA_PERMISSION_DENIED.

  • On iOS, enableScreenShare() shows the system broadcast picker, and screen capture starts when the user taps Start Broadcast. If the user closes the picker, call enableScreenShare() again to show it again.

  • Sharing has started when the share stream of the host fires onStreamEnabled, not when the Promise resolves.

  • If the user stops sharing from the system controls, such as iOS Control Center, the SDK ends the share for you and onStreamDisabled fires.

  • Calling it while the host is already sharing rejects with 3054 ERROR_ALREADY_IN_REQUESTED_STATE.

  • The Screen Share stream of a participant can be accessed from the screenShareStream property of the useParticipant hook.

disableScreenShare()​

  • By using the disableScreenShare() function of the useRoom hook, the host can stop sharing their screen to other hosts and audience members.

toggleScreenShare()​

  • By using the toggleScreenShare() function of the useRoom hook, the host can start or stop sharing their screen to other hosts and audience members based on the current state of the screen sharing.

  • It takes the same optional track as enableScreenShare(), and uses it only when screen sharing is turned on.

  • The Screen Share stream of a participant can be accessed from the screenShareStream property of useParticipant hook.

note

Audience members (in RECV_ONLY mode) cannot share their screen. For them, enableScreenShare() and toggleScreenShare() reject with 3066 ERROR_ACTION_NOT_SUPPORTED_IN_MODE. Show the screen share controls only to hosts, because on Android createScreenShareVideoTrack() shows the consent dialog before that rejection.

Example​

import React from "react";
import {
createScreenShareVideoTrack,
useRoom,
} from "@videosdk.live/react-native-sdk";
import { TouchableOpacity, Text } from "react-native";

const RoomControls = () => {
const {
enableScreenShare,
disableScreenShare,
toggleScreenShare,
isScreenSharing,
} = useRoom();

const handleEnableScreenShare = async () => {
try {
const screenShareTrack = await createScreenShareVideoTrack({
encoderConfig: "h720p_15fps",
withAudio: false, // Android only
});
await enableScreenShare(screenShareTrack);
} catch (err) {
console.error("enableScreenShare failed:", err);
}
};

const handleDisableScreenShare = async () => {
try {
await disableScreenShare();
} catch (err) {
console.error("disableScreenShare failed:", err);
}
};

const handleToggleScreenShare = async () => {
try {
// Create a track only when screen sharing is about to start
const screenShareTrack = isScreenSharing
? undefined
: await createScreenShareVideoTrack({ encoderConfig: "h720p_15fps" });
await toggleScreenShare(screenShareTrack);
} catch (err) {
console.error("toggleScreenShare failed:", err);
}
};

return (
<>
<TouchableOpacity onPress={handleEnableScreenShare}>
<Text>Enable Screen Share</Text>
</TouchableOpacity>

<TouchableOpacity onPress={handleDisableScreenShare}>
<Text>Disable Screen Share</Text>
</TouchableOpacity>

<TouchableOpacity onPress={handleToggleScreenShare}>
<Text>Toggle Screen Share</Text>
</TouchableOpacity>
</>
);
};

export default RoomControls;

Handling Screen Share Events​

Events associated with enableScreenShare​

  • Every Participant—including all the hosts and audience members will receive a callback on onStreamEnabled() event of the useParticipant() hook with the RTCStream object.

  • Every participant—including all the hosts and audience members will receive the onPresenterChanged() callback of the useRoom hook, which provides the participantId as the presenterId of the participant who started the screen share.

Events associated with disableScreenShare​

  • Every Participant—including all the hosts and audience members will receive a callback on onStreamDisabled() event of the useParticipant() hook with the RTCStream object.

  • Every Participant—including all the hosts and audience members will receive the onPresenterChanged() callback of the useRoom hook, with the presenterId as null, indicating that there is no current presenter.

Events associated with toggleScreenShare​

  • Every Participant—including all the hosts and audience members will receive a callback on onStreamEnabled() event of the useParticipant() hook with the RTCStream object, if the screen share broadcasting was started.

  • Every Participant—including all the hosts and audience members will receive a callback on onStreamDisabled() event of the useParticipant() hook with the RTCStream object, if the screen share broadcasting was stopped.

  • Every Participant—including all the hosts and audience members will receive the onPresenterChanged() callback of the useRoom hook, providing the participantId as the presenterId of the participant who started the screen share or null if the screen share was turned off.

import { useParticipant, useRoom } from "@videosdk.live/react-native-sdk";
import { Text } from "react-native";

const LiveStreamView = () => {
//Callback for when the presenter changes
function onPresenterChanged(presenterId) {
if(presenterId){
console.log(presenterId, "started screen share");
}else{
console.log("someone stopped screen share");
}
}

const { participants } = useRoom({
onPresenterChanged,
// ...
});

return <>{/* Your live stream UI */}</>;
}

const ParticipantView = ({ participantId }) => {
//Callback for when the participant starts a stream
function onStreamEnabled(stream) {
if(stream.kind === 'share'){
console.log("Share Stream On: onStreamEnabled", stream);
}
}

//Callback for when the participant stops a stream
function onStreamDisabled(stream) {
if(stream.kind === 'share'){
console.log("Share Stream Off: onStreamDisabled", stream);
}
}

const {
displayName,
// ...
} = useParticipant(participantId,{
onStreamEnabled,
onStreamDisabled,
// ...
});
return <Text>{displayName}</Text>;
}

Rendering the Screen Share Stream​

To display the screen share from another host:

1. Get the presenter's id​

To render the screenshare, you will need the participantId of the host presenting the screen. Call getActivePresenterId() of the useRoom hook. Calling it while rendering re-renders the component when the presenter changes.

import React from "react";
import { useRoom } from "@videosdk.live/react-native-sdk";

const RoomView = () => {
const { getActivePresenterId } = useRoom();
const presenterId = getActivePresenterId();

return <>{presenterId && <PresenterView presenterId={presenterId} />}</>;
};

export default RoomView;

2. Access the Screen Share Stream​

Now that you have the presenter's id, you can obtain the screenShareStream using the useParticipant hook and play it.

import React from "react";
import {
useParticipant,
MediaStream,
RTCView,
} from "@videosdk.live/react-native-sdk";

const PresenterView = ({ presenterId }) => {
const { screenShareStream, screenShareOn } = useParticipant(presenterId);

if (!screenShareOn || !screenShareStream) return null;

return (
<RTCView
streamURL={new MediaStream([screenShareStream.track]).toURL()}
objectFit="contain"
style={{ flex: 1 }}
/>
);
};

export default PresenterView;

API References​

Got a Question? Ask us on discord