Skip to content

Commit

Permalink
Merge pull request #365 from THEOplayer/release/v7.8.1
Browse files Browse the repository at this point in the history
Release/v7.8.1
  • Loading branch information
tvanlaerhoven authored Aug 14, 2024
2 parents c85ac38 + 120485a commit b6ef694
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 23 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.1.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [7.8.1] - 24-08-14

### Fixed

- Fixed an issue on Android where the notification background would be displayed in low resolution on recent Android versions.

### Added

- Added support on iOS for 'album' and 'artist' in the nowPlayingInfo.

## [7.8.0] - 24-08-09

### Added
Expand Down
4 changes: 2 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ dependencies {
implementation "androidx.core:core-ktx:${safeExtGet('corektxVersion', '1.10.1')}"

// The minimum supported THEOplayer version is 7.6.0
def theoplayer_sdk_version = safeExtGet('THEOplayer_sdk', '[7.6.0, 8.0.0)')
def theoplayer_mediasession_version = safeExtGet('THEOplayer_mediasession', '[7.5.0, 8.0.0)')
def theoplayer_sdk_version = safeExtGet('THEOplayer_sdk', '[7.10.0, 8.0.0)')
def theoplayer_mediasession_version = safeExtGet('THEOplayer_mediasession', '[7.10.0, 8.0.0)')

println("Using THEOplayer (${versionString(theoplayer_sdk_version)})")
implementation "com.theoplayer.theoplayer-sdk-android:core:${theoplayer_sdk_version}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,18 @@ import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
import com.facebook.imagepipeline.image.CloseableImage
import com.facebook.imagepipeline.request.ImageRequest
import com.theoplayer.R
import com.theoplayer.android.api.source.SourceDescription
import com.theoplayer.android.connector.mediasession.MediaSessionConnector

private const val TAG = "MediaNotification"

class MediaNotificationBuilder(
private val context: Context,
private val notificationManager: NotificationManager,
private val mediaSession: MediaSessionCompat
private val mediaSessionConnector: MediaSessionConnector
) {

private val mediaSession: MediaSessionCompat
get() = mediaSessionConnector.mediaSession
private var channel: NotificationChannel? = null
private var channelId: String? = null

Expand Down Expand Up @@ -136,8 +139,16 @@ class MediaNotificationBuilder(
// Add an app icon and set its accent color
setSmallIcon(R.drawable.ic_notification_small)

// Set the large icon that is shown in the notification
setLargeIcon(largeIcon)
largeIcon?.let {
// Set the large icon that is shown in the notification
setLargeIcon(largeIcon)

// Also provide the mediaSession with our downloaded asset
mediaSessionConnector.getMediaSessionMetadataProvider().apply {
setArt(largeIcon)
invalidateMediaSessionMetadata()
}
}

// Be careful when you set the background color. In an ordinary notification in
// Android version 5.0 or later, the color is applied only to the background of the
Expand Down Expand Up @@ -170,7 +181,7 @@ class MediaNotificationBuilder(
// Add up to 3 actions to be shown in the notification's standard-sized contentView.
if (enableMediaControls) {
// The Rewind, Play/Pause and FastForward actions.
style.setShowActionsInCompactView(0,1,2)
style.setShowActionsInCompactView(0, 1, 2)
} else {
// The placeholder action, which was added above.
style.setShowActionsInCompactView(0)
Expand All @@ -193,16 +204,13 @@ class MediaNotificationBuilder(
}
}

fun fetchImageFromUri(uri: Uri?, block: (Bitmap?) -> Unit) {
if (uri == null) {
fun fetchImageFromMetadata(source: SourceDescription?, block: (Bitmap?) -> Unit) {
val img = source?.poster ?: source?.metadata?.get("displayIconUri")
if (img == null) {
block(null)
return
}

val imageRequest = ImageRequest.fromUri(uri)
val imagePipeline = Fresco.getImagePipeline()

imagePipeline.fetchDecodedImage(imageRequest, null).also {
Fresco.getImagePipeline().fetchDecodedImage(ImageRequest.fromUri(Uri.parse(img)), null).also {
it.subscribe(
object : BaseBitmapDataSubscriber() {
override fun onNewResultImpl(bitmap: Bitmap?) {
Expand All @@ -211,7 +219,7 @@ fun fetchImageFromUri(uri: Uri?, block: (Bitmap?) -> Unit) {

override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage>>) {
if (dataSource.failureCause != null) {
Log.w(TAG, "Failed to get image $uri")
Log.w(TAG, "Failed to get image $img")
}
block(null)
}
Expand All @@ -224,7 +232,7 @@ fun fetchImageFromUri(uri: Uri?, block: (Bitmap?) -> Unit) {
fun loadPlaceHolderIcon(context: Context, res: Int = R.drawable.ic_notification_large): Bitmap? {
return try {
BitmapFactory.decodeResource(context.resources, res)
} catch(e: Exception) {
} catch (e: Exception) {
// Make sure we never crash on trying to decode a possibly overridden icon resource.
Log.w(TAG, "Failed to decode placeHolderIcon: ${e.message}")
null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class MediaPlaybackService : Service() {
initMediaSession()

notificationManager = (getSystemService(NOTIFICATION_SERVICE) as NotificationManager)
notificationBuilder = MediaNotificationBuilder(this, notificationManager, mediaSession)
notificationBuilder = MediaNotificationBuilder(this, notificationManager, mediaSessionConnector)

// This ensures that the service starts and continues to run, even when all
// UI MediaBrowser activities that are bound to it unbind.
Expand Down Expand Up @@ -215,7 +215,7 @@ class MediaPlaybackService : Service() {
when (playbackState) {
PlaybackStateCompat.STATE_PAUSED -> {
// Fetch large icon asynchronously
fetchImageFromUri(mediaSession.controller.metadata?.description?.iconUri) { largeIcon ->
fetchImageFromMetadata(player?.source) { largeIcon ->
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build(playbackState, largeIcon, mediaSessionConfig.mediaSessionEnabled))
}
}
Expand All @@ -228,7 +228,7 @@ class MediaPlaybackService : Service() {
startForegroundWithPlaybackState(playbackState, loadPlaceHolderIcon(this))

// Fetch the correct large icon asynchronously.
fetchImageFromUri(mediaSession.controller.metadata?.description?.iconUri) { largeIcon ->
fetchImageFromMetadata(player?.source) { largeIcon ->
startForegroundWithPlaybackState(playbackState, largeIcon)
}
}
Expand Down
2 changes: 1 addition & 1 deletion example/android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ newArchEnabled=false
hermesEnabled=true

# Version of the THEOplayer SDK, if not specified, the latest available version within bounds is set.
#THEOplayer_sdk=[7.6.0, 8.0.0)
#THEOplayer_sdk=[7.10.0, 8.0.0)

# Override Android sdk versions
#THEOplayer_compileSdkVersion = 34
Expand Down
14 changes: 14 additions & 0 deletions ios/backgroundAudio/THEOplayerRCTNowPlayingManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ class THEOplayerRCTNowPlayingManager {
self.updatePlaybackState()
self.nowPlayingInfo = [String : Any]()
self.updateTitle(metadata.title)
self.updateArtist(metadata.metadataKeys?["artist"] as? String)
self.updateAlbum(metadata.metadataKeys?["album"] as? String)
self.updateSubtitle(metadata.metadataKeys?["subtitle"] as? String)
self.updateDuration(player.duration)
self.updateMediaType() // video
Expand Down Expand Up @@ -106,6 +108,18 @@ class THEOplayerRCTNowPlayingManager {
}
}

private func updateArtist(_ metadataArtist: String?) {
if let artist = metadataArtist {
self.nowPlayingInfo[MPMediaItemPropertyArtist] = artist
}
}

private func updateAlbum(_ metadataAlbum: String?) {
if let album = metadataAlbum {
self.nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = album
}
}

private func updateSubtitle(_ metadataSubtitle: String?) {
if let subtitle = metadataSubtitle {
self.nowPlayingInfo[MPMediaItemPropertyArtist] = subtitle
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-theoplayer",
"version": "7.8.0",
"version": "7.8.1",
"description": "A THEOplayer video component for react-native.",
"main": "lib/commonjs/index",
"module": "lib/module/index",
Expand Down

0 comments on commit b6ef694

Please sign in to comment.