@stream-io/video-react-native-sdk 1.27.4 → 1.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/android/src/main/java/com/streamvideo/reactnative/audio/AudioDeviceManager.kt +19 -11
- package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioFocusUtil.kt +23 -9
- package/android/src/main/java/com/streamvideo/reactnative/callmanager/StreamInCallManagerModule.kt +48 -14
- package/dist/commonjs/index.js +2 -0
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/modules/call-manager/CallManager.js +5 -0
- package/dist/commonjs/modules/call-manager/CallManager.js.map +1 -1
- package/dist/commonjs/utils/internal/registerSDKGlobals.js +34 -0
- package/dist/commonjs/utils/internal/registerSDKGlobals.js.map +1 -0
- package/dist/commonjs/utils/push/setupIosCallKeepEvents.js +44 -0
- package/dist/commonjs/utils/push/setupIosCallKeepEvents.js.map +1 -1
- package/dist/commonjs/version.js +1 -1
- package/dist/module/index.js +2 -0
- package/dist/module/index.js.map +1 -1
- package/dist/module/modules/call-manager/CallManager.js +5 -0
- package/dist/module/modules/call-manager/CallManager.js.map +1 -1
- package/dist/module/utils/internal/registerSDKGlobals.js +28 -0
- package/dist/module/utils/internal/registerSDKGlobals.js.map +1 -0
- package/dist/module/utils/push/setupIosCallKeepEvents.js +44 -0
- package/dist/module/utils/push/setupIosCallKeepEvents.js.map +1 -1
- package/dist/module/version.js +1 -1
- package/dist/typescript/index.d.ts.map +1 -1
- package/dist/typescript/modules/call-manager/CallManager.d.ts +2 -0
- package/dist/typescript/modules/call-manager/CallManager.d.ts.map +1 -1
- package/dist/typescript/modules/call-manager/types.d.ts +1 -0
- package/dist/typescript/modules/call-manager/types.d.ts.map +1 -1
- package/dist/typescript/utils/internal/registerSDKGlobals.d.ts +2 -0
- package/dist/typescript/utils/internal/registerSDKGlobals.d.ts.map +1 -0
- package/dist/typescript/utils/push/setupIosCallKeepEvents.d.ts.map +1 -1
- package/dist/typescript/version.d.ts +1 -1
- package/ios/StreamInCallManager.m +4 -0
- package/ios/StreamInCallManager.swift +213 -88
- package/package.json +7 -7
- package/src/index.ts +2 -0
- package/src/modules/call-manager/CallManager.ts +5 -0
- package/src/modules/call-manager/native-module.d.ts +11 -0
- package/src/modules/call-manager/types.ts +1 -0
- package/src/utils/internal/registerSDKGlobals.ts +30 -0
- package/src/utils/push/setupIosCallKeepEvents.ts +49 -0
- package/src/version.ts +1 -1
- package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioSetupStoreUtil.kt +0 -41
|
@@ -91,6 +91,8 @@ export class CallManager {
|
|
|
91
91
|
* @param config.deviceEndpointType The default audio device endpoint type to set. It can be one of the following:
|
|
92
92
|
* - `'speaker'`: (Default) For normal video or voice calls.
|
|
93
93
|
* - `'earpiece'`: For voice-only mobile call type scenarios.
|
|
94
|
+
*
|
|
95
|
+
* @param config.enableStereoAudioOutput Whether to enable stereo audio output. Only supported for listener audio role.
|
|
94
96
|
*/
|
|
95
97
|
start = (config?: StreamInCallManagerConfig): void => {
|
|
96
98
|
NativeManager.setAudioRole(config?.audioRole ?? 'communicator');
|
|
@@ -98,6 +100,9 @@ export class CallManager {
|
|
|
98
100
|
const type = config.deviceEndpointType ?? 'speaker';
|
|
99
101
|
NativeManager.setDefaultAudioDeviceEndpointType(type);
|
|
100
102
|
}
|
|
103
|
+
if (config?.audioRole === 'listener' && config.enableStereoAudioOutput) {
|
|
104
|
+
NativeManager.setEnableStereoAudioOutput(true);
|
|
105
|
+
}
|
|
101
106
|
NativeManager.start();
|
|
102
107
|
};
|
|
103
108
|
|
|
@@ -51,6 +51,11 @@ export interface CallManager extends NativeModule {
|
|
|
51
51
|
*/
|
|
52
52
|
stop: () => void;
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Setup the in call manager.
|
|
56
|
+
*/
|
|
57
|
+
setup: () => void;
|
|
58
|
+
|
|
54
59
|
/**
|
|
55
60
|
* Mutes the speaker
|
|
56
61
|
*/
|
|
@@ -66,6 +71,12 @@ export interface CallManager extends NativeModule {
|
|
|
66
71
|
*/
|
|
67
72
|
setForceSpeakerphoneOn: (boolean) => void;
|
|
68
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Enables or disables stereo audio output.
|
|
76
|
+
* @param enable - Whether to enable stereo audio output.
|
|
77
|
+
*/
|
|
78
|
+
setEnableStereoAudioOutput: (enable: boolean) => void;
|
|
79
|
+
|
|
69
80
|
/**
|
|
70
81
|
* Log the current audio state natively.
|
|
71
82
|
* Meant for debugging purposes.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { StreamRNVideoSDKGlobals } from '@stream-io/video-client';
|
|
2
|
+
import { NativeModules } from 'react-native';
|
|
3
|
+
|
|
4
|
+
const StreamInCallManagerNativeModule = NativeModules.StreamInCallManager;
|
|
5
|
+
|
|
6
|
+
const streamRNVideoSDKGlobals: StreamRNVideoSDKGlobals = {
|
|
7
|
+
callManager: {
|
|
8
|
+
setup: ({ defaultDevice }) => {
|
|
9
|
+
StreamInCallManagerNativeModule.setDefaultAudioDeviceEndpointType(
|
|
10
|
+
defaultDevice,
|
|
11
|
+
);
|
|
12
|
+
StreamInCallManagerNativeModule.setup();
|
|
13
|
+
},
|
|
14
|
+
start: () => {
|
|
15
|
+
StreamInCallManagerNativeModule.start();
|
|
16
|
+
},
|
|
17
|
+
stop: () => {
|
|
18
|
+
StreamInCallManagerNativeModule.stop();
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Note: The global type declaration for `streamRNVideoSDK` is defined in
|
|
24
|
+
// @stream-io/video-client/src/types.ts and is automatically available when
|
|
25
|
+
// importing from the client package.
|
|
26
|
+
export function registerSDKGlobals() {
|
|
27
|
+
if (!global.streamRNVideoSDK) {
|
|
28
|
+
global.streamRNVideoSDK = streamRNVideoSDKGlobals;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
processCallFromPushInBackground,
|
|
13
13
|
} from './internal/utils';
|
|
14
14
|
import { AppState, NativeModules, Platform } from 'react-native';
|
|
15
|
+
import { RTCAudioSession } from '@stream-io/react-native-webrtc';
|
|
15
16
|
import { setPushLogoutCallback } from '../internal/pushLogoutCallback';
|
|
16
17
|
|
|
17
18
|
type PushConfig = NonNullable<StreamVideoConfig['push']>;
|
|
@@ -75,6 +76,34 @@ export function setupIosCallKeepEvents(
|
|
|
75
76
|
});
|
|
76
77
|
}
|
|
77
78
|
|
|
79
|
+
/**
|
|
80
|
+
* CallKeep / CallKit audio-session events -> WebRTC (iOS)
|
|
81
|
+
*
|
|
82
|
+
* iOS CallKit is the authority that *activates* and *deactivates* the underlying `AVAudioSession`
|
|
83
|
+
* when a call is answered/ended from the system UI (lock screen, Call UI, Bluetooth, etc).
|
|
84
|
+
*
|
|
85
|
+
* WebRTC on iOS wraps `AVAudioSession` with `RTCAudioSession` and its AudioDeviceModule relies on
|
|
86
|
+
* being notified of those lifecycle transitions to correctly start/stop audio I/O and keep its
|
|
87
|
+
* internal activation state consistent (e.g. activation count, playout/recording start).
|
|
88
|
+
*
|
|
89
|
+
* If these callbacks don’t reach WebRTC, answering via the native dialer UI can result in:
|
|
90
|
+
* - no microphone capture / one-way audio
|
|
91
|
+
* - silent playout until the app forces an audio reconfiguration
|
|
92
|
+
* - flaky audio routing (speaker/earpiece/Bluetooth) across subsequent calls
|
|
93
|
+
*
|
|
94
|
+
* We forward CallKeep’s `didActivateAudioSession` / `didDeactivateAudioSession` events to WebRTC’s
|
|
95
|
+
* `RTCAudioSession.audioSessionDidActivate()` / `audioSessionDidDeactivate()` methods.
|
|
96
|
+
*/
|
|
97
|
+
function didActivateAudioSession() {
|
|
98
|
+
logger.debug('didActivateAudioSession');
|
|
99
|
+
RTCAudioSession.audioSessionDidActivate();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function didDeactivateAudioSession() {
|
|
103
|
+
logger.debug('didDeactivateAudioSession');
|
|
104
|
+
RTCAudioSession.audioSessionDidDeactivate();
|
|
105
|
+
}
|
|
106
|
+
|
|
78
107
|
function didDisplayIncomingCall(callUUID: string, payload: object) {
|
|
79
108
|
const voipPushNotification = getVoipPushNotificationLib();
|
|
80
109
|
// @ts-expect-error - call_cid is not part of RNCallKeepEventPayload
|
|
@@ -118,6 +147,20 @@ export function setupIosCallKeepEvents(
|
|
|
118
147
|
},
|
|
119
148
|
);
|
|
120
149
|
|
|
150
|
+
const { remove: removeDidActivateAudioSession } = callkeep.addEventListener(
|
|
151
|
+
'didActivateAudioSession',
|
|
152
|
+
() => {
|
|
153
|
+
didActivateAudioSession();
|
|
154
|
+
},
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
const { remove: removeDidDeactivateAudioSession } = callkeep.addEventListener(
|
|
158
|
+
'didDeactivateAudioSession',
|
|
159
|
+
() => {
|
|
160
|
+
didDeactivateAudioSession();
|
|
161
|
+
},
|
|
162
|
+
);
|
|
163
|
+
|
|
121
164
|
const { remove: removeDidLoadWithEvents } = callkeep.addEventListener(
|
|
122
165
|
'didLoadWithEvents',
|
|
123
166
|
(events) => {
|
|
@@ -133,6 +176,10 @@ export function setupIosCallKeepEvents(
|
|
|
133
176
|
answerCall(data.callUUID);
|
|
134
177
|
} else if (name === 'RNCallKeepPerformEndCallAction') {
|
|
135
178
|
endCall(data.callUUID);
|
|
179
|
+
} else if (name === 'RNCallKeepDidActivateAudioSession') {
|
|
180
|
+
didActivateAudioSession();
|
|
181
|
+
} else if (name === 'RNCallKeepDidDeactivateAudioSession') {
|
|
182
|
+
didDeactivateAudioSession();
|
|
136
183
|
}
|
|
137
184
|
});
|
|
138
185
|
},
|
|
@@ -142,6 +189,8 @@ export function setupIosCallKeepEvents(
|
|
|
142
189
|
removeAnswerCall();
|
|
143
190
|
removeEndCall();
|
|
144
191
|
removeDisplayIncomingCall();
|
|
192
|
+
removeDidActivateAudioSession();
|
|
193
|
+
removeDidDeactivateAudioSession();
|
|
145
194
|
removeDidLoadWithEvents();
|
|
146
195
|
});
|
|
147
196
|
}
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '1.
|
|
1
|
+
export const version = '1.28.1';
|
package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioSetupStoreUtil.kt
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
package com.streamvideo.reactnative.audio.utils
|
|
2
|
-
|
|
3
|
-
import android.media.AudioManager
|
|
4
|
-
import android.util.Log
|
|
5
|
-
import com.facebook.react.bridge.ReactContext
|
|
6
|
-
import com.streamvideo.reactnative.audio.AudioDeviceManager
|
|
7
|
-
import com.streamvideo.reactnative.callmanager.StreamInCallManagerModule.Companion.TAG
|
|
8
|
-
|
|
9
|
-
class AudioSetupStoreUtil(
|
|
10
|
-
private val mReactContext: ReactContext,
|
|
11
|
-
private val mAudioManager: AudioManager,
|
|
12
|
-
private val mAudioDeviceManager: AudioDeviceManager
|
|
13
|
-
) {
|
|
14
|
-
private var isOrigAudioSetupStored = false
|
|
15
|
-
private var origIsSpeakerPhoneOn = false
|
|
16
|
-
private var origIsMicrophoneMute = false
|
|
17
|
-
private var origAudioMode = AudioManager.MODE_NORMAL
|
|
18
|
-
|
|
19
|
-
fun storeOriginalAudioSetup() {
|
|
20
|
-
if (!isOrigAudioSetupStored) {
|
|
21
|
-
origAudioMode = mAudioManager.mode
|
|
22
|
-
origIsSpeakerPhoneOn = AudioManagerUtil.isSpeakerphoneOn(mAudioManager)
|
|
23
|
-
origIsMicrophoneMute = mAudioManager.isMicrophoneMute
|
|
24
|
-
isOrigAudioSetupStored = true
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
fun restoreOriginalAudioSetup() {
|
|
29
|
-
if (isOrigAudioSetupStored) {
|
|
30
|
-
if (origIsSpeakerPhoneOn) {
|
|
31
|
-
mAudioDeviceManager.setSpeakerphoneOn(true)
|
|
32
|
-
}
|
|
33
|
-
mAudioManager.setMicrophoneMute(origIsMicrophoneMute)
|
|
34
|
-
mAudioManager.mode = origAudioMode
|
|
35
|
-
mReactContext.currentActivity?.apply {
|
|
36
|
-
volumeControlStream = AudioManager.USE_DEFAULT_STREAM_TYPE
|
|
37
|
-
}
|
|
38
|
-
isOrigAudioSetupStored = false
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|