From 9ffdd6f3291deb936b5d02fdf183fd40ae28ee70 Mon Sep 17 00:00:00 2001 From: davidliu Date: Thu, 15 Aug 2024 15:27:10 +0900 Subject: [PATCH] ios: Add helper methods to access RTCAudioSession.audioSessionDidActivate and deactivate --- Documentation/iOSInstallation.md | 27 ++++++++++++++++++++ ios/RCTWebRTC.xcodeproj/project.pbxproj | 4 +++ ios/RCTWebRTC/WebRTCModule+RTCAudioSession.m | 20 +++++++++++++++ src/RTCAudioSession.ts | 25 ++++++++++++++++++ src/index.ts | 2 ++ 5 files changed, 78 insertions(+) create mode 100644 ios/RCTWebRTC/WebRTCModule+RTCAudioSession.m create mode 100644 src/RTCAudioSession.ts diff --git a/Documentation/iOSInstallation.md b/Documentation/iOSInstallation.md index eb98961b0..b027ef74b 100644 --- a/Documentation/iOSInstallation.md +++ b/Documentation/iOSInstallation.md @@ -26,6 +26,33 @@ Navigate to `/ios//` and edit `Info.plist`, add the Microphone permission description ``` +## CallKit + +If your app uses a CallKit integration to handle incoming calls, then your +CXProviderDelegate should call through to `RTCAudioSession.sharedInstance.audioSessionDidActivate/Deactivate` accordingly. + +``` +#import + +- (void) provider:(CXProvider *) provider didActivateAudioSession:(AVAudioSession *) audioSession { + [[RTCAudioSession sharedInstance] audioSessionDidActivate:[AVAudioSession sharedInstance]]; +} + +- (void) provider:(CXProvider *) provider didDeactivateAudioSession:(AVAudioSession *) audioSession { + [[RTCAudioSession sharedInstance] audioSessionDidDeactivate:[AVAudioSession sharedInstance]]; +} +``` + +Javascript methods are also provided to call these methods: + +``` +import { RTCAudioSession } from '@livekit/react-native-webrtc' + +// Call as needed. +RTCAudioSession.audioSessionDidActivate(); +RTCAudioSession.audioSessionDidDeactivate(); +``` + ## Library not loaded/Code signature invalid This is an issue with iOS 13.3.1. diff --git a/ios/RCTWebRTC.xcodeproj/project.pbxproj b/ios/RCTWebRTC.xcodeproj/project.pbxproj index 7c4e2bd7d..49e26d1ce 100644 --- a/ios/RCTWebRTC.xcodeproj/project.pbxproj +++ b/ios/RCTWebRTC.xcodeproj/project.pbxproj @@ -24,6 +24,7 @@ 4EE3A8D425B841DD00FAA24A /* ScreenCapturer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EE3A8CD25B841DD00FAA24A /* ScreenCapturer.m */; }; D3FF699919D2664B25C9D458 /* Pods_RCTWebRTC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A20F721AD842563B66292D5B /* Pods_RCTWebRTC.framework */; }; D74EF94829652169000742E1 /* TrackCapturerEventsEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = D74EF94629652169000742E1 /* TrackCapturerEventsEmitter.m */; }; + D7F0711E2C6DC91F0031F594 /* WebRTCModule+RTCAudioSession.m in Sources */ = {isa = PBXBuildFile; fileRef = D7F0711D2C6DC91F0031F594 /* WebRTCModule+RTCAudioSession.m */; }; DEC96577264176C10052DB35 /* DataChannelWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = DEC96576264176C10052DB35 /* DataChannelWrapper.m */; }; /* End PBXBuildFile section */ @@ -75,6 +76,7 @@ D74EF94529652148000742E1 /* CapturerEventsDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CapturerEventsDelegate.h; path = RCTWebRTC/CapturerEventsDelegate.h; sourceTree = SOURCE_ROOT; }; D74EF94629652169000742E1 /* TrackCapturerEventsEmitter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TrackCapturerEventsEmitter.m; path = RCTWebRTC/TrackCapturerEventsEmitter.m; sourceTree = SOURCE_ROOT; }; D74EF94729652169000742E1 /* TrackCapturerEventsEmitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TrackCapturerEventsEmitter.h; path = RCTWebRTC/TrackCapturerEventsEmitter.h; sourceTree = SOURCE_ROOT; }; + D7F0711D2C6DC91F0031F594 /* WebRTCModule+RTCAudioSession.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "WebRTCModule+RTCAudioSession.m"; path = "RCTWebRTC/WebRTCModule+RTCAudioSession.m"; sourceTree = SOURCE_ROOT; }; D7F99C122938F4E0000A2450 /* WebRTCModule+RTCMediaStream.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "WebRTCModule+RTCMediaStream.h"; path = "RCTWebRTC/WebRTCModule+RTCMediaStream.h"; sourceTree = SOURCE_ROOT; }; DEC96576264176C10052DB35 /* DataChannelWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = DataChannelWrapper.m; path = RCTWebRTC/DataChannelWrapper.m; sourceTree = ""; }; DEC96579264176DF0052DB35 /* DataChannelWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DataChannelWrapper.h; path = RCTWebRTC/DataChannelWrapper.h; sourceTree = ""; }; @@ -131,6 +133,7 @@ 4EE3A8AF25B8413200FAA24A /* VideoCaptureController.h */, 0BDDA6DF20C18B6B00B38B45 /* VideoCaptureController.m */, 4EE3A8B525B8414A00FAA24A /* WebRTCModule+Permissions.m */, + D7F0711D2C6DC91F0031F594 /* WebRTCModule+RTCAudioSession.m */, 4EE3A8B825B8415900FAA24A /* WebRTCModule+RTCDataChannel.h */, 4EE3A8B925B8415900FAA24A /* WebRTCModule+RTCDataChannel.m */, D7F99C122938F4E0000A2450 /* WebRTCModule+RTCMediaStream.h */, @@ -262,6 +265,7 @@ 4EC498BC25B8777F00E76218 /* ScreenCapturePickerViewManager.m in Sources */, 4EE3A8B225B8414000FAA24A /* WebRTCModule.m in Sources */, 4EE3A8D225B841DD00FAA24A /* CaptureController.m in Sources */, + D7F0711E2C6DC91F0031F594 /* WebRTCModule+RTCAudioSession.m in Sources */, D74EF94829652169000742E1 /* TrackCapturerEventsEmitter.m in Sources */, 4EE3A8D125B841DD00FAA24A /* SocketConnection.m in Sources */, 4EE3A8BD25B8416500FAA24A /* WebRTCModule+RTCMediaStream.m in Sources */, diff --git a/ios/RCTWebRTC/WebRTCModule+RTCAudioSession.m b/ios/RCTWebRTC/WebRTCModule+RTCAudioSession.m new file mode 100644 index 000000000..cd4fa138c --- /dev/null +++ b/ios/RCTWebRTC/WebRTCModule+RTCAudioSession.m @@ -0,0 +1,20 @@ +#import + +#import +#import + +#import "WebRTCModule.h" + +@implementation WebRTCModule (RTCAudioSession) + +RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(audioSessionDidActivate) { + [[RTCAudioSession sharedInstance] audioSessionDidActivate:[AVAudioSession sharedInstance]]; + return nil; +} + +RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(audioSessionDidDeactivate) { + [[RTCAudioSession sharedInstance] audioSessionDidDeactivate:[AVAudioSession sharedInstance]]; + return nil; +} + +@end diff --git a/src/RTCAudioSession.ts b/src/RTCAudioSession.ts new file mode 100644 index 000000000..fccc9b6d1 --- /dev/null +++ b/src/RTCAudioSession.ts @@ -0,0 +1,25 @@ +import { NativeModules, Platform } from 'react-native'; + +const { WebRTCModule } = NativeModules; + +export default class RTCAudioSession { + /** + * To be called when CallKit activates the audio session. + */ + static audioSessionDidActivate() { + // Only valid for iOS + if (Platform.OS === "ios") { + WebRTCModule.audioSessionDidActivate() + } + } + + /** + * To be called when CallKit deactivates the audio session. + */ + static audioSessionDidDeactivate() { + // Only valid for iOS + if (Platform.OS === "ios") { + WebRTCModule.audioSessionDidDeactivate() + } + } +} diff --git a/src/index.ts b/src/index.ts index b495f3d4e..e47c0042f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,6 +15,7 @@ import MediaStream from './MediaStream'; import MediaStreamTrack from './MediaStreamTrack'; import MediaStreamTrackEvent from './MediaStreamTrackEvent'; import permissions from './Permissions'; +import RTCAudioSession from './RTCAudioSession'; import RTCErrorEvent from './RTCErrorEvent'; import RTCIceCandidate from './RTCIceCandidate'; import RTCPeerConnection from './RTCPeerConnection'; @@ -40,6 +41,7 @@ export { RTCRtpReceiver, RTCRtpSender, RTCErrorEvent, + RTCAudioSession, MediaStream, MediaStreamTrack, mediaDevices,