# 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: - [Android Services](https://developer.android.com/guide/components/services) - [Foreground Services](https://developer.android.com/guide/components/foreground-services) - [Media Projection Manager](https://developer.android.com/reference/android/media/projection/MediaProjectionManager) ## 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: ```kotlin // 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) } ``` ```java // 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: ```kotlin 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()) } ``` ```java 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: ```xml ``` ### Foreground permissions Starting with Android 14, Google requires developers to [specify appropriate foreground service types in their apps](https://developer.android.com/about/versions/14/changes/fgs-types-required). 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. ```xml ``` ## 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`: ```kotlin 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) } } } ``` ```java @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. ```kotlin 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) } ``` ```java ZoomVideoSDKUser user; // Get the specific user you want to subscribe to their share screen List 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) } ```