react-native-theoplayer 3.5.0 → 3.6.0

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
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.1.0/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.6.0] - 24-02-02
9
+
10
+ ### Fixed
11
+
12
+ - Fixed a build issue on the iOS bridge caused by the deprecated DispatchDispatch protocol.
13
+ - Fixed an issue on Android where the `MediaPlaybackService` would sometimes crash with a `ForegroundServiceDidNotStartInTimeException` exception.
14
+
15
+ ### Added
16
+
17
+ - Added the ability to override both small and large notification icons in Android with `ic_notification_small` and `ic_notification_large` resources respectively.
18
+
8
19
  ## [3.5.0] - 24-01-30
9
20
 
10
21
  ### Added
@@ -294,7 +294,7 @@ class PlayerEventEmitter internal constructor(
294
294
  )
295
295
  payload.putMap(EVENT_PROP_VERSION, WritableNativeMap().apply {
296
296
  putString(EVENT_PROP_VERSION, THEOplayerGlobal.getVersion())
297
- putString(EVENT_PROP_SUITE_VERSION, THEOplayerGlobal.getPlayerSuiteVersion())
297
+ putString(EVENT_PROP_SUITE_VERSION, "")
298
298
  })
299
299
 
300
300
  // Notify the player is ready
@@ -21,7 +21,8 @@ open class DefaultEventDispatcher: EventDispatcher<Event<*>> {
21
21
 
22
22
  fun dispatchEvent(event: Event<*>) {
23
23
  _listeners[event.type]?.forEach { listener ->
24
- (listener as EventListener<Event<*>>).handleEvent(event)
24
+ @Suppress("UNCHECKED_CAST")
25
+ (listener as EventListener<Event<*>>).handleEvent(event)
25
26
  }
26
27
  }
27
28
  }
@@ -41,6 +41,7 @@ class CastEventAdapter(private val castApi: Cast, private val emitter: Emitter)
41
41
 
42
42
  private fun serializeError(error: CastError): WritableMap {
43
43
  val errorPayload = Arguments.createMap()
44
+ @Suppress("SENSELESS_NULL_IN_WHEN")
44
45
  errorPayload.putString(
45
46
  EVENT_PROP_ERROR_CODE,
46
47
  when (error.errorCode) {
@@ -216,10 +216,12 @@ class ContentProtectionModule(private val context: ReactApplicationContext) :
216
216
  }
217
217
 
218
218
  @ReactMethod
219
+ @Suppress("UNUSED_PARAMETER")
219
220
  fun addListener(eventName: String?) {
220
221
  }
221
222
 
222
223
  @ReactMethod
224
+ @Suppress("UNUSED_PARAMETER")
223
225
  fun removeListeners(count: Int?) {
224
226
  }
225
227
 
@@ -5,6 +5,7 @@ import android.app.NotificationChannel
5
5
  import android.app.NotificationManager
6
6
  import android.content.Context
7
7
  import android.graphics.Bitmap
8
+ import android.graphics.BitmapFactory
8
9
  import android.net.Uri
9
10
  import android.os.Build
10
11
  import android.support.v4.media.session.MediaSessionCompat
@@ -195,3 +196,13 @@ fun fetchImageFromUri(uri: Uri?, block: (Bitmap?) -> Unit) {
195
196
  )
196
197
  }
197
198
  }
199
+
200
+ fun loadPlaceHolderIcon(context: Context, res: Int = R.drawable.ic_notification_large): Bitmap? {
201
+ return try {
202
+ BitmapFactory.decodeResource(context.resources, res)
203
+ } catch(e: Exception) {
204
+ // Make sure we never crash on trying to decode a possibly overridden icon resource.
205
+ Log.w(TAG, "Failed to decode placeHolderIcon: ${e.message}")
206
+ null
207
+ }
208
+ }
@@ -3,6 +3,7 @@ package com.theoplayer.media
3
3
  import android.app.*
4
4
  import android.content.Intent
5
5
  import android.content.pm.ServiceInfo
6
+ import android.graphics.Bitmap
6
7
  import android.os.Binder
7
8
  import android.os.Build
8
9
  import android.os.Bundle
@@ -96,6 +97,8 @@ class MediaPlaybackService : MediaBrowserServiceCompat() {
96
97
  Log.w(TAG, "Failed to start foreground service: ${e.message}")
97
98
  }
98
99
 
100
+ // Quickly post a notification and already call startForeground. This has to happen within 5s
101
+ // after creating the service to avoid a ForegroundServiceDidNotStartInTimeException
99
102
  updateNotification(PlaybackStateCompat.STATE_PLAYING)
100
103
  }
101
104
 
@@ -222,6 +225,7 @@ class MediaPlaybackService : MediaBrowserServiceCompat() {
222
225
  }
223
226
  }
224
227
 
228
+ @Suppress("UNUSED_PARAMETER")
225
229
  private fun allowBrowsing(clientPackageName: String, clientUid: Int): Boolean {
226
230
  // Only allow browsing from the same package
227
231
  return TextUtils.equals(clientPackageName, packageName)
@@ -264,26 +268,13 @@ class MediaPlaybackService : MediaBrowserServiceCompat() {
264
268
  // When a service runs in the foreground, it must display a notification, ideally
265
269
  // with one or more transport controls. The notification should also include useful
266
270
  // information from the session's metadata.
267
- // Fetch large icon asynchronously
271
+
272
+ // Get the foreground service started in time before fetching an icon.
273
+ startForegroundWithPlaybackState(playbackState, loadPlaceHolderIcon(this))
274
+
275
+ // Fetch the correct large icon asynchronously.
268
276
  fetchImageFromUri(mediaSession.controller.metadata?.description?.iconUri) { largeIcon ->
269
- try {
270
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
271
- startForeground(
272
- NOTIFICATION_ID,
273
- notificationBuilder.build(playbackState, largeIcon, enableMediaControls),
274
- ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
275
- )
276
- } else {
277
- startForeground(
278
- NOTIFICATION_ID,
279
- notificationBuilder.build(playbackState, largeIcon, enableMediaControls)
280
- )
281
- }
282
- } catch (e: IllegalStateException) {
283
- // Make sure that app does not crash in case anything goes wrong with starting the service.
284
- // https://issuetracker.google.com/issues/229000935
285
- Log.w(TAG, "Failed to start foreground service: ${e.message}")
286
- }
277
+ startForegroundWithPlaybackState(playbackState, largeIcon)
287
278
  }
288
279
  }
289
280
  PlaybackStateCompat.STATE_STOPPED -> {
@@ -303,4 +294,25 @@ class MediaPlaybackService : MediaBrowserServiceCompat() {
303
294
  }
304
295
  }
305
296
  }
297
+
298
+ private fun startForegroundWithPlaybackState(@PlaybackStateCompat.State playbackState: Int, largeIcon: Bitmap? = null) {
299
+ try {
300
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
301
+ startForeground(
302
+ NOTIFICATION_ID,
303
+ notificationBuilder.build(playbackState, largeIcon, enableMediaControls),
304
+ ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
305
+ )
306
+ } else {
307
+ startForeground(
308
+ NOTIFICATION_ID,
309
+ notificationBuilder.build(playbackState, largeIcon, enableMediaControls)
310
+ )
311
+ }
312
+ } catch (e: IllegalStateException) {
313
+ // Make sure that app does not crash in case anything goes wrong with starting the service.
314
+ // https://issuetracker.google.com/issues/229000935
315
+ Log.w(TAG, "Failed to start foreground service: ${e.message}")
316
+ }
317
+ }
306
318
  }
@@ -139,8 +139,8 @@ class THEOplayerRCTPlayerAPI: NSObject, RCTBridgeModule {
139
139
  if newPresentationMode == .fullscreen {
140
140
  print(ERROR_MESSAGE_PLAYER_FULLSCREEN_UNSUPPORTED_FEATURE)
141
141
  }
142
- if let theView = self.bridge.uiManager.view(forReactTag: node) as? THEOplayerRCTView,
143
- let player = theView.player {
142
+ else if let theView = self.bridge.uiManager.view(forReactTag: node) as? THEOplayerRCTView,
143
+ let player = theView.player {
144
144
  if player.presentationMode != newPresentationMode {
145
145
  if DEBUG_PLAYER_API { PrintUtils.printLog(logText: "[NATIVE] Changing TheoPlayer to \(presentationMode)") }
146
146
  player.presentationMode = newPresentationMode
@@ -27,7 +27,7 @@ public class THEOplayerRCTBroadcastEventHandler: DefaultEventDispatcher {
27
27
  }
28
28
  }
29
29
 
30
- public class DefaultEventDispatcher: NSObject, THEOplayerSDK.EventDispatcherProtocol, THEOplayerSDK.DispatchDispatch {
30
+ public class DefaultEventDispatcher: NSObject, THEOplayerSDK.EventDispatcherProtocol {
31
31
  private var eventListeners = [String: [EventListenerWrapper]]()
32
32
 
33
33
  public func addEventListener<E>(type: THEOplayerSDK.EventType<E>, listener: @escaping (_ : E) -> ()) -> THEOplayerSDK.EventListener {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-theoplayer",
3
- "version": "3.5.0",
3
+ "version": "3.6.0",
4
4
  "description": "A THEOplayer video component for react-native.",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",