Screen sharing
The Video SDK enables an app to live stream the contents of the device's screen to the session. This feature enhances the collaborative experience of a session by allowing a user to share their content on their Android device's screen.
To follow along with this section, you should have a basic understanding of Android Services. If you are not familiar with Services, Notifications, and foreground services, we strongly recommend that you take some time to learn about them before proceeding with this section. Here are some useful links explaining services and other concepts covered in this section:
Get permission
Before using the SDK's built-in functionality for screen sharing, you must first request permission to capture screen content through Android's Media Projection Manager. To do so, add the following code to your Activity:
// Obtain the screen capture Intent through the MediaProjectionManager
val manager = getSystemService(Context.MEDIA_PROJECTION_SERVICE) as? MediaProjectionManager
manager?.createScreenCaptureIntent()?.let {
// Pass the intent and a code unique to your application here
startActivityForResult(it, 0)
}
// Implement this to listen for the result of your request
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Verify that this is the same request you sent earlier and that it was successful
if (requestCode == 0 && resultCode == Activity.RESULT_OK) {
startScreenShare(data)
}
}
private fun startScreenShare(data: Intent?) {
val intent = Intent(this, YourNotificationService::class.java)
val shareHelper = ZoomVideoSDK.getInstance().shareHelper
// For Android O and newer, you must start a foreground service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent)
} else {
startService(intent)
}
shareHelper.startShareScreen(data)
}
// Obtain the screen capture Intent through the MediaProjectionManager
MediaProjectionManager manager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
if (manager != null) {
Intent intent = manager.createScreenCaptureIntent();
// Pass the intent and a code unique to your application here
startActivityForResult(intent, 0);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Verify that this is the same request you sent earlier and that it was successful
if (requestCode == 0 && resultCode == Activity.RESULT_OK) {
startScreenShare(data);
}
}
private void startScreenShare(Intent data) {
Intent intent = new Intent(this, YourNotificationService.class);
ZoomVideoSDKShareHelper shareHelper = ZoomVideoSDK.getInstance().getShareHelper();
// For Android O and newer, you must start a foreground service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent);
} else {
startService(intent);
}
shareHelper.startShareScreen(data);
}
If you are running Android O or later, you must first implement a Service to be run as a foreground service before starting the screen share. Foreground services require a notification, which also requires a notification channel as of Android O. The following code can be run from within the onCreate method of your Service:
val channelId = "SomeUniqueString"
// Create a Builder for your notification with a unique String for the channelId
// Recommended: store the channel ID as a top-level constant within your Service class
val builder = NotificationCompat.Builder(applicationContext, channelId).apply {
setAutoCancel(false)
setOngoing(true)
setContentText("Screen Share")
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Device is running a version that requires a notification channel
(getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager)?.let {
if (it.getNotificationChannel(channelId) == null) {
// Your notification channel has not been created yet
it.createNotificationChannel(channelId)
}
}
val id = 0 // Define some ID for your notification
startForeground(id, builder.build())
}
String channelId = "SomeUniqueString";
// Create a builder for your notification with a unique String for the channelId
// Recommended: store the channel ID as a top-level constant within your Service class
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), channelId)
.setAutoCancel(false)
.setOngoing(true)
.setContentText("Screen Share");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Device is running a version that requires a notification channel
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (manager != null && manager.getNotificationChannel(channelId == null)) {
// Your notification channel has not been created yet
manager.createNotificationChannel(channelId);
}
int id = 0; // Define some ID for your notification
startForeground(id, builder.build());
}
After implementing your Service, don't forget to declare it in your AndroidManifest.xml file within the application element:
<service
android:name=".YourService"
android:foregroundServiceType="mediaProjection" />
Foreground permissions
Starting with Android 14, Google requires developers to specify appropriate foreground service types in their apps. The Video SDK uses these foreground service permissions.
| Permission | Description |
|---|---|
FOREGROUND_SERVICE_MICROPHONE | Allow the capability to receive audio when the app is put in the background. |
FOREGROUND_SERVICE_MEDIA_PLAYBACK | Allow the capability to share audio while screen sharing. |
FOREGROUND_SERVICE_MEDIA_PROJECTION | Allow the capability to project the screen while screen sharing. |
FOREGROUND_SERVICE_CONNECTED_DEVICE | Allow the capability to use Bluetooth device as the audio source. |
FOREGROUND_SERVICE_PHONE_CALL | Allow the capability to use Bluetooth device for the meeting call. |
The screen sharing feature in Video SDK requires foreground service. If the screen sharing feature is not included in your project, add the following code in Androidmanifest.xml to remove the service and permissions. Note that removing FOREGROUND_SERVICE_MICROPHONE permission might cause an audio issue when the application is in the background. Therefore, to ensure the audio works as expected, maintain FOREGROUND_SERVICE_MICROPHONE and FOREGROUND_SERVICE_CONNECTED_DEVICE permissions in the project and start the foreground service when joining a meeting.
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" tools:node="remove"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" tools:node="remove"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" tools:node="remove"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" tools:node="remove"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" tools:node="remove"/>
Verify screen share
After successfully completing the above steps to share your screen, you can verify that your screen share is visible on another device by responding to the following callback to get notified when screen sharing status changes within your ZoomVideoSDKDelegate:
override fun onUserShareStatusChanged(shareHelper: ZoomVideoSDKShareHelper, userInfo: ZoomVideoSDKUser, shareAction: ZoomVideoSDKShareAction) {
super.onUserShareStatusChanged(shareHelper, userInfo, shareAction)
val status = shareAction.shareStatus
// Create a new VideoView within your Activity
val videoView = ZoomVideoSDKVideoView(this)
when (status) {
ZoomVideoSDKShareStatus.ZoomVideoSDKShareStatus_None -> {
// Do nothing
}
// User has begun sharing.
ZoomVideoSDKShareStatus.ZoomVideoSDKShareStatus_Start -> {
shareAction.shareCanvas.subscribe(videoView, ZoomVideoSDKVideoAspect.ZoomVideoSDKVideoAspect_Original, ZoomVideoSDKVideoResolution.ZoomVideoSDKResolution_Auto)
}
ZoomVideoSDKShareStatus.ZoomVideoSDKShareStatus_Pause -> {
// Do nothing
}
ZoomVideoSDKShareStatus.ZoomVideoSDKShareStatus_Resume -> {
// Do nothing
}
ZoomVideoSDKShareStatus.ZoomVideoSDKShareStatus_Stop -> {
shareAction.shareCanvas.unSubscribe(videoView)
}
}
}
@Override
public void onUserShareStatusChanged(ZoomVideoSDKShareHelper shareHelper, ZoomVideoSDKUser userInfo, ZoomVideoSDKShareAction shareAction) {
super.onUserShareStatusChanged(shareHelper, userInfo, shareAction);
ZoomVideoSDKShareStatus status = shareAction.getShareStatus();
// Create a new VideoView within your Activity
ZoomVideoSDKVideoView videoView = new ZoomVideoSDKVideoView(this);
switch (status) {
case ZoomVideoSDKShareStatus_None:
break;
// User has begun sharing.
case ZoomVideoSDKShareStatus_Start:
shareAction.getShareCanvas().subscribe(videoView, ZoomVideoSDKVideoAspect.ZoomVideoSDKVideoAspect_Original, ZoomVideoSDKVideoResolution.ZoomVideoSDKResolution_Auto);
break;
case ZoomVideoSDKShareStatus_Pause:
break;
case ZoomVideoSDKShareStatus_Resume:
break;
case ZoomVideoSDKShareStatus_Stop:
shareAction.getShareCanvas().unSubscribe(videoView);
break;
}
}
Share multiple screens
If the local user would like to subscribe to a specific view instead of the latest view shared from the delegate callback onUserShareStatusChanged, identify the user to subscribe to, retrieve the user's share action list, and subscribe to the selected share action.
val user: ZoomVideoSDKUser // Get the specific user you want to subscribe to their share screen
val shareActionList = user.getShareActionList()
// The shareActionList can contain 0 to multiple share coming from the selected user
if (shareActionList.isNotEmpty()) {
// Get the share you want to subscribe to - Example the first share
val shareAction: ZMVideoSDKShareAction = shareActionList[0]
shareAction.getShareCanvas().subscribeWithView(yourView, ZoomVideoSDKVideoAspect.Original, ZoomVideoSDKVideoResolution.Auto)
}
ZoomVideoSDKUser user; // Get the specific user you want to subscribe to their share screen
List<ZoomVideoSDKShareAction> shareActionList = user.getShareActionList();
// The shareActionList can contain 0 to multiple share coming from the selected user
if (shareActionList.size() > 0) {
// Get the share you want to subscribe to - Example the first share
ZoomVideoSDKShareAction shareAction = shareActionList.get(0);
// Create a new VideoView within your Activity
ZoomVideoSDKVideoView videoView = new ZoomVideoSDKVideoView(this);
shareAction.getShareCanvas().subscribe(videoView, ZoomVideoSDKVideoAspect.ZoomVideoSDKVideoAspect_Original, ZoomVideoSDKVideoResolution.ZoomVideoSDKResolution_Auto)
}