Screen sharing 2.x - Bandyer/Bandyer-iOS-SDK GitHub Wiki

Table of contents

In app screen sharing

The BandyerSDK supports sharing the app screen during a video call since 1.4.0 version. This tool allows users to stream video of the app screen using and managing an Apple's RPScreenRecorder object internally. This tool is enabled by default and it will be available to the user in the "share" menu while performing a call. Starting from version 2.2.0 the tool can be disabled before initialising the BandyerSDK.

The following snippets of code are going to show how to disable the tool:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        let config = Config()
        config.environment = .sandbox
        config.inAppScreensharingConfiguration = InAppScreensharingToolConfiguration.disabled()

        BandyerSDK.instance().initialize(withApplicationId: "PUT_YOUR_APP_ID_HERE", config: config)

        return true
    }
}
@interface AppDelegate ()
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    BDKConfig *config = [BDKConfig new];
    config.environment = BDKEnvironment.sandbox;
    config.inAppScreensharingConfiguration = [BDKInAppScreensharingToolConfiguration disabled];

    [BandyerSDK.instance initializeWithApplicationId:@"PUT YOUR APP ID HERE" config:config];

    return YES;
}

@end

Broadcast screen sharing

Starting from version 2.1.0 the BandyerSDK provides support for sharing the whole user's device screen during a video call. In order to enable the feature in your app, you are required to create an app extension. On iOS, only Broadcast upload app extensions can record the user's device screen, but don't worry we got you covered, in this document we will guide you through the process of creating your broadcast upload app extension and we will show you how you can enable this feature in your app with the BandyerSDK. The broadcast screen sharing feature is an optional feature, if you don't plan to provide this functionality in your app, you can skip this guide altogether.

Sections

Broadcast upload extension

The first thing you must do in order to enable the broadcast screen sharing in your app is to create a Broadcast upload app extension.

Creating an upload extension

Open your app project in Xcode and select your app project file in the project navigation panel, then click on the "+" icon in the editor lower left corner like you'd do for adding a new target. The following dialog panel should have appear on your screen:

Add upload extension target

Select "Broadcast Upload Extension", then click next

Add upload extension target

Give your extension a name then click "Finish".

Extension bundle identifier

Click on your project file in the project navigator panel, then select the BroadcastUpload extension target and select the "General" tab in the main editor window. Make sure the extension bundle identifier have a prefix consisting of their containing application's bundle identifier followed by a '.' plus some other name. Failing to do will result in a validation error when you try to upload your app to the App store. Let's quickly look at an example showing how the bundle identifier of your app extension should be formatted. Let's pretend your application bundle identifier is com.acme.MyWonderfulApp, let's also pretend your application extension name is MyExtension, then the application extension bundle identifier would be com.acme.MyWonderfulApp.MyExtension.

Bundle display name

As a final step we strongly suggest you to change the Bundle display name of your app extension in the Info.plist file to the name of your app. The value provided to that key in the Info.plist file will be shown to the user when she / he requests to start a screen sharing, so it is important that your user can quickly identify your app in the system provided picker. Congratulations, you have now created an app extension that will be shipped with your app.

Bandyer Broadcast Extension Framework

The Bandyer BandyerBroadcastExtension.framework is a standalone binary framework that enables a bidirectional communication between your Upload extension and the Bandyer.framework embedded in your app and viceversa. This framework must be used by your app extension, it will take care of the lifecycle of the extension responding to the extension events and it will communicate with the BandyerSDK embedded in your app coordinating the screen recording broadcasting during a video call.

Requirements

The BandyerBroadcastExtension.framework requires iOS 12.0 and Swift 5.1. The BandyerSDK and the BandyerBroadcastExtension must have compatible versions in order to communicate properly, the following table lists every version of the BandyerSDK and its compatible BandyerBroadcastExtension version

BandyerSDK BroadcastExtensionFramework
3.0.0-beta 1.1.0
2.10.0 1.1.0
2.9.0 1.1.0
2.8.0 1.1.0
2.7.0 1.1.0
2.6.0 1.1.0
2.5.1 1.0.0
2.5.0 1.0.0
2.4.1 1.0.0
2.4.0 1.0.0
2.3.0 1.0.0
2.2.0 1.0.0
2.1.2 1.0.0
2.1.1 1.0.0
2.1.0 1.0.0
2.0.0 1.0.0-beta
1.x.x Not supported

Installation

The BandyerBroadcastExtension.framework must be linked to your app extension and embedded in your app bundle. Several installation methods are supported. Cocoapods is the most straightforward way to add the framework to your project.

Cocoapods

Let's pretend you have the following Podfile listing all the dependencies of your app, let's also say your app is called MyApp for simplicity sake:

target 'MyApp' do
  use_frameworks!
  platform :ios, '10.0'
  
  pod 'Bandyer', '~> 2.1'
  # A bunch of other dependencies
  
end

After you have created your app extension target (let's pretend your target is called "UploadExtension") you should update your Podfile as well:

target 'MyApp' do
  use_frameworks!
  platform :ios, '10.0'
  
  pod 'Bandyer', '~> 2.1'
  # A bunch of other dependencies
  
end

target 'UploadExtension' do
  use_frameworks!
  platform :ios, '12.0'
  
  pod 'BandyerBroadcastExtension', '~> 1.0'
end

Before running pod install in the terminal make sure you changed 'UploadExtension' with the name of your broadcast upload extension target in your Podfile. Then from the terminal run the following command:

pod install

App group

The BandyerSDK and the BandyerBroadcastExtension must have access to a shared app group in order to be able to communicate. If your app does not have one, you must create it from your account on the Apple developer site or from Xcode.

What's an app group?

Security app groups allows multiple apps produced by a single development team to access shared containers and communicate using inteprocess communication. An app group is identified by an app group identifier. App group identifiers have the following format group.<group name> where <group name> can be anything you want, but it is convention to use the bundle identifier of your app or a reverse DNS format of your organization. For example, let's pretend your app bundle identifier is com.acme.MyWonderfulApp, then the app group identifier would be group.com.acme.MyWonderfulApp. When your app or any of your app extension is added to an app group, you must re-generate your provisioning profile bound to the target bundle identifier. Don't worry if you rely on Xcode it'll do that for you.

App group entitlement

Open Xcode and select your project file, then in the editor panel select your app target and click on the "Signing and capabilities" tab.

Target entitlement 1

Click on the "+ Capability" and select "App groups", if the "App Groups" entry is not displayed like in the image above, otherwise go to next step.

If you don't have created an App group yet, click on the small "+" icon in the "App groups" entry and follow the Xcode wizard that will guide you through the process of creating an "App group". Once you've done it, the "App groups" entry should list all the app groups associated with your app, make sure at least one is selected. If everything went fine, Xcode should have created an entitlements file, or updated the existing one, adding an app group entry to the file.

Target entitlement 2

Then select the app extension target and do the same thing for this target, this time tough you should not create the app group because one has been already created. Again, if everything went fine, Xcode should have created another entitlement file, this time for the app extension, listing the app group entry.

RPBroadcastSampleHandler subclass

The last step you are required to do in order to have a fully fledged broadcast upload extension is to implement a RPBroadcastSampleHandler subclass. As you might have noticed when you created the Upload extension target, Xcode added a SampleHandler.swift file or a SampleHandler.h and a SampleHandler.m files (depending on which programming language you have choosen when creating the target) to your project. Open your implementation file and replace the Xcode template implementation with the following:

import ReplayKit
import BandyerBroadcastExtension

class SampleHandler: RPBroadcastSampleHandler {

    override func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?) {
        #error("Please replace APP_GROUP_IDENTIFIER_GOES_HERE placeholder with your app group identifier")
        BroadcastExtension.instance.start(appGroupIdentifier: "APP_GROUP_IDENTIFIER_GOES_HERE", setupInfo: setupInfo) { [weak self] error in
            self?.finishBroadcastWithError(error)
        }
    }
    
    override func broadcastPaused() {
        BroadcastExtension.instance.pause()
    }
    
    override func broadcastResumed() {
        BroadcastExtension.instance.resume()
    }
    
    override func broadcastFinished() {
        BroadcastExtension.instance.finish()
    }
    
    override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
        BroadcastExtension.instance.process(sampleBuffer: sampleBuffer, ofType: sampleBufferType)
    }
}
#import "SampleHandler.h"

#import <BandyerBroadcastExtension/BandyerBroadcastExtension.h>

@implementation SampleHandler

- (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *,NSObject *> *)setupInfo
{
#error "Replace APP_GROUP_IDENTIFIER_GOES_HERE placeholder with your app group identifier"
    __weak __typeof__(self) _wself = self;
    [BBEBroadcastExtension.instance startWithAppGroupIdentifier:@"APP_GROUP_IDENTIFIER_GOES_HERE" setupInfo:setupInfo errorHandler:^(NSError * _Nonnull error) {
        __strong __typeof__(_wself) sself = _wself;
        [sself finishBroadcastWithError:error];
    }];
}

- (void)broadcastPaused
{
    [BBEBroadcastExtension.instance pause];
}

- (void)broadcastResumed
{
    [BBEBroadcastExtension.instance resume];
}

- (void)broadcastFinished
{
    [BBEBroadcastExtension.instance finish];
}

- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType
{
    [BBEBroadcastExtension.instance processSampleBuffer:sampleBuffer ofType:sampleBufferType];
}

@end

Replace the APP_GROUP_IDENTIFIER_GOES_HERE string with your app group identifier and you're done!

Broadcast screensharing tool configuration

The very last step you must do in order to enable the feature in your app is to provide a BDKBroadcastScreensharingToolConfiguration object to the BDKConfig object you provide to the BandyerSDK when you initialize it. The following snippet of code shows you how to enable the broadcast screensharing tool:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        let config = Config()
        config.environment = .sandbox

        if #available(iOS 12.0, *) {
            // This configuration object enable the sdk to talk with the broadcast extension
            // You must provide the app group identifier used by your app and the upload extension bundle identifier
            #error("Please replace APP_GROUP_IDENTIFIER_GOES_HERE with your app group identifier")
            #error("Please replace UPLOAD_EXTENSION_BUNDLE_IDENTIFIER_GOES_HERE with your upload extension bundle identifier")
            config.broadcastScreensharingConfiguration = BroadcastScreensharingToolConfiguration.enabled(appGroupIdentifier: "APP_GROUP_IDENTIFIER_GOES_HERE",
                                                                                                         broadcastExtensionBundleIdentifier: "UPLOAD_EXTENSION_BUNDLE_IDENTIFIER_GOES_HERE")
        }

        BandyerSDK.instance().initialize(withApplicationId: "PUT_YOUR_APP_ID_HERE", config: config)

        return true
    }
}
@interface AppDelegate ()
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    BDKConfig *config = [BDKConfig new];
    config.environment = BDKEnvironment.sandbox;

    if (@available(iOS 12.0, *))
    {
#error("Please replace APP_GROUP_IDENTIFIER_GOES_HERE with your app group identifier")
#error("Please replace EXTENSION_BUNDLE_IDENTIFIER_GOES_HERE with your upload extension bundle identifier")
        // This configuration object enable the sdk to talk with the broadcast extension
        config.broadcastScreensharingConfiguration = [BDKBroadcastScreensharingToolConfiguration
                                                      enabledWithAppGroupIdentifier:@"APP_GROUP_IDENTIFIER_GOES_HERE"
                                                      broadcastExtensionBundleIdentifier:@"EXTENSION_BUNDLE_IDENTIFIER_GOES_HERE"];
    }

    [BandyerSDK.instance initializeWithApplicationId:@"PUT YOUR APP ID HERE" config:config];

    return YES;
}

@end

Make sure to replace the app group and the extension bundle identifiers with your own.

Sample app

We created two apps, one in objective-c and one in swift to show you how to integrate the BandyerBroadcastExtension in a real app

⚠️ **GitHub.com Fallback** ⚠️