react-native-theoplayer 7.8.0 → 7.8.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 +10 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/com/theoplayer/media/MediaNotificationBuilder.kt +22 -14
- package/android/src/main/java/com/theoplayer/media/MediaPlaybackService.kt +3 -3
- package/ios/backgroundAudio/THEOplayerRCTNowPlayingManager.swift +14 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,16 @@ 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
|
+
## [7.8.1] - 24-08-14
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Fixed an issue on Android where the notification background would be displayed in low resolution on recent Android versions.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Added support on iOS for 'album' and 'artist' in the nowPlayingInfo.
|
|
17
|
+
|
|
8
18
|
## [7.8.0] - 24-08-09
|
|
9
19
|
|
|
10
20
|
### Added
|
package/android/build.gradle
CHANGED
|
@@ -113,8 +113,8 @@ dependencies {
|
|
|
113
113
|
implementation "androidx.core:core-ktx:${safeExtGet('corektxVersion', '1.10.1')}"
|
|
114
114
|
|
|
115
115
|
// The minimum supported THEOplayer version is 7.6.0
|
|
116
|
-
def theoplayer_sdk_version = safeExtGet('THEOplayer_sdk', '[7.
|
|
117
|
-
def theoplayer_mediasession_version = safeExtGet('THEOplayer_mediasession', '[7.
|
|
116
|
+
def theoplayer_sdk_version = safeExtGet('THEOplayer_sdk', '[7.10.0, 8.0.0)')
|
|
117
|
+
def theoplayer_mediasession_version = safeExtGet('THEOplayer_mediasession', '[7.10.0, 8.0.0)')
|
|
118
118
|
|
|
119
119
|
println("Using THEOplayer (${versionString(theoplayer_sdk_version)})")
|
|
120
120
|
implementation "com.theoplayer.theoplayer-sdk-android:core:${theoplayer_sdk_version}"
|
|
@@ -23,15 +23,18 @@ import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
|
|
|
23
23
|
import com.facebook.imagepipeline.image.CloseableImage
|
|
24
24
|
import com.facebook.imagepipeline.request.ImageRequest
|
|
25
25
|
import com.theoplayer.R
|
|
26
|
+
import com.theoplayer.android.api.source.SourceDescription
|
|
27
|
+
import com.theoplayer.android.connector.mediasession.MediaSessionConnector
|
|
26
28
|
|
|
27
29
|
private const val TAG = "MediaNotification"
|
|
28
30
|
|
|
29
31
|
class MediaNotificationBuilder(
|
|
30
32
|
private val context: Context,
|
|
31
33
|
private val notificationManager: NotificationManager,
|
|
32
|
-
private val
|
|
34
|
+
private val mediaSessionConnector: MediaSessionConnector
|
|
33
35
|
) {
|
|
34
|
-
|
|
36
|
+
private val mediaSession: MediaSessionCompat
|
|
37
|
+
get() = mediaSessionConnector.mediaSession
|
|
35
38
|
private var channel: NotificationChannel? = null
|
|
36
39
|
private var channelId: String? = null
|
|
37
40
|
|
|
@@ -136,8 +139,16 @@ class MediaNotificationBuilder(
|
|
|
136
139
|
// Add an app icon and set its accent color
|
|
137
140
|
setSmallIcon(R.drawable.ic_notification_small)
|
|
138
141
|
|
|
139
|
-
|
|
140
|
-
|
|
142
|
+
largeIcon?.let {
|
|
143
|
+
// Set the large icon that is shown in the notification
|
|
144
|
+
setLargeIcon(largeIcon)
|
|
145
|
+
|
|
146
|
+
// Also provide the mediaSession with our downloaded asset
|
|
147
|
+
mediaSessionConnector.getMediaSessionMetadataProvider().apply {
|
|
148
|
+
setArt(largeIcon)
|
|
149
|
+
invalidateMediaSessionMetadata()
|
|
150
|
+
}
|
|
151
|
+
}
|
|
141
152
|
|
|
142
153
|
// Be careful when you set the background color. In an ordinary notification in
|
|
143
154
|
// Android version 5.0 or later, the color is applied only to the background of the
|
|
@@ -170,7 +181,7 @@ class MediaNotificationBuilder(
|
|
|
170
181
|
// Add up to 3 actions to be shown in the notification's standard-sized contentView.
|
|
171
182
|
if (enableMediaControls) {
|
|
172
183
|
// The Rewind, Play/Pause and FastForward actions.
|
|
173
|
-
style.setShowActionsInCompactView(0,1,2)
|
|
184
|
+
style.setShowActionsInCompactView(0, 1, 2)
|
|
174
185
|
} else {
|
|
175
186
|
// The placeholder action, which was added above.
|
|
176
187
|
style.setShowActionsInCompactView(0)
|
|
@@ -193,16 +204,13 @@ class MediaNotificationBuilder(
|
|
|
193
204
|
}
|
|
194
205
|
}
|
|
195
206
|
|
|
196
|
-
fun
|
|
197
|
-
|
|
207
|
+
fun fetchImageFromMetadata(source: SourceDescription?, block: (Bitmap?) -> Unit) {
|
|
208
|
+
val img = source?.poster ?: source?.metadata?.get("displayIconUri")
|
|
209
|
+
if (img == null) {
|
|
198
210
|
block(null)
|
|
199
211
|
return
|
|
200
212
|
}
|
|
201
|
-
|
|
202
|
-
val imageRequest = ImageRequest.fromUri(uri)
|
|
203
|
-
val imagePipeline = Fresco.getImagePipeline()
|
|
204
|
-
|
|
205
|
-
imagePipeline.fetchDecodedImage(imageRequest, null).also {
|
|
213
|
+
Fresco.getImagePipeline().fetchDecodedImage(ImageRequest.fromUri(Uri.parse(img)), null).also {
|
|
206
214
|
it.subscribe(
|
|
207
215
|
object : BaseBitmapDataSubscriber() {
|
|
208
216
|
override fun onNewResultImpl(bitmap: Bitmap?) {
|
|
@@ -211,7 +219,7 @@ fun fetchImageFromUri(uri: Uri?, block: (Bitmap?) -> Unit) {
|
|
|
211
219
|
|
|
212
220
|
override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage>>) {
|
|
213
221
|
if (dataSource.failureCause != null) {
|
|
214
|
-
Log.w(TAG, "Failed to get image $
|
|
222
|
+
Log.w(TAG, "Failed to get image $img")
|
|
215
223
|
}
|
|
216
224
|
block(null)
|
|
217
225
|
}
|
|
@@ -224,7 +232,7 @@ fun fetchImageFromUri(uri: Uri?, block: (Bitmap?) -> Unit) {
|
|
|
224
232
|
fun loadPlaceHolderIcon(context: Context, res: Int = R.drawable.ic_notification_large): Bitmap? {
|
|
225
233
|
return try {
|
|
226
234
|
BitmapFactory.decodeResource(context.resources, res)
|
|
227
|
-
} catch(e: Exception) {
|
|
235
|
+
} catch (e: Exception) {
|
|
228
236
|
// Make sure we never crash on trying to decode a possibly overridden icon resource.
|
|
229
237
|
Log.w(TAG, "Failed to decode placeHolderIcon: ${e.message}")
|
|
230
238
|
null
|
|
@@ -77,7 +77,7 @@ class MediaPlaybackService : Service() {
|
|
|
77
77
|
initMediaSession()
|
|
78
78
|
|
|
79
79
|
notificationManager = (getSystemService(NOTIFICATION_SERVICE) as NotificationManager)
|
|
80
|
-
notificationBuilder = MediaNotificationBuilder(this, notificationManager,
|
|
80
|
+
notificationBuilder = MediaNotificationBuilder(this, notificationManager, mediaSessionConnector)
|
|
81
81
|
|
|
82
82
|
// This ensures that the service starts and continues to run, even when all
|
|
83
83
|
// UI MediaBrowser activities that are bound to it unbind.
|
|
@@ -215,7 +215,7 @@ class MediaPlaybackService : Service() {
|
|
|
215
215
|
when (playbackState) {
|
|
216
216
|
PlaybackStateCompat.STATE_PAUSED -> {
|
|
217
217
|
// Fetch large icon asynchronously
|
|
218
|
-
|
|
218
|
+
fetchImageFromMetadata(player?.source) { largeIcon ->
|
|
219
219
|
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build(playbackState, largeIcon, mediaSessionConfig.mediaSessionEnabled))
|
|
220
220
|
}
|
|
221
221
|
}
|
|
@@ -228,7 +228,7 @@ class MediaPlaybackService : Service() {
|
|
|
228
228
|
startForegroundWithPlaybackState(playbackState, loadPlaceHolderIcon(this))
|
|
229
229
|
|
|
230
230
|
// Fetch the correct large icon asynchronously.
|
|
231
|
-
|
|
231
|
+
fetchImageFromMetadata(player?.source) { largeIcon ->
|
|
232
232
|
startForegroundWithPlaybackState(playbackState, largeIcon)
|
|
233
233
|
}
|
|
234
234
|
}
|
|
@@ -54,6 +54,8 @@ class THEOplayerRCTNowPlayingManager {
|
|
|
54
54
|
self.updatePlaybackState()
|
|
55
55
|
self.nowPlayingInfo = [String : Any]()
|
|
56
56
|
self.updateTitle(metadata.title)
|
|
57
|
+
self.updateArtist(metadata.metadataKeys?["artist"] as? String)
|
|
58
|
+
self.updateAlbum(metadata.metadataKeys?["album"] as? String)
|
|
57
59
|
self.updateSubtitle(metadata.metadataKeys?["subtitle"] as? String)
|
|
58
60
|
self.updateDuration(player.duration)
|
|
59
61
|
self.updateMediaType() // video
|
|
@@ -106,6 +108,18 @@ class THEOplayerRCTNowPlayingManager {
|
|
|
106
108
|
}
|
|
107
109
|
}
|
|
108
110
|
|
|
111
|
+
private func updateArtist(_ metadataArtist: String?) {
|
|
112
|
+
if let artist = metadataArtist {
|
|
113
|
+
self.nowPlayingInfo[MPMediaItemPropertyArtist] = artist
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private func updateAlbum(_ metadataAlbum: String?) {
|
|
118
|
+
if let album = metadataAlbum {
|
|
119
|
+
self.nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = album
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
109
123
|
private func updateSubtitle(_ metadataSubtitle: String?) {
|
|
110
124
|
if let subtitle = metadataSubtitle {
|
|
111
125
|
self.nowPlayingInfo[MPMediaItemPropertyArtist] = subtitle
|