@stream-io/video-react-native-sdk 1.26.4 → 1.26.5

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 CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ## [1.26.5](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-react-native-sdk-1.26.4...@stream-io/video-react-native-sdk-1.26.5) (2025-12-23)
6
+
7
+ ### Dependency Updates
8
+
9
+ - `@stream-io/video-client` updated to version `1.39.2`
10
+ - `@stream-io/video-react-bindings` updated to version `1.12.5`
11
+
12
+ ### Bug Fixes
13
+
14
+ - do not set invalid BT devices as communication device ([#2064](https://github.com/GetStream/stream-video-js/issues/2064)) ([fe41a34](https://github.com/GetStream/stream-video-js/commit/fe41a349df41c11e05b673e6107788203e94fae9))
15
+
5
16
  ## [1.26.4](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-react-native-sdk-1.26.3...@stream-io/video-react-native-sdk-1.26.4) (2025-12-18)
6
17
 
7
18
  ### Dependency Updates
@@ -44,7 +44,22 @@ internal class AudioDeviceEndpointUtils {
44
44
  val endpoints: MutableList<AudioDeviceEndpoint> = mutableListOf()
45
45
  var foundWiredHeadset = false
46
46
  val omittedDevices = StringBuilder("omitting devices =[")
47
- adiArr.toList().forEach { audioDeviceInfo ->
47
+ adiArr.forEach { audioDeviceInfo ->
48
+ /**
49
+ * Only devices in a sink role can be selected via AudioManager#setCommunicationDevice
50
+ * (API 31+). We enforce this at the endpoint construction level as a safety net
51
+ * because AudioDeviceCallback can surface devices that aren't valid call endpoints.
52
+ */
53
+ val isInvalidCallEndpoint = !audioDeviceInfo.isSink
54
+
55
+ if (isInvalidCallEndpoint) {
56
+ omittedDevices.append(
57
+ "(type=[${audioDeviceInfo.type}]," +
58
+ " name=[${audioDeviceInfo.productName}]),"
59
+ )
60
+ return@forEach
61
+ }
62
+
48
63
  val endpoint = getEndpointFromAudioDeviceInfo(audioDeviceInfo)
49
64
  if (endpoint.type != AudioDeviceEndpoint.TYPE_UNKNOWN) {
50
65
  if (endpoint.type == AudioDeviceEndpoint.TYPE_WIRED_HEADSET) {
@@ -115,11 +130,8 @@ internal class AudioDeviceEndpointUtils {
115
130
  AudioDeviceInfo.TYPE_USB_HEADSET -> AudioDeviceEndpoint.TYPE_WIRED_HEADSET
116
131
  // Bluetooth Devices
117
132
  AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
118
- AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
119
133
  AudioDeviceInfo.TYPE_HEARING_AID,
120
- AudioDeviceInfo.TYPE_BLE_HEADSET,
121
- AudioDeviceInfo.TYPE_BLE_SPEAKER,
122
- AudioDeviceInfo.TYPE_BLE_BROADCAST -> AudioDeviceEndpoint.TYPE_BLUETOOTH
134
+ AudioDeviceInfo.TYPE_BLE_HEADSET -> AudioDeviceEndpoint.TYPE_BLUETOOTH
123
135
  // Everything else is defaulted to TYPE_UNKNOWN
124
136
  else -> AudioDeviceEndpoint.TYPE_UNKNOWN
125
137
  }
@@ -25,6 +25,39 @@ internal class AudioManagerUtil {
25
25
  }
26
26
  }
27
27
 
28
+ /**
29
+ * Safe wrapper around [AudioManager.setCommunicationDevice] to avoid crashing the app on
30
+ * OEM-specific edge cases. On API 31+, Android requires that:
31
+ * - the device is a sink (output), and
32
+ * - the device is among [AudioManager.availableCommunicationDevices].
33
+ */
34
+ @RequiresApi(31)
35
+ fun setCommunicationDeviceSafely(
36
+ audioManager: AudioManager,
37
+ deviceInfo: AudioDeviceInfo,
38
+ ): Boolean {
39
+
40
+ if (!deviceInfo.isSink) {
41
+ Log.w(TAG, "setCommunicationDeviceSafely: rejecting non-sink device type=${deviceInfo.type}, id=${deviceInfo.id}")
42
+ return false
43
+ }
44
+
45
+ val available = audioManager.availableCommunicationDevices
46
+ val isAvailable = available.any { it.id == deviceInfo.id }
47
+ if (!isAvailable) {
48
+ Log.w(TAG, "setCommunicationDeviceSafely: device not in availableCommunicationDevices type=${deviceInfo.type}, id=${deviceInfo.id}")
49
+ return false
50
+ }
51
+
52
+ return try {
53
+ audioManager.setCommunicationDevice(deviceInfo)
54
+ true
55
+ } catch (e: IllegalArgumentException) {
56
+ Log.w(TAG, "setCommunicationDeviceSafely: failed type=${deviceInfo.type}, id=${deviceInfo.id}", e)
57
+ false
58
+ }
59
+ }
60
+
28
61
  fun isSpeakerphoneOn(audioManager: AudioManager): Boolean {
29
62
  return if (Build.VERSION.SDK_INT >= 31) {
30
63
  AudioManager31PlusImpl.isSpeakerphoneOn(audioManager)
@@ -83,7 +116,7 @@ internal class AudioManagerUtil {
83
116
  endpointMaps.nonBluetoothEndpoints.values.firstOrNull {
84
117
  it.type == deviceType
85
118
  }?.let {
86
- audioManager.setCommunicationDevice(it.deviceInfo)
119
+ setCommunicationDeviceSafely(audioManager, it.deviceInfo)
87
120
  bluetoothManager.updateDevice()
88
121
  return endpointMaps.nonBluetoothEndpoints[deviceType]
89
122
  }
@@ -92,7 +125,7 @@ internal class AudioManagerUtil {
92
125
  AudioDeviceEndpoint.TYPE_SPEAKER -> {
93
126
  val speakerDevice = endpointMaps.nonBluetoothEndpoints[AudioDeviceEndpoint.TYPE_SPEAKER]
94
127
  speakerDevice?.let {
95
- audioManager.setCommunicationDevice(it.deviceInfo)
128
+ setCommunicationDeviceSafely(audioManager, it.deviceInfo)
96
129
  bluetoothManager.updateDevice()
97
130
  return speakerDevice
98
131
  }
@@ -4,5 +4,5 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.version = void 0;
7
- const version = exports.version = '1.26.4';
7
+ const version = exports.version = '1.26.5';
8
8
  //# sourceMappingURL=version.js.map
@@ -1,2 +1,2 @@
1
- export const version = '1.26.4';
1
+ export const version = '1.26.5';
2
2
  //# sourceMappingURL=version.js.map
@@ -1,2 +1,2 @@
1
- export declare const version = "1.26.4";
1
+ export declare const version = "1.26.5";
2
2
  //# sourceMappingURL=version.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-io/video-react-native-sdk",
3
- "version": "1.26.4",
3
+ "version": "1.26.5",
4
4
  "description": "Stream Video SDK for React Native",
5
5
  "author": "https://getstream.io",
6
6
  "homepage": "https://getstream.io/video/docs/react-native/",
@@ -50,8 +50,8 @@
50
50
  "!**/.*"
51
51
  ],
52
52
  "dependencies": {
53
- "@stream-io/video-client": "1.39.1",
54
- "@stream-io/video-react-bindings": "1.12.4",
53
+ "@stream-io/video-client": "1.39.2",
54
+ "@stream-io/video-react-bindings": "1.12.5",
55
55
  "intl-pluralrules": "2.0.1",
56
56
  "lodash.merge": "^4.6.2",
57
57
  "react-native-url-polyfill": "^3.0.0",
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '1.26.4';
1
+ export const version = '1.26.5';