Add setRemoteSDP method

This commit is contained in:
Tiago Jacobs
2022-03-27 15:05:47 -03:00
parent ce5b8e8979
commit 6fce1d61f3
13 changed files with 131 additions and 14 deletions

View File

@@ -24,6 +24,10 @@
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSMicrophoneUsageDescription</key>
<string>Needs microphone access for streaming your voice when you're joined in full audio mode</string>
<key>NSCameraUsageDescription</key>
<string>Needs camera access for streaming your camera when you're sharing it</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>

View File

@@ -12,7 +12,8 @@ open class BBBSampleHandler : RPBroadcastSampleHandler {
// Logger (these messages are displayed in the console application)
private var logger = os.Logger(subsystem: "BigBlueButtonMobileSDK", category: "BBBSampleHandler")
private var appGroupName:String = "";
private var observer:NSKeyValueObservation?;
private var createOfferCallObserver:NSKeyValueObservation?;
private var setRemoteSDPCallObserver:NSKeyValueObservation?;
private var screenBroadcaster:ScreenBroadcaster?;
open func setAppGroupName(appGroupName:String) {
@@ -35,8 +36,8 @@ open class BBBSampleHandler : RPBroadcastSampleHandler {
self.screenBroadcaster = ScreenBroadcaster()
// Listen for createOffer requests from the UI APP
logger.info("Configuring observer")
self.observer = userDefaults.observe(\.createScreenShareOffer, options: [.new]) { (defaults, change) in
logger.info("Configuring observer for createOffer")
self.createOfferCallObserver = userDefaults.observe(\.createScreenShareOffer, options: [.new]) { (defaults, change) in
self.logger.info("Observer detected a createScreenShareOffer request!")
Task.init {
@@ -52,6 +53,26 @@ open class BBBSampleHandler : RPBroadcastSampleHandler {
}
}
}
logger.info("Configuring observer for setRemoteSDP")
self.setRemoteSDPCallObserver = userDefaults.observe(\.setScreenShareRemoteSDP, options: [.new]) { (defaults, change) in
let payload:String = (change.newValue!);
self.logger.info("Observer detected a setScreenShareRemoteSDP request with payload \(payload)")
let payloadData = payload.data(using: .utf8)!
let decodedPayload = (try? JSONDecoder().decode([String: String].self, from: payloadData))!
let sdp = decodedPayload["sdp"]
Task.init {
let remoteSDPDefined = await self.screenBroadcaster!.setRemoteSDP(remoteSDP: sdp!)
if(remoteSDPDefined){
self.logger.info("Remote SDP defined!")
BBBSharedData
.getUserDefaults(appGroupName: self.appGroupName)
.set(BBBSharedData.generatePayload(), forKey: BBBSharedData.SharedData.setScreenShareRemoteSDPCompleted)
}
}
}
}
open override func broadcastPaused() {

View File

@@ -29,4 +29,15 @@ open class ScreenBroadcaster {
}
}
public func setRemoteSDP(remoteSDP:String) async -> Bool {
do {
try await self.webRTCClient.setRemoteSDP(remoteSDP: remoteSDP)
return true
}
catch {
return false
}
}
}

View File

@@ -20,6 +20,8 @@ open class BBBSharedData {
public static let broadcastFinished = "broadcastFinished" // Broadcaster -> UI APP
public static let createScreenShareOffer = "createScreenShareOffer" // UI APP -> Broadcaster
public static let screenShareOfferCreated = "screenShareOfferCreated" // Broadcaster -> UI APP
public static let setScreenShareRemoteSDP = "setScreenShareRemoteSDP" // UI APP -> Broadcaster
public static let setScreenShareRemoteSDPCompleted = "setScreenShareRemoteSDPCompleted" // Broadcaster -> UI APP
}
// Get reference to userDefaults object (that's actually the object used to share information among UI APP and the BroadcastUploadExtension APP)

View File

@@ -34,5 +34,15 @@ extension UserDefaults {
@objc open dynamic var screenShareOfferCreated: String {
return string(forKey: BBBSharedData.SharedData.createScreenShareOffer) ?? ""
}
// UI APP -> Broadcaster
@objc open dynamic var setScreenShareRemoteSDP: String {
return string(forKey: BBBSharedData.SharedData.setScreenShareRemoteSDP) ?? ""
}
// Broadcaster -> UI APP
@objc open dynamic var setScreenShareRemoteSDPCompleted: String {
return string(forKey: BBBSharedData.SharedData.setScreenShareRemoteSDPCompleted) ?? ""
}
}

View File

@@ -7,6 +7,7 @@
import Foundation
import WebRTC
import os
protocol WebRTCClientDelegate: AnyObject {
func webRTCClient(_ client: WebRTCClient, didDiscoverLocalCandidate candidate: RTCIceCandidate)
@@ -14,6 +15,7 @@ protocol WebRTCClientDelegate: AnyObject {
}
open class WebRTCClient: NSObject {
private var logger = os.Logger(subsystem: "BigBlueButtonMobileSDK", category: "WebRTCClient")
// The `RTCPeerConnectionFactory` is in charge of creating new RTCPeerConnection instances.
// A new RTCPeerConnection should be created every new call, but the factory is shared.
@@ -76,10 +78,16 @@ open class WebRTCClient: NSObject {
return sdp
}
func set(remoteSdp: RTCSessionDescription, completion: @escaping (Error?) -> ()) {
self.peerConnection.setRemoteDescription(remoteSdp, completionHandler: completion)
public func setRemoteSDP(remoteSDP: String) async {
do {
let rtcSessionDescription = RTCSessionDescription(type: RTCSdpType.answer, sdp: remoteSDP)
try await self.peerConnection.setRemoteDescription(rtcSessionDescription)
} catch {
self.logger.error("Error setting remote SDP")
}
}
func set(remoteCandidate: RTCIceCandidate, completion: @escaping (Error?) -> ()) {
self.peerConnection.add(remoteCandidate, completionHandler: completion)
}
@@ -138,41 +146,41 @@ open class WebRTCClient: NSObject {
extension WebRTCClient: RTCPeerConnectionDelegate {
public func peerConnection(_ peerConnection: RTCPeerConnection, didChange stateChanged: RTCSignalingState) {
debugPrint("peerConnection new signaling state: \(stateChanged)")
self.logger.info("peerConnection new signaling state: \(stateChanged.rawValue)")
}
public func peerConnection(_ peerConnection: RTCPeerConnection, didAdd stream: RTCMediaStream) {
debugPrint("peerConnection did add stream \(stream)")
self.logger.info("peerConnection did add stream \(stream.streamId)")
}
public func peerConnection(_ peerConnection: RTCPeerConnection, didRemove stream: RTCMediaStream) {
debugPrint("peerConnection did remove stream \(stream)")
self.logger.info("peerConnection did remove stream \(stream.streamId)")
}
public func peerConnectionShouldNegotiate(_ peerConnection: RTCPeerConnection) {
debugPrint("peerConnection should negotiate")
self.logger.info("peerConnection should negotiate")
}
public func peerConnection(_ peerConnection: RTCPeerConnection, didChange newState: RTCIceConnectionState) {
debugPrint("peerConnection new connection state: \(newState)")
self.logger.info("peerConnection new connection state: \(newState.rawValue)")
self.delegate?.webRTCClient(self, didChangeConnectionState: newState)
}
public func peerConnection(_ peerConnection: RTCPeerConnection, didChange newState: RTCIceGatheringState) {
debugPrint("peerConnection new gathering state: \(newState)")
self.logger.info("peerConnection new gathering state: \(newState.rawValue)")
}
public func peerConnection(_ peerConnection: RTCPeerConnection, didGenerate candidate: RTCIceCandidate) {
debugPrint("peerConnection discovered new candidate")
self.logger.info("peerConnection discovered new candidate")
self.delegate?.webRTCClient(self, didDiscoverLocalCandidate: candidate)
}
public func peerConnection(_ peerConnection: RTCPeerConnection, didRemove candidates: [RTCIceCandidate]) {
debugPrint("peerConnection did remove candidate(s)")
self.logger.info("peerConnection did remove candidate(s)")
}
public func peerConnection(_ peerConnection: RTCPeerConnection, didOpen dataChannel: RTCDataChannel) {
debugPrint("peerConnection did open data channel")
self.logger.info("peerConnection did open data channel")
}
}

View File

@@ -17,6 +17,7 @@ open class BigBlueButtonSDK: NSObject {
private static var userDefaults:UserDefaults?
private static var observer1: NSKeyValueObservation?
private static var observer2: NSKeyValueObservation?
private static var observer3: NSKeyValueObservation?
public static func initialize(broadcastExtensionBundleId:String, appGroupName:String) {
self.broadcastExtensionBundleId = broadcastExtensionBundleId
@@ -44,6 +45,11 @@ open class BigBlueButtonSDK: NSObject {
ReactNativeEventEmitter.emitter.sendEvent(withName: ReactNativeEventEmitter.EVENT.onScreenShareOfferCreated.rawValue, body: sdp)
}
//setScreenShareRemoteSDPCompleted
observer3 = userDefaults?.observe(\.setScreenShareRemoteSDPCompleted, options: [.new]) { (defaults, change) in
logger.info("Detected a change in userDefaults for key setScreenShareRemoteSDPCompleted")
ReactNativeEventEmitter.emitter.sendEvent(withName: ReactNativeEventEmitter.EVENT.onSetScreenShareRemoteSDPCompleted.rawValue, body: nil)
}
}
public static func getBroadcastExtensionBundleId() -> String {

View File

@@ -19,6 +19,7 @@ open class ReactNativeEventEmitter: RCTEventEmitter {
case onBroadcastResumed = "onBroadcastResumed"
case onBroadcastFinished = "onBroadcastFinished"
case onScreenShareOfferCreated = "onScreenShareOfferCreated"
case onSetScreenShareRemoteSDPCompleted = "onSetScreenShareRemoteSDPCompleted"
}
override init() {

View File

@@ -11,4 +11,5 @@
RCT_EXTERN_METHOD(initializeScreenShare)
RCT_EXTERN_METHOD(createScreenShareOffer)
RCT_EXTERN_METHOD(setScreenShareRemoteSDP: (NSString *)remoteSDP)
@end

View File

@@ -39,4 +39,17 @@ class ScreenShareServiceManager: NSObject {
}
@objc func setScreenShareRemoteSDP(_ remoteSDP:String) -> Void {
logger.info("setScreenShareRemoteSDP call arrived on swift: \(remoteSDP)")
// Send request of "set remote SDP" to broadcast upload extension
// TIP - the handling of this method response is done in observer3 of BigBlueButtonSDK class
logger.info("setScreenShareRemoteSDP - persisting information on UserDefaults")
BBBSharedData
.getUserDefaults(appGroupName: BigBlueButtonSDK.getAppGroupName())
.set(BBBSharedData.generatePayload(properties: [
"sdp": remoteSDP
]), forKey: BBBSharedData.SharedData.setScreenShareRemoteSDP)
}
}

View File

@@ -0,0 +1,32 @@
import { setScreenShareRemoteSDP as nativeSetScreenShareRemoteSDP } from '../native-components/BBBN_ScreenShareService';
import nativeEmitter from '../native-messaging/emitter';
// Reference to the resolver of last call
let resolve = (value: unknown) => {
console.log(
`default resolve function called, this should never happen: ${value}`
);
};
// Resolve promise when SDP offer is available
nativeEmitter.addListener('onSetScreenShareRemoteSDPCompleted', () => {
resolve(undefined);
});
// Entry point of this method
function setScreenShareRemoteSDP(remoteSdp: string) {
return new Promise((res, rej) => {
// store the resolver for later call (when event is received)
resolve = res;
try {
console.log(`>nativeSetScreenShareRemoteSDP ${remoteSdp}`);
// call native swift method that triggers the broadcast popup
nativeSetScreenShareRemoteSDP(remoteSdp);
} catch (e) {
rej(`Call to nativeSetScreenShareRemoteSDP failed`);
}
});
}
export default setScreenShareRemoteSDP;

View File

@@ -9,3 +9,7 @@ export function initializeScreenShare() {
export function createScreenShareOffer() {
ScreenShareService.createScreenShareOffer();
}
export function setScreenShareRemoteSDP(remoteSDP: string) {
ScreenShareService.setScreenShareRemoteSDP(remoteSDP);
}

View File

@@ -2,6 +2,7 @@ import type { MutableRefObject } from 'react';
import type { WebView, WebViewMessageEvent } from 'react-native-webview';
import initializeScreenShare from '../methods/initializeScreenShare';
import createScreenShareOffer from '../methods/createScreenShareOffer';
import setScreenShareRemoteSDP from '../methods/setScreenShareRemoteSDP';
function observePromiseResult(
webViewRef: MutableRefObject<WebView>,
@@ -43,6 +44,9 @@ export function handleWebviewMessage(
case 'createOffer':
promise = createScreenShareOffer();
break;
case 'setRemoteDescription':
promise = setScreenShareRemoteSDP(data?.arguments[0].sdp);
break;
default:
throw `Unknown method ${data?.method}`;
}