Screen Share - Android
Screen sharing sends your phone's screen to the other participants in the room, for presentations, demos or walkthroughs.
How Screen share works?
-
Screen sharing works in these steps:
- Your app asks the user for permission to capture the screen.
- If the user allows it, your app passes the result to
enableScreenShare(). If not, nothing is shared. - The SDK starts a foreground service, shows its notification and starts sharing the screen.
- The screen share stream arrives on
onStreamEnabled(). Add it to aVideoViewto display it.
enableScreenShare()
-
Call
room.enableScreenShare(data)with the resultIntentof the screen capture prompt to start sharing the screen. -
enableScreenShare()is asuspendfunction. Call it from a coroutine, such aslifecycleScope.launch(fromandroidx.lifecycle:lifecycle-runtime-ktx). It returns once sharing has started, which can take a moment. -
It throws
VideoSDKExceptionwith3054(ERROR_ALREADY_IN_REQUESTED_STATE) when the screen is already being shared,3055(ERROR_OPERATION_IN_PROGRESS) while another screen share call is running, and3016(ERROR_GET_DISPLAY_MEDIA_PERMISSION_DENIED) when the permission result can't be used. -
Called before the room is joined, or while it is reconnecting,
enableScreenShare()anddisableScreenShare()do nothing and report3035(ERROR_ACTION_PERFORMED_BEFORE_ROOM_JOINED) or3065(ERROR_ROOM_RECONNECTING) ononErrorinstead of throwing. -
You can pass a custom screen share track, created with
VideoSDK.createScreenShareVideoTrack(), toenableScreenShare(). Learn more in Custom Screen Share Track. -
The participant's screen share stream arrives on the
onStreamEnabledevent ofParticipantEventListener. -
room.isScreenSharingistruewhile the local participant's screen share is published.
System Audio with Screen Share
-
You can share the device's audio along with the screen.
-
enableAudio: Boolean: In theenableScreenShare()method, the second parameter,enableAudio, is a flag that controls whether system audio is shared. Set it totrueto include system audio with the screen share, orfalseto share only the screen without audio. It defaults tofalse. -
If you share a custom screen share track, set
withAudio = truewhen you create it withVideoSDK.createScreenShareVideoTrack()instead. -
Ensure that you request the necessary permissions (
android.permission.RECORD_AUDIO) for screen sharing and system audio capture on the user's device. The required permissions may vary based on the Android version and device manufacturer. -
Devices running
Android 9(API Level 28) or below will not support the System Audio sharing feature.noteSystem audio is mixed into your microphone track, so it is sent only while the microphone is on, and muting the microphone mutes it too. No separate
SHARE_AUDIOstream is sent, so other participants hear it in your microphone stream andgetShareAudioStats()returnsnullfor you.
Screenshare permission
-
A participant’s Screen share stream is provided via the
MediaProjectionAPI. -
Get an instance of the
MediaProjectionManagerand call thecreateScreenCaptureIntent()method in an activity. This initiates a prompt dialog for the user to confirm screen projection. -
The user sees a dialog like this:

- After permission is received from the user, you can call
enableScreenShare()method.
private fun enableScreenShare() {
val mediaProjectionManager = application.getSystemService(
MEDIA_PROJECTION_SERVICE
) as MediaProjectionManager
startActivityForResult(
mediaProjectionManager.createScreenCaptureIntent(), CAPTURE_PERMISSION_REQUEST_CODE
)
}
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode != CAPTURE_PERMISSION_REQUEST_CODE) return
if (resultCode == RESULT_OK && data != null) {
lifecycleScope.launch {
try {
// Enabling screen share
room!!.enableScreenShare(data, enableAudio = true) // Enables system audio sharing
} catch (e: VideoSDKException) {
Log.e("VideoSDK", "Screen share failed: ${e.code} ${e.name}")
}
}
}
}
Screen share notification
-
While the screen is being shared, the SDK runs a foreground service and shows its notification: "VideoSDK is sharing your screen".
-
This notification can't be customised. The
notificationTitle,notificationContentandnotificationIconmeta-data entries inAndroidManifest.xmlhave no effect. -
On Android 13 (API level 33) and later, the notification shows in the notification drawer only if your app has the
POST_NOTIFICATIONSpermission. The screen share works either way. -
If the user swipes your app away from the recent apps screen, the screen share ends.
disableScreenShare()
-
Call
room.disableScreenShare()to stop sharing the screen. -
disableScreenShare()is asuspendfunction. It throwsVideoSDKExceptionwith3054(ERROR_ALREADY_IN_REQUESTED_STATE) when nothing is being shared, and3055(ERROR_OPERATION_IN_PROGRESS) while another screen share call is running.
private fun disableScreenShare() {
lifecycleScope.launch {
try {
// Disabling screen share
room!!.disableScreenShare()
} catch (e: VideoSDKException) {
Log.e("VideoSDK", "Stopping screen share failed: ${e.code} ${e.name}")
}
}
}
Events associated with enableScreenShare
-
On every device in the room,
onStreamEnabled()is called on the listener of thatParticipant, with the newRTCStream. ItskindisMediaType.SHARE. -
Every Participant, including the one who shares, will receive
onPresenterChanged()callback of theRoomclass with the participantId aspresenterIdwho started the screen share.
Events associated with disableScreenShare
-
On every device in the room,
onStreamDisabled()is called on the listener of thatParticipant, with theRTCStreamthat stopped. ItskindisMediaType.SHARE. -
Every Participant will receive
onPresenterChanged()callback of theRoomclass with thepresenterIdasnullindicating there is no presenter.
private fun setLocalListeners() {
room!!.localParticipant.addEventListener(object : ParticipantEventListener() {
//Callback for when the participant starts a stream
override fun onStreamEnabled(stream: RTCStream) {
if (stream.kind == MediaType.SHARE) {
Log.d("VideoSDK","Share Stream On: onStreamEnabled $stream")
}
}
//Callback for when the participant stops a stream
override fun onStreamDisabled(stream: RTCStream) {
if (stream.kind == MediaType.SHARE) {
Log.d("VideoSDK","Share Stream Off: onStreamDisabled $stream")
}
}
})
}
private val roomEventListener: RoomEventListener = object : RoomEventListener() {
//Callback for when the presenter changes
override fun onPresenterChanged(presenterId: String?) {
if(!TextUtils.isEmpty(presenterId))
{
Log.d("VideoSDK","$presenterId started screen share")
}else{
Log.d("VideoSDK","someone stopped screen share")
}
}
}
Rendering Screen Share Stream
-
When the local participant shares their screen,
onStreamEnabled()of theParticipantEventListeneris called with anRTCStreamof kindMediaType.SHARE. Add its track to aVideoViewto display it. -
VideoTrackcomes from thevideosdk.org.webrtcpackage.
import videosdk.org.webrtc.VideoTrack
private fun setLocalListeners() {
room!!.localParticipant.addEventListener(object : ParticipantEventListener() {
override fun onStreamEnabled(stream: RTCStream) {
if (stream.kind == MediaType.SHARE) {
// display share video
val videoTrack = stream.track as? VideoTrack
shareView!!.addTrack(videoTrack)
}
}
override fun onStreamDisabled(stream: RTCStream) {
if (stream.kind == MediaType.SHARE) {
shareView!!.removeTrack()
}
}
})
}
- When a participant shares their screen, the
onPresenterChanged()function in theRoomEventListeneris triggered on every participant's device, including the sharer's own, providing thepresenterIdof the screen sharer.room.getActivePresenterId()returns the same ID at any time. It is triggered withnullwhen the share stops. The example below shows another participant's share; your own share arrives on the local participant'sonStreamEnabled(), as shown above.
private val roomEventListener: RoomEventListener = object : RoomEventListener() {
override fun onPresenterChanged(presenterId: String?) {
updatePresenter(presenterId)
}
}
//Getting the stream from the participantId
private fun updatePresenter(participantId: String?) {
// find participant
val participant = room!!.participants.get(participantId) ?: return
// find share stream in participant
var shareStream: RTCStream? = null
for (stream: RTCStream in participant.streams.values) {
if (stream.kind == MediaType.SHARE) {
shareStream = stream
break
}
}
if (shareStream == null) return
// display share video
val videoTrack = shareStream.track as? VideoTrack
shareView!!.addTrack(videoTrack)
// listen for share stop event
participant.addEventListener(object : ParticipantEventListener() {
override fun onStreamDisabled(stream: RTCStream) {
if (stream.kind == MediaType.SHARE) {
shareView!!.removeTrack()
}
}
})
}
- Here screenShare stream is displayed using
VideoView. - To know more about
VideoView, please visit here
API Reference
The API references for all the methods and events utilised in this guide are provided below.
Got a Question? Ask us on discord

