@stream-io/video-react-native-sdk 1.9.5 → 1.9.6

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,13 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ## [1.9.6](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-react-native-sdk-1.9.5...@stream-io/video-react-native-sdk-1.9.6) (2025-01-22)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * pip android crash on activity not enabled ([#1650](https://github.com/GetStream/stream-video-js/issues/1650)) ([013853b](https://github.com/GetStream/stream-video-js/commit/013853b11d83c9959dfc6805e1be492d0b1d36f5))
11
+
5
12
  ## [1.9.5](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-react-native-sdk-1.9.4...@stream-io/video-react-native-sdk-1.9.5) (2025-01-21)
6
13
 
7
14
  ### Dependency Updates
@@ -12,6 +12,7 @@ import android.net.Uri
12
12
  import android.os.Build
13
13
  import android.os.PowerManager
14
14
  import android.os.Process
15
+ import android.util.Log
15
16
  import android.util.Rational
16
17
  import androidx.annotation.RequiresApi
17
18
  import com.facebook.react.ReactActivity
@@ -23,10 +24,11 @@ import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEm
23
24
  import com.streamvideo.reactnative.util.RingtoneUtil
24
25
 
25
26
 
26
- class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
27
+ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) :
28
+ ReactContextBaseJavaModule(reactContext) {
27
29
 
28
30
  override fun getName(): String {
29
- return NAME;
31
+ return NAME
30
32
  }
31
33
 
32
34
  private var thermalStatusListener: PowerManager.OnThermalStatusChangedListener? = null
@@ -39,30 +41,37 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) : Reac
39
41
  RCTDeviceEventEmitter::class.java
40
42
  ).emit(PIP_CHANGE_EVENT, isInPictureInPictureMode)
41
43
  // inform the activity
42
- if (isInPictureInPictureMode && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
44
+ if (isInPictureInPictureMode && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && hasPiPSupport()) {
43
45
  (reactApplicationContext.currentActivity as? ReactActivity)?.let { activity ->
44
- val params = getPiPParams()
45
- val aspect =
46
- if (newConfig.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
47
- Rational(9, 16)
46
+ try {
47
+ val params = getPiPParams()
48
+ val aspect =
49
+ if (newConfig.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
50
+ Rational(9, 16)
51
+ } else {
52
+ Rational(16, 9)
53
+ }
54
+ params.setAspectRatio(aspect)
55
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
56
+ // this platform doesn't support autoEnterEnabled
57
+ // so we manually enter here
58
+ activity.enterPictureInPictureMode(params.build())
48
59
  } else {
49
- Rational(16, 9)
60
+ activity.setPictureInPictureParams(params.build())
50
61
  }
51
- params.setAspectRatio(aspect)
52
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
53
- // this platform doesn't support autoEnterEnabled
54
- // so we manually enter here
55
- activity.enterPictureInPictureMode(params.build())
56
- } else {
57
- activity.setPictureInPictureParams(params.build())
62
+ // NOTE: workaround - on PiP mode, android goes to "paused but can render" state
63
+ // RN pauses rendering in paused mode, so we instruct it to resume here
64
+ reactApplicationContext?.onHostResume(activity)
65
+ } catch (e: IllegalStateException) {
66
+ Log.d(
67
+ NAME,
68
+ "Skipping Picture-in-Picture mode. Its not enabled for activity"
69
+ )
58
70
  }
59
- // NOTE: workaround - on PiP mode, android goes to "paused but can render" state
60
- // RN pauses rendering in paused mode, so we instruct it to resume here
61
- reactApplicationContext?.onHostResume(activity)
62
71
  }
63
72
  }
64
73
  }
65
-
74
+
66
75
  val filter = IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)
67
76
  reactApplicationContext.registerReceiver(powerReceiver, filter)
68
77
  }
@@ -70,11 +79,14 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) : Reac
70
79
  @ReactMethod
71
80
  fun getDefaultRingtoneUrl(promise: Promise) {
72
81
  val defaultRingtoneUri: Uri? =
73
- RingtoneUtil.getActualDefaultRingtoneUri(reactApplicationContext);
82
+ RingtoneUtil.getActualDefaultRingtoneUri(reactApplicationContext)
74
83
  if (defaultRingtoneUri != null) {
75
- promise.resolve(defaultRingtoneUri.toString());
84
+ promise.resolve(defaultRingtoneUri.toString())
76
85
  } else {
77
- promise.reject(NAME, "Cannot get default ringtone in Android - check native logs for more info");
86
+ promise.reject(
87
+ NAME,
88
+ "Cannot get default ringtone in Android - check native logs for more info"
89
+ )
78
90
  }
79
91
  }
80
92
 
@@ -105,17 +117,21 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) : Reac
105
117
  @ReactMethod
106
118
  fun canAutoEnterPipMode(value: Boolean) {
107
119
  StreamVideoReactNative.canAutoEnterPictureInPictureMode = value
108
- if (!hasPermission() || Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return
120
+ if (!hasPiPSupport() || Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return
109
121
  val activity = reactApplicationContext!!.currentActivity!!
110
- if (value) {
111
- activity.setPictureInPictureParams(getPiPParams().build())
112
- // NOTE: for SDK_INT < Build.VERSION_CODES.S
113
- // onUserLeaveHint from Activity is used, SDK cant directly use it
114
- // onUserLeaveHint will call the PiP listener and we call enterPictureInPictureMode there
115
- } else {
116
- val params = PictureInPictureParams.Builder()
117
- params.setAutoEnterEnabled(false)
118
- activity.setPictureInPictureParams(params.build())
122
+ try {
123
+ if (value) {
124
+ activity.setPictureInPictureParams(getPiPParams().build())
125
+ // NOTE: for SDK_INT < Build.VERSION_CODES.S
126
+ // onUserLeaveHint from Activity is used, SDK cant directly use it
127
+ // onUserLeaveHint will call the PiP listener and we call enterPictureInPictureMode there
128
+ } else {
129
+ val params = PictureInPictureParams.Builder()
130
+ params.setAutoEnterEnabled(false)
131
+ activity.setPictureInPictureParams(params.build())
132
+ }
133
+ } catch (e: IllegalStateException) {
134
+ Log.d(NAME, "Skipping Picture-in-Picture mode. Its not enabled for activity")
119
135
  }
120
136
  }
121
137
 
@@ -123,8 +139,9 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) : Reac
123
139
  fun startThermalStatusUpdates(promise: Promise) {
124
140
  try {
125
141
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
126
- val powerManager = reactApplicationContext.getSystemService(ReactApplicationContext.POWER_SERVICE) as PowerManager
127
-
142
+ val powerManager =
143
+ reactApplicationContext.getSystemService(ReactApplicationContext.POWER_SERVICE) as PowerManager
144
+
128
145
  val listener = PowerManager.OnThermalStatusChangedListener { status ->
129
146
  val thermalStatus = when (status) {
130
147
  PowerManager.THERMAL_STATUS_NONE -> "NONE"
@@ -136,12 +153,12 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) : Reac
136
153
  PowerManager.THERMAL_STATUS_SHUTDOWN -> "SHUTDOWN"
137
154
  else -> "UNKNOWN"
138
155
  }
139
-
156
+
140
157
  reactApplicationContext
141
158
  .getJSModule(RCTDeviceEventEmitter::class.java)
142
159
  .emit("thermalStateDidChange", thermalStatus)
143
160
  }
144
-
161
+
145
162
  thermalStatusListener = listener
146
163
  powerManager.addThermalStatusListener(listener)
147
164
  // Get initial status
@@ -157,7 +174,8 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) : Reac
157
174
  @ReactMethod
158
175
  fun stopThermalStatusUpdates() {
159
176
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
160
- val powerManager = reactApplicationContext.getSystemService(ReactApplicationContext.POWER_SERVICE) as PowerManager
177
+ val powerManager =
178
+ reactApplicationContext.getSystemService(ReactApplicationContext.POWER_SERVICE) as PowerManager
161
179
  // Store the current listener in a local val for safe null checking
162
180
  val currentListener = thermalStatusListener
163
181
  if (currentListener != null) {
@@ -171,7 +189,8 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) : Reac
171
189
  fun currentThermalState(promise: Promise) {
172
190
  try {
173
191
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
174
- val powerManager = reactApplicationContext.getSystemService(ReactApplicationContext.POWER_SERVICE) as PowerManager
192
+ val powerManager =
193
+ reactApplicationContext.getSystemService(ReactApplicationContext.POWER_SERVICE) as PowerManager
175
194
  val status = powerManager.currentThermalStatus
176
195
  val thermalStatus = when (status) {
177
196
  PowerManager.THERMAL_STATUS_NONE -> "NONE"
@@ -201,7 +220,8 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) : Reac
201
220
  }
202
221
 
203
222
  private fun sendPowerModeEvent() {
204
- val powerManager = reactApplicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager
223
+ val powerManager =
224
+ reactApplicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager
205
225
  val isLowPowerMode = powerManager.isPowerSaveMode
206
226
  reactApplicationContext
207
227
  .getJSModule(RCTDeviceEventEmitter::class.java)
@@ -211,22 +231,34 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) : Reac
211
231
  @ReactMethod
212
232
  fun isLowPowerModeEnabled(promise: Promise) {
213
233
  try {
214
- val powerManager = reactApplicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager
234
+ val powerManager =
235
+ reactApplicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager
215
236
  promise.resolve(powerManager.isPowerSaveMode)
216
237
  } catch (e: Exception) {
217
238
  promise.reject("ERROR", e.message)
218
239
  }
219
240
  }
220
241
 
221
- private fun hasPermission(): Boolean {
222
- return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && reactApplicationContext.packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) {
242
+ private fun hasPiPSupport(): Boolean {
243
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && reactApplicationContext.packageManager.hasSystemFeature(
244
+ PackageManager.FEATURE_PICTURE_IN_PICTURE
245
+ )
246
+ ) {
223
247
  val appOps =
224
248
  reactApplicationContext.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
225
249
  val packageName = reactApplicationContext.packageName
226
250
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
227
- appOps.unsafeCheckOpNoThrow(AppOpsManager.OPSTR_PICTURE_IN_PICTURE, Process.myUid(), packageName) == AppOpsManager.MODE_ALLOWED
251
+ appOps.unsafeCheckOpNoThrow(
252
+ AppOpsManager.OPSTR_PICTURE_IN_PICTURE,
253
+ Process.myUid(),
254
+ packageName
255
+ ) == AppOpsManager.MODE_ALLOWED
228
256
  } else {
229
- appOps.checkOpNoThrow(AppOpsManager.OPSTR_PICTURE_IN_PICTURE, Process.myUid(), packageName) == AppOpsManager.MODE_ALLOWED
257
+ appOps.checkOpNoThrow(
258
+ AppOpsManager.OPSTR_PICTURE_IN_PICTURE,
259
+ Process.myUid(),
260
+ packageName
261
+ ) == AppOpsManager.MODE_ALLOWED
230
262
  }
231
263
  } else {
232
264
  false
@@ -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.9.5';
7
+ const version = exports.version = '1.9.6';
8
8
  //# sourceMappingURL=version.js.map
@@ -1,2 +1,2 @@
1
- export const version = '1.9.5';
1
+ export const version = '1.9.6';
2
2
  //# sourceMappingURL=version.js.map
@@ -1,2 +1,2 @@
1
- export declare const version = "1.9.5";
1
+ export declare const version = "1.9.6";
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.9.5",
3
+ "version": "1.9.6",
4
4
  "packageManager": "yarn@3.2.4",
5
5
  "main": "dist/commonjs/index.js",
6
6
  "module": "dist/module/index.js",
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '1.9.5';
1
+ export const version = '1.9.6';