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 +11 -0
- package/android/src/main/java/com/theoplayer/PlayerEventEmitter.kt +1 -1
- package/android/src/main/java/com/theoplayer/broadcast/DefaultEventDispatcher.kt +2 -1
- package/android/src/main/java/com/theoplayer/cast/CastEventAdapter.kt +1 -0
- package/android/src/main/java/com/theoplayer/drm/ContentProtectionModule.kt +2 -0
- package/android/src/main/java/com/theoplayer/media/MediaNotificationBuilder.kt +11 -0
- package/android/src/main/java/com/theoplayer/media/MediaPlaybackService.kt +31 -19
- package/android/src/main/res/drawable/ic_notification_large.png +0 -0
- package/ios/THEOplayerRCTPlayerAPI.swift +2 -2
- package/ios/eventBroadcasting/THEOplayerRCTBroadcastEventHandler.swift +1 -1
- package/package.json +1 -1
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|
|
Binary file
|
|
@@ -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
|
-
|
|
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
|
|
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 {
|