@javascriptcommon/react-native-track-player 4.1.14 → 4.1.16
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/android/src/main/java/com/doublesymmetry/trackplayer/utils/BundleUtils.kt +2 -2
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/AudioItem.kt +11 -2
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AudioPlayer.swift +8 -2
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/Observer/AVPlayerItemObserver.swift +3 -3
- package/package.json +1 -1
|
@@ -21,8 +21,8 @@ object BundleUtils {
|
|
|
21
21
|
if (!data!!.containsKey(key)) return null
|
|
22
22
|
val obj = data[key]
|
|
23
23
|
if (obj is String) {
|
|
24
|
-
// Remote or Local Uri
|
|
25
|
-
if (obj.trim { it <= ' ' }.isEmpty())
|
|
24
|
+
// Remote or Local Uri - allow empty URLs for placeholder tracks
|
|
25
|
+
if (obj.trim { it <= ' ' }.isEmpty()) return Uri.EMPTY
|
|
26
26
|
return Uri.parse(obj as String?)
|
|
27
27
|
} else if (obj is Bundle) {
|
|
28
28
|
// require/import
|
|
@@ -77,15 +77,23 @@ enum class MediaType(val value: String) {
|
|
|
77
77
|
|
|
78
78
|
|
|
79
79
|
fun audioItem2MediaItem(audioItem: AudioItem, context: Context? = null): MediaItem {
|
|
80
|
+
// Check if this is a placeholder track (notPlayable flag from TrackAudioItem)
|
|
81
|
+
val isNotPlayable = (audioItem as? com.doublesymmetry.trackplayer.model.TrackAudioItem)?.notPlayable ?: false
|
|
82
|
+
val hasValidUrl = audioItem.audioUrl.isNotBlank()
|
|
83
|
+
|
|
80
84
|
return MediaItem.Builder()
|
|
81
85
|
.setMediaId(audioItem.mediaId ?: UUID.randomUUID().toString())
|
|
86
|
+
// Always set URI (even empty string) so ExoPlayer adds item to timeline
|
|
82
87
|
.setUri(audioItem.audioUrl)
|
|
83
88
|
.setMediaMetadata(
|
|
84
89
|
MediaMetadata.Builder()
|
|
85
90
|
.setTitle(audioItem.title)
|
|
86
91
|
.setArtist(audioItem.artist)
|
|
92
|
+
// Mark placeholder tracks as not playable so Android Auto shows them correctly in queue
|
|
93
|
+
.setIsPlayable(true)
|
|
94
|
+
.setIsBrowsable(false)
|
|
87
95
|
.setArtworkUri((
|
|
88
|
-
if (context != null && audioItem.audioUrl.startsWith("file://")) {
|
|
96
|
+
if (context != null && hasValidUrl && audioItem.audioUrl.startsWith("file://")) {
|
|
89
97
|
saveMediaCoverToPng(
|
|
90
98
|
audioItem.audioUrl,
|
|
91
99
|
context.contentResolver,
|
|
@@ -94,7 +102,7 @@ fun audioItem2MediaItem(audioItem: AudioItem, context: Context? = null): MediaIt
|
|
|
94
102
|
?: audioItem.artwork
|
|
95
103
|
}
|
|
96
104
|
else audioItem.artwork)?.toUri())
|
|
97
|
-
.setArtworkData(if (audioItem.audioUrl.startsWith("file://")) getEmbeddedBitmapArray(
|
|
105
|
+
.setArtworkData(if (hasValidUrl && audioItem.audioUrl.startsWith("file://")) getEmbeddedBitmapArray(
|
|
98
106
|
audioItem.audioUrl.substring(7)) else null, MediaMetadata.PICTURE_TYPE_MEDIA)
|
|
99
107
|
.setExtras(Bundle().apply {
|
|
100
108
|
audioItem.options?.headers?.let {
|
|
@@ -108,6 +116,7 @@ fun audioItem2MediaItem(audioItem: AudioItem, context: Context? = null): MediaIt
|
|
|
108
116
|
}
|
|
109
117
|
putString("type", audioItem.type.toString())
|
|
110
118
|
putString("uri", audioItem.audioUrl)
|
|
119
|
+
putBoolean("notPlayable", isNotPlayable)
|
|
111
120
|
}).build())
|
|
112
121
|
.setTag(audioItem)
|
|
113
122
|
.build()
|
|
@@ -214,7 +214,7 @@ public class AudioPlayer: AVPlayerWrapperDelegate {
|
|
|
214
214
|
// Reset playback values without updating, because that will happen in
|
|
215
215
|
// the loadNowPlayingMetaValues call straight after:
|
|
216
216
|
nowPlayingInfoController.setWithoutUpdate(keyValues: [
|
|
217
|
-
MediaItemProperty.duration(
|
|
217
|
+
MediaItemProperty.duration(item.getDuration()),
|
|
218
218
|
NowPlayingInfoProperty.playbackRate(nil),
|
|
219
219
|
NowPlayingInfoProperty.elapsedPlaybackTime(nil)
|
|
220
220
|
])
|
|
@@ -328,6 +328,7 @@ public class AudioPlayer: AVPlayerWrapperDelegate {
|
|
|
328
328
|
MediaItemProperty.artist(item.getArtist()),
|
|
329
329
|
MediaItemProperty.title(item.getTitle()),
|
|
330
330
|
MediaItemProperty.albumTitle(item.getAlbumTitle()),
|
|
331
|
+
MediaItemProperty.duration(item.getDuration()),
|
|
331
332
|
])
|
|
332
333
|
loadArtwork(forItem: item)
|
|
333
334
|
}
|
|
@@ -341,8 +342,10 @@ public class AudioPlayer: AVPlayerWrapperDelegate {
|
|
|
341
342
|
- Playback rate
|
|
342
343
|
*/
|
|
343
344
|
func updateNowPlayingPlaybackValues() {
|
|
345
|
+
// Use wrapper.duration if valid, otherwise fallback to currentItem's duration (from metadata)
|
|
346
|
+
let duration = wrapper.duration > 0 ? wrapper.duration : (currentItem?.getDuration() ?? 0)
|
|
344
347
|
nowPlayingInfoController.set(keyValues: [
|
|
345
|
-
MediaItemProperty.duration(
|
|
348
|
+
MediaItemProperty.duration(duration),
|
|
346
349
|
NowPlayingInfoProperty.playbackRate(wrapper.playWhenReady ? Double(wrapper.rate) : 0),
|
|
347
350
|
NowPlayingInfoProperty.elapsedPlaybackTime(wrapper.currentTime)
|
|
348
351
|
])
|
|
@@ -422,6 +425,9 @@ public class AudioPlayer: AVPlayerWrapperDelegate {
|
|
|
422
425
|
|
|
423
426
|
func AVWrapper(didUpdateDuration duration: Double) {
|
|
424
427
|
event.updateDuration.emit(data: duration)
|
|
428
|
+
/*if(automaticallyUpdateNowPlayingInfo){
|
|
429
|
+
updateNowPlayingPlaybackValues()
|
|
430
|
+
}*/
|
|
425
431
|
}
|
|
426
432
|
|
|
427
433
|
func AVWrapper(didReceiveCommonMetadata metadata: [AVMetadataItem]) {
|
|
@@ -104,9 +104,9 @@ class AVPlayerItemObserver: NSObject {
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
case AVPlayerItemKeyPath.loadedTimeRanges:
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
// Note: loadedTimeRanges represents buffered content, not total duration.
|
|
108
|
+
// Do NOT call didUpdateDuration here - it would report buffer size instead of actual duration.
|
|
109
|
+
break
|
|
110
110
|
|
|
111
111
|
case AVPlayerItemKeyPath.playbackLikelyToKeepUp:
|
|
112
112
|
if let playbackLikelyToKeepUp = change?[.newKey] as? Bool {
|
package/package.json
CHANGED