Content Share


The content share feature enhances the collaborative experience of a meeting session by allowing the users to share their content on the iOS device's screen. During a session, participants can share their screens with other participants.

The ContentShareService method is used for starting and stopping screen sharing as well as observable properties to know. You can use this method to check the screen share availability (for example it may be restricted in the meeting settings) and the current status of screen sharing.

On iOS, screen sharing requires app-level configuration, which the SDK does not provide. Screen sharing on iOS involves creating an app extension that can capture the entire screen - even when your app is in the background. A step-by-step guide for enabling screen share is as follows:

  • Create a broadcast extension
  • Set up App Groups
  • App set up
  • Next steps

BlueJeans SDK makes use of iOS-level support for screen sharing. This support allows you to capture the device's screen even when the app is running in the background. To accomplish this, you must add a broadcast extension to your project. The broadcast extension is a separate process to run on iOS. For more detail on broadcast extensions, how they work, and their limitations, see this WWDC video.

Setting up Screen Share to your app 

Create a broadcast extension

You must first create a broadcast extension it is a distinct separation in your application. This extension requires its bundle number and provisioning number.

  • Open the application project using Xcode, select File -> New -> Target.
  • Select Broadcast Upload Extension, and choose a name for the broadcast extension. You do not need to include a UI Extension.
  • Select your application under "Embed in Application".

Note

  • If you are manually managing code signing, use the Apple developer portal to create a provisioning profile for this extension.
  • If you use Xcode for managing code signing, the extension will create automatically.

 

Then select the newly created Broadcast Upload extension target in your project. You need to link the following "xcframeworks" from the SDK.

  • CocoaLumberjack
  • CocoaLumberjackSwift
  • MMWormhole
  • BJNiOSBroadcastExtension

The standard broadcast extension requires a class that sub-classes RPBroadcastSampleHandler. The BJNiOSBroadcastExtension "xcframework" supplies the BJNSampleHandler class that can be used directly in your extension without modification as follows:

import ReplayKit
import BJNiOSBroadcastExtension
 
class SampleHandler: BJNSampleHandler {}

It is not recommended to use BJNSampleHandler subclasses in the early stages of the screen-sharing setup. However, once it is working, you may wish to sub-class this method to add some of your logic here. It is important to consider the following points:

  • All super methods from the "BJNSampleHandler" class must be called.
  • The extension has a low memory limit of 50 MB. A reasonable portion of this is already needed to handle the processing of incoming frames. Be very careful with your storage allocation, as iOS will terminate your extension if you exceed the specified storage limit.

Set up App Groups

The next step is to ensure the broadcast extension and the app can communicate. You can do this via App Groups (more detail here). Do the following steps to create an app group in X-code

  • Select your project in the project navigator and go to the "Signing & Capabilities" tab. Select your app target.
  • Choose "+ Capability", followed by "App Groups".
  • Use the "+" button to create a new app group.
  • Make sure the App Group is selected for your app. This should update (or create, if needed) your entitlements file with the associated app group. Switch to the extension target, and also select the same app group.
  • If Xcode is managing code signing, it should automatically re-generate the provisioning profiles for both targets. If not, you will need to do this through the developer portal.
  • At this stage, the entitlements files for both targets should have something similar to the screenshot below:

  • This stage is very important - without the correct setup here the app will not be able to receive frames from the extension, and screen sharing will not work.

The SDK can automatically setup the connection between the app and extension at run time, but needs some configuration information. This is done by adding the following key/value pairs to your info plist: To both the app and extension plist:

  • Add a string entry, with a key of BJNScreenSharingAppGroup and the value set to the app group id generated above. To only the app plist:
  • Add another string entry, with the key of BJNScreenSharingBundleID and the value set to the bundle id of your broadcast upload extension.

App set up

You are now ready to add logic to your app to start, stop, and otherwise manage screen sharing. The SDK exposes a property contentShareAvailability. It is important to observe this property. You need to ensure that screen sharing is available before exposing any UX to start a screen share

There are multiple reasons screen sharing may not be available, for example, if you are not in a meeting, no other participants are present, or if the moderator has disabled screen sharing.

Assuming screen sharing is available, Apple provides a piece of system UI to initiate screen sharing. This can be done using something like the following:

let pickerViewDiameter: CGFloat = 44
let pickerView = RPSystemBroadcastPickerView(frame: CGRect(x: 0, y: 0,
                                                           width: pickerViewDiameter,
                                                           height: pickerViewDiameter))
 
pickerView.preferredExtension = "Your Broadcast Upload Extension id"
 
// Microphone audio is passed through the main application instead of
// the broadcast extension.
pickerView.showsMicrophoneButton = false
 
view.addSubview(pickerView)
 
// Setup layout constraints

This creates a button that will bring up the system UX to initiate screen sharing. The "preferredExtension" property ensures that your app will receive the captured frames. Without it, the system will ask the user to choose which extension (there may be several installed on a user's device). That was quite a lot of setup, but at this stage, it should be possible to join a meeting, and if available, begin screen sharing.

Screen sharing can be stopped in several ways, through the SDK (see below), through the system control panel, or by tapping on the red status bar that iOS displays when screen sharing is active. Screen sharing works at the device level, and so will capture the screen even when your app is back-grounded. One caveat here - it is important that your app is still running in the background. This should already be the case as described in the initial get-started documentation for the SDK.

Next steps

Once screen sharing is active, you can stop it at any time using BJNVideo.stopScreenShare(). The SDK provides the following properties for you to observe:

  • contentShareAvailability - used to determine if screen sharing is allowed for the user in the current meeting.
  • contentShareExtensionStatus - identifies what set screen sharing is in currently.
  • contentShareStopReason - sharing can be stopped for a number of reasons, this property provides context to better inform the user.

Screen sharing can also be configured through an object conforming to ContentShareParametersProtocol as follows:

struct ContentShareParameters: ContentShareParametersProtocol {
    var requireConfirmationBeforeHijacking: Bool
    var messageProvider: MessageProvider = {( stopReason, availability ) -> String in return "Message for stop reason: 
                                            \(stopReason.rawValue) and availability: \(availability.rawValue)"}
}

If the requireConfirmationBeforeHijacking field is set to false, then initiating screen share will take over any existing screen share. If it is set to true, then the following will happen:

  • If no one is sharing, then screen sharing will begin as normal, otherwise:
    • Screen sharing will not start immediately.
    • The contentShareExtensionStatus property will instead change to .waitingForConfirmation.
    • At this stage, the user should be prompted to confirm they want to take over screen sharing from the other participant.
    • Based on the user response, the app should call either stopContentShare() or confirmContentShare().
    • If confirmContentShare() is called, screen sharing will begin, replacing the other participant's share.

The messageProvider variable allows the app to provide the user a meaningful alert if sharing is stopped for an unexpected reason (for example stopped by the moderator, or another user has taken over-sharing).