Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify broadcast extension setup with standard format for identifiers #573

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .nanpa/broadcast-identifier-defaults.kdl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
patch type="change" "Simplify broadcast extension setup with standard format for identifiers"
28 changes: 16 additions & 12 deletions Docs/ios-screen-sharing.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,17 @@ flowchart LR

To use the Broadcast Capture mode, follow these steps to add a Broadcast Upload Extension target and associated configuration to your project. You can also refer to the [example app](https://github.com/livekit-examples/swift-example), which demonstrates this configuration.

#### 1. Add Broadcast Upload Extension Target

#### 1. Add Broadcast Upload Extension Target

<img src="Resources/new-target-options.png" width="500" />

1. In Xcode, Choose "File" > "New > "Target"
2. From the template chooser, select "Broadcast Upload Extension"
3. Name the extension (e.g. "BroadcastExtension"). Take note of the extension's bundle identifier, as it will be needed later.
4. Replace the default content of `SampleHandler.swift` in the new target with the following:
3. Name the extension (e.g. "BroadcastExtension").
4. Press "Finish"
5. From the "Signing & Capabilities" tab of the new target, change the bundle identifier to be the same as your main app with `.broadcast` added to the end. To use a custom identifier, see *[Custom Identifiers](#custom-identifiers)* below.
6. Replace the default content of `SampleHandler.swift` in the new target with the following:

```swift
import LiveKit
Expand All @@ -75,14 +77,9 @@ In order for the broadcast extension to communicate with your app, they must be
2. Select the "Signing & Capabilities" tab and press the "+ Capability" button.
3. Add the "App Groups" capability.
4. Press "+" to add a new app group.
5. Enter an app group identifier in the format `group.<domain>.<group_name>`. Be sure to use the same identifier for both targets.

#### 3. Add Properties to Info.plist

1. Set `RTCAppGroupIdentifier` in the Info.plist of **both targets** to the group identifier from the previous step.
2. Set `RTCScreenSharingExtension` in the Info.plist of your **primary app target** to the broadcast extension's bundle identifier.
5. Add the target to the group `group.<main-app-bundle-id>`. To use a custom identifier, see *[Custom Identifiers](#custom-identifiers)* below.

#### 4. Begin Screen Share
#### 3. Begin Screen Share

With setup of the broadcast extension complete, broadcast capture will be used by default when enabling screen share:
```swift
Expand All @@ -102,6 +99,8 @@ While running your app in a debug session in Xcode, check the debug console for

### Advanced Usage

#### Manual Track Publication

When using broadcast capture, a broadcast can be initiated externally (for example, via control center). By default, when a broadcast begins, the local participant automatically publishes a screen share track. In some cases, however, you may want to handle track publication manually. You can achieve this by using `BroadcastManager`:

First, disable automatic track publication:
Expand All @@ -111,7 +110,7 @@ BroadcastManager.shared.shouldPublishTrack = false

Then, use one of the two methods for detecting changes in the broadcast state:

#### Combine Publisher
##### Combine Publisher
```swift
let subscription = BroadcastManager.shared
.isBroadcastingPublisher
Expand All @@ -120,7 +119,7 @@ let subscription = BroadcastManager.shared
}
```

#### Delegate
##### Delegate
```swift
class MyDelegate: BroadcastManagerDelegate {
func broadcastManager(didChangeState isBroadcasting: Bool) {
Expand All @@ -129,3 +128,8 @@ class MyDelegate: BroadcastManagerDelegate {
}
BroadcastManager.shared.delegate = MyDelegate()
```

#### Custom Identifiers

By default, the app group identifier is expected to be `group.<main-app-bundle-id>`, and the broadcast extension's bundle identifier is expected to be `<main-app-bundle-id>.broadcast`.
To override these values, set `RTCAppGroupIdentifier` in Info.plist for both targets (both broadcast extension and main app), and set `RTCScreenSharingExtension` in Info.plist for your main app.
32 changes: 27 additions & 5 deletions Sources/LiveKit/Broadcast/BroadcastBundleInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,19 @@ import Foundation
final class BroadcastBundleInfo {

/// Identifier of the app group shared by the primary app and broadcast extension.
@BundleInfo("RTCAppGroupIdentifier")
static var groupIdentifier: String?

static var groupIdentifier: String? {
if let override = groupIdentifierOverride { return override }
guard let bundleIdentifier = Bundle.main.bundleIdentifier else { return nil }
let appBundleIdentifier = bundleIdentifier.dropSuffix(".\(extensionSuffix)") ?? bundleIdentifier
return "group.\(appBundleIdentifier)"
}

/// Bundle identifier of the broadcast extension.
@BundleInfo("RTCScreenSharingExtension")
static var screenSharingExtension: String?
static var screenSharingExtension: String? {
if let override = screenSharingExtensionOverride { return override }
guard let bundleIdentifier = Bundle.main.bundleIdentifier else { return nil }
return "\(bundleIdentifier).\(extensionSuffix)"
}

/// Path to the socket file used for interprocess communication.
static var socketPath: String? {
Expand All @@ -38,7 +45,14 @@ final class BroadcastBundleInfo {
static var hasExtension: Bool {
socketPath != nil && screenSharingExtension != nil
}

@BundleInfo("RTCAppGroupIdentifier")
private static var groupIdentifierOverride: String?

@BundleInfo("RTCScreenSharingExtension")
private static var screenSharingExtensionOverride: String?

private static let extensionSuffix = "broadcast"
private static let socketFileDescriptor = "rtc_SSFD"

private static func socketPath(for groupIdentifier: String) -> String? {
Expand All @@ -49,4 +63,12 @@ final class BroadcastBundleInfo {
}
}

private extension String {
func dropSuffix(_ suffix: String) -> Self? {
guard hasSuffix(suffix) else { return nil }
let trailingIndex = index(endIndex, offsetBy: -suffix.count)
return String(self[..<trailingIndex])
}
}

#endif
5 changes: 1 addition & 4 deletions Sources/LiveKit/Broadcast/BundleInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ struct BundleInfo<Value>: Sendable {
}

var wrappedValue: Value? {
guard let value = bundle.infoDictionary?[key] as? Value else {
logger.warning("Missing bundle property with key `\(key)`")
return nil
}
guard let value = bundle.infoDictionary?[key] as? Value else { return nil }
return value
}
}
Loading