Screen Share - Android
Screen sharing in a meeting is the process of sharing your mobile screen with other participants in the meeting. It allows everyone in the meeting to see exactly what you are seeing on your screen, which can be helpful for presentations, demonstrations, or collaborations.
How Screen share works?
- The following diagram shows flow of the screen sharing in android using VideoSDK :
enableScreenShare()
-
By using
enableScreenShare()
function ofMeeting
class, local participant can share his/her mobile screen to other participants. -
You can pass customised screenshare track in
enableScreenShare()
by using Custom Screen Share Track. -
Screen Share stream of the participant can be accessed from the
onStreamEnabled
event ofParticipantEventListener
.
Screenshare permission
-
A participant’s Screen share stream is provided via the
MediaProjection
API. This API is only compatible withBuild.VERSION_CODES.LOLLIPOP
or higher. -
Get an instance of the
MediaProjectionManager
and Call thecreateScreenCaptureIntent()
method in an activity. This initiates a prompt dialog for the user to confirm screen projection. -
One will get a prompt dialog like this:
- After permission is received from the user, you can call
enableScreenShare()
method.
- Kotlin
- Java
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) {
// Enabling screen share
meeting!!.enableScreenShare(data)
}
}
private void enableScreenShare() {
MediaProjectionManager mediaProjectionManager =
(MediaProjectionManager) getApplication().getSystemService(
Context.MEDIA_PROJECTION_SERVICE);
startActivityForResult(
mediaProjectionManager.createScreenCaptureIntent(), CAPTURE_PERMISSION_REQUEST_CODE);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode != CAPTURE_PERMISSION_REQUEST_CODE)
return;
if (resultCode == Activity.RESULT_OK) {
// Enabling screen share
meeting.enableScreenShare(data);
}
}
Customise notification
-
When a presenter starts screen share, presenter will receive a notification with a pre-defined title and message.
-
Notification with pre-defined title and message will look like this:
- You can Customise those title, message and icon as per your requirements using
<meta-data>
specified inapp/src/main/AndroidManifest.xml
.
<application>
<meta-data
android:name="notificationTitle"
android:value="@string/notificationTitle"
/>
<meta-data
android:name="notificationContent"
android:value="@string/notificationContent"
/>
<meta-data
android:name="notificationIcon"
android:resource="@mipmap/ic_launcher_round"
/>
</application>
disableScreenShare()
- By using
disableScreenShare()
function ofMeeting
class, local participant can stop sharing his/her mobile screen to other participants.
- Kotlin
- Java
private fun disableScreenShare() {
// Disabling screen share
meeting!!.disableScreenShare()
}
private void disableScreenShare(){
// Disabling screen share
meeting.disableScreenShare();
}
Events associated with enableScreenShare
-
Participant who share their mobile screen will receive a callback on
onStreamEnabled()
of theParticipant
withStream
object. -
While other Participants will receive
onPresenterChanged()
callback of theMeeting
class with the participantId aspresenterId
who started the screen share.
Events associated with disableScreenShare
-
Participant who shared their mobile screen will receive a callback on
onStreamDisabled()
of theParticipant
withStream
object. -
While other Participants will receive
onPresenterChanged()
callback of theMeeting
class with thepresenterId
asnull
indicating there is no presenter.
- Kotlin
- Java
private fun setLocalListeners() {
meeting!!.localParticipant.addEventListener(object : ParticipantEventListener() {
//Callback for when the participant starts a stream
override fun onStreamEnabled(stream: Stream) {
if (stream.kind.equals("share", ignoreCase = true)) {
Log.d("VideoSDK","Share Stream On: onStreamEnabled $stream");
}
}
//Callback for when the participant stops a stream
override fun onStreamDisabled(stream: Stream) {
if (stream.kind.equals("share", ignoreCase = true)) {
Log.d("VideoSDK","Share Stream On: onStreamDisabled $stream");
}
}
});
}
private val meetingEventListener: MeetingEventListener = object : MeetingEventListener() {
//Callback for when the presenter changes
override fun onPresenterChanged(participantId: String) {
if(!TextUtils.isEmpty(participantId))
{
Log.d("VideoSDK","$participantId started screen share");
}else{
Log.d("VideoSDK","some one stopped screen share");
}
}
}
private void setLocalListeners() {
meeting.getLocalParticipant().addEventListener(new ParticipantEventListener() {
//Callback for when the participant starts a stream
@Override
public void onStreamEnabled(Stream stream) {
if (stream.getKind().equalsIgnoreCase("share")) {
Log.d("VideoSDK","Share Stream On: onStreamEnabled" + stream);
}
}
//Callback for when the participant stops a stream
@Override
public void onStreamDisabled(Stream stream) {
if (stream.getKind().equalsIgnoreCase("share")) {
Log.d("VideoSDK","Share Stream Off: onStreamDisabled" + stream);
}
}
});
}
private final MeetingEventListener meetingEventListener = new MeetingEventListener() {
//Callback for when the presenter changes
@Override
public void onPresenterChanged(String participantId) {
if(participantId != null){
Log.d("VideoSDK",participantId + "started screen share");
}else{
Log.d("VideoSDK","some one stopped screen share");
}
}
};
Rendering Screen Share Stream
- When a local participant shares their screen, the
onStreamEnabled()
function of theParticipantEventListener
is triggered, allowing theStream
to be added to aVideoView
.
- Kotlin
- Java
private fun setLocalListeners() {
meeting!!.localParticipant.addEventListener(object : ParticipantEventListener() {
override fun onStreamEnabled(stream: Stream) {
if (stream.kind.equals("share", ignoreCase = true)) {
// display share video
val videoTrack = stream.track as VideoTrack
shareView!!.addTrack(videoTrack)
}
}
override fun onStreamDisabled(stream: Stream) {
if (stream.kind.equals("share", ignoreCase = true)) {
shareView!!.removeTrack()
}
}
});
}
private void setLocalListeners() {
meeting.getLocalParticipant().addEventListener(new ParticipantEventListener() {
@Override
public void onStreamEnabled(Stream stream) {
if (stream.getKind().equalsIgnoreCase("share")) {
// display share video
VideoTrack videoTrack = (VideoTrack) stream.getTrack();
shareView.addTrack(videoTrack);
}
}
@Override
public void onStreamDisabled(Stream stream) {
if (stream.getKind().equalsIgnoreCase("share")) {
shareView.removeTrack();
}
}
});
}
- When another participant (excluding the local participant) shares their screen, the
onPresenterChanged()
function in theMeetingEventListener
is triggered, providing theparticipantId
of the screen sharer.
- Kotlin
- Java
private val meetingEventListener: MeetingEventListener = object : MeetingEventListener() {
override fun onPresenterChanged(participantId: String) {
updatePresenter(participantId)
}
}
//Getting the stream from the participantId
private fun updatePresenter(participantId: String?) {
// find participant
val participant = meeting!!.participants.get(participantId) ?: return
// find share stream in participant
var shareStream: Stream? = null
for (stream: Stream in participant.streams.values) {
if ((stream.kind == "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: Stream) {
if ((stream.kind == "share")) {
shareView!!.removeTrack()
}
}
})
}
private final MeetingEventListener meetingEventListener = new MeetingEventListener() {
//Triggered when Presenter changes
@Override
public void onPresenterChanged(String participantId) {
updatePresenter(participantId);
}
};
//Getting the stream from the participantId
private void updatePresenter(String participantId) {
// find participant
Participant participant = meeting.getParticipants().get(participantId);
if (participant == null) return;
// find share stream in participant
Stream shareStream = null;
for (Stream stream: participant.getStreams().values()) {
if (stream.getKind().equals("share")) {
shareStream = stream;
break;
}
}
if (shareStream == null) return;
// display share video
VideoTrack videoTrack = (VideoTrack) shareStream.getTrack();
shareView.addTrack(videoTrack)
// listen for share stop event
participant.addEventListener(new ParticipantEventListener() {
@Override
public void onStreamDisabled(Stream stream) {
if (stream.getKind().equals("share")) {
shareView.removeTrack();
}
}
});
}
- Here screenShare stream is displayed using
VideoView
, but you may also useSurfaceViewRender
for the same. - For
VideoView
, SDK version should be0.1.13
or higher. - 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