Skip to content

Commit aa0a21d

Browse files
ladvochiroshihorie
andauthored
Simplify broadcast extension setup with standard format for identifiers (livekit#573)
When configuring a broadcast extension, manually setting the info keys `RTCAppGroupIdentifier` and `RTCScreenSharingExtension` is no longer required when using the standard format. The standard format is as follows: - App group: `group.<main-app-bundle-id>` - Broadcast extension: `<main-app-bundle-id>.broadcast` --------- Co-authored-by: Hiroshi Horie <[email protected]>
1 parent c3ee701 commit aa0a21d

File tree

4 files changed

+45
-21
lines changed

4 files changed

+45
-21
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
patch type="change" "Simplify broadcast extension setup with standard format for identifiers"

Docs/ios-screen-sharing.md

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,17 @@ flowchart LR
4444

4545
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.
4646

47-
#### 1. Add Broadcast Upload Extension Target
4847

48+
#### 1. Add Broadcast Upload Extension Target
4949

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

5252
1. In Xcode, Choose "File" > "New > "Target"
5353
2. From the template chooser, select "Broadcast Upload Extension"
54-
3. Name the extension (e.g. "BroadcastExtension"). Take note of the extension's bundle identifier, as it will be needed later.
55-
4. Replace the default content of `SampleHandler.swift` in the new target with the following:
54+
3. Name the extension (e.g. "BroadcastExtension").
55+
4. Press "Finish"
56+
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.
57+
6. Replace the default content of `SampleHandler.swift` in the new target with the following:
5658

5759
```swift
5860
import LiveKit
@@ -75,14 +77,9 @@ In order for the broadcast extension to communicate with your app, they must be
7577
2. Select the "Signing & Capabilities" tab and press the "+ Capability" button.
7678
3. Add the "App Groups" capability.
7779
4. Press "+" to add a new app group.
78-
5. Enter an app group identifier in the format `group.<domain>.<group_name>`. Be sure to use the same identifier for both targets.
79-
80-
#### 3. Add Properties to Info.plist
81-
82-
1. Set `RTCAppGroupIdentifier` in the Info.plist of **both targets** to the group identifier from the previous step.
83-
2. Set `RTCScreenSharingExtension` in the Info.plist of your **primary app target** to the broadcast extension's bundle identifier.
80+
5. Add the target to the group `group.<main-app-bundle-id>`. To use a custom identifier, see *[Custom Identifiers](#custom-identifiers)* below.
8481

85-
#### 4. Begin Screen Share
82+
#### 3. Begin Screen Share
8683

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

103100
### Advanced Usage
104101

102+
#### Manual Track Publication
103+
105104
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`:
106105

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

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

114-
#### Combine Publisher
113+
##### Combine Publisher
115114
```swift
116115
let subscription = BroadcastManager.shared
117116
.isBroadcastingPublisher
@@ -120,7 +119,7 @@ let subscription = BroadcastManager.shared
120119
}
121120
```
122121

123-
#### Delegate
122+
##### Delegate
124123
```swift
125124
class MyDelegate: BroadcastManagerDelegate {
126125
func broadcastManager(didChangeState isBroadcasting: Bool) {
@@ -129,3 +128,8 @@ class MyDelegate: BroadcastManagerDelegate {
129128
}
130129
BroadcastManager.shared.delegate = MyDelegate()
131130
```
131+
132+
#### Custom Identifiers
133+
134+
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`.
135+
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.

Sources/LiveKit/Broadcast/BroadcastBundleInfo.swift

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,19 @@ import Foundation
2020

2121
enum BroadcastBundleInfo {
2222
/// Identifier of the app group shared by the primary app and broadcast extension.
23-
@BundleInfo("RTCAppGroupIdentifier")
24-
static var groupIdentifier: String?
25-
23+
static var groupIdentifier: String? {
24+
if let override = groupIdentifierOverride { return override }
25+
guard let bundleIdentifier = Bundle.main.bundleIdentifier else { return nil }
26+
let appBundleIdentifier = bundleIdentifier.dropSuffix(".\(extensionSuffix)") ?? bundleIdentifier
27+
return "group.\(appBundleIdentifier)"
28+
}
29+
2630
/// Bundle identifier of the broadcast extension.
27-
@BundleInfo("RTCScreenSharingExtension")
28-
static var screenSharingExtension: String?
31+
static var screenSharingExtension: String? {
32+
if let override = screenSharingExtensionOverride { return override }
33+
guard let bundleIdentifier = Bundle.main.bundleIdentifier else { return nil }
34+
return "\(bundleIdentifier).\(extensionSuffix)"
35+
}
2936

3037
/// Path to the socket file used for interprocess communication.
3138
static var socketPath: String? {
@@ -37,7 +44,14 @@ enum BroadcastBundleInfo {
3744
static var hasExtension: Bool {
3845
socketPath != nil && screenSharingExtension != nil
3946
}
47+
48+
@BundleInfo("RTCAppGroupIdentifier")
49+
private static var groupIdentifierOverride: String?
4050

51+
@BundleInfo("RTCScreenSharingExtension")
52+
private static var screenSharingExtensionOverride: String?
53+
54+
private static let extensionSuffix = "broadcast"
4155
private static let socketFileDescriptor = "rtc_SSFD"
4256

4357
private static func socketPath(for groupIdentifier: String) -> String? {
@@ -48,4 +62,12 @@ enum BroadcastBundleInfo {
4862
}
4963
}
5064

65+
private extension String {
66+
func dropSuffix(_ suffix: String) -> Self? {
67+
guard hasSuffix(suffix) else { return nil }
68+
let trailingIndex = index(endIndex, offsetBy: -suffix.count)
69+
return String(self[..<trailingIndex])
70+
}
71+
}
72+
5173
#endif

Sources/LiveKit/Broadcast/BundleInfo.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,7 @@ struct BundleInfo<Value>: Sendable {
2828
}
2929

3030
var wrappedValue: Value? {
31-
guard let value = bundle.infoDictionary?[key] as? Value else {
32-
logger.warning("Missing bundle property with key `\(key)`")
33-
return nil
34-
}
31+
guard let value = bundle.infoDictionary?[key] as? Value else { return nil }
3532
return value
3633
}
3734
}

0 commit comments

Comments
 (0)