react-native-mp3-player 1.0.4 → 1.0.5
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/README.md
CHANGED
|
@@ -34,6 +34,7 @@ For audio to continue when the app is backgrounded or the screen is locked (and
|
|
|
34
34
|
1. **Enable Background Modes → Audio** (or “Audio, AirPlay, and Picture in Picture”) in your app’s Xcode project: select your target → **Signing & Capabilities** → **+ Capability** → **Background Modes** → check **Audio**.
|
|
35
35
|
2. The package configures **AVAudioSession** (category `.playback` with options for Bluetooth, AirPlay, ducking) and handles **interruptions** and **background transitions** so that playback can continue when the app is backgrounded.
|
|
36
36
|
3. **Lock screen and Control Center** controls (play, pause, seek, 15-second skip) are handled **natively**, so they work even when the JavaScript thread is suspended (e.g. screen locked). When the app returns to the foreground, events are emitted so your UI stays in sync.
|
|
37
|
+
4. **Now Playing widget:** The package sets and updates **MPNowPlayingInfoCenter** as soon as a track is loaded (title, artist, duration, elapsed, rate, artwork) and keeps it updated every second during playback. When you pause, the widget shows the track as paused (rate 0), not "Not Playing". Now playing info is only cleared when there is no current track (e.g. after `reset()`).
|
|
37
38
|
|
|
38
39
|
### Android background playback
|
|
39
40
|
|
|
@@ -202,6 +202,10 @@ public class RNTrackPlayer: NSObject, AudioSessionControllerDelegate {
|
|
|
202
202
|
player.remoteCommandController.handlePauseCommand = { [weak self] _ in
|
|
203
203
|
guard let self = self else { return MPRemoteCommandHandlerStatus.commandFailed }
|
|
204
204
|
self.player.pause()
|
|
205
|
+
if self.player.currentItem != nil && self.player.automaticallyUpdateNowPlayingInfo {
|
|
206
|
+
self.player.updateNowPlayingPlaybackValues()
|
|
207
|
+
}
|
|
208
|
+
self.emit(event: EventType.PlaybackState, body: self.getPlaybackStateBodyKeyValues(state: .paused))
|
|
205
209
|
self.emit(event: EventType.RemotePause)
|
|
206
210
|
return MPRemoteCommandHandlerStatus.success
|
|
207
211
|
}
|
|
@@ -209,6 +213,10 @@ public class RNTrackPlayer: NSObject, AudioSessionControllerDelegate {
|
|
|
209
213
|
player.remoteCommandController.handlePlayCommand = { [weak self] _ in
|
|
210
214
|
guard let self = self else { return MPRemoteCommandHandlerStatus.commandFailed }
|
|
211
215
|
self.player.play()
|
|
216
|
+
if self.player.currentItem != nil && self.player.automaticallyUpdateNowPlayingInfo {
|
|
217
|
+
self.player.updateNowPlayingPlaybackValues()
|
|
218
|
+
}
|
|
219
|
+
self.emit(event: EventType.PlaybackState, body: self.getPlaybackStateBodyKeyValues(state: .playing))
|
|
212
220
|
self.emit(event: EventType.RemotePlay)
|
|
213
221
|
return MPRemoteCommandHandlerStatus.success
|
|
214
222
|
}
|
|
@@ -247,6 +255,10 @@ public class RNTrackPlayer: NSObject, AudioSessionControllerDelegate {
|
|
|
247
255
|
player.remoteCommandController.handleStopCommand = { [weak self] _ in
|
|
248
256
|
guard let self = self else { return MPRemoteCommandHandlerStatus.commandFailed }
|
|
249
257
|
self.player.stop()
|
|
258
|
+
if self.player.currentItem != nil && self.player.automaticallyUpdateNowPlayingInfo {
|
|
259
|
+
self.player.updateNowPlayingPlaybackValues()
|
|
260
|
+
}
|
|
261
|
+
self.emit(event: EventType.PlaybackState, body: self.getPlaybackStateBodyKeyValues(state: .stopped))
|
|
250
262
|
self.emit(event: EventType.RemoteStop)
|
|
251
263
|
return MPRemoteCommandHandlerStatus.success
|
|
252
264
|
}
|
|
@@ -255,9 +267,17 @@ public class RNTrackPlayer: NSObject, AudioSessionControllerDelegate {
|
|
|
255
267
|
guard let self = self else { return MPRemoteCommandHandlerStatus.commandFailed }
|
|
256
268
|
if self.player.playerState == .paused {
|
|
257
269
|
self.player.play()
|
|
270
|
+
if self.player.currentItem != nil && self.player.automaticallyUpdateNowPlayingInfo {
|
|
271
|
+
self.player.updateNowPlayingPlaybackValues()
|
|
272
|
+
}
|
|
273
|
+
self.emit(event: EventType.PlaybackState, body: self.getPlaybackStateBodyKeyValues(state: .playing))
|
|
258
274
|
self.emit(event: EventType.RemotePlay)
|
|
259
275
|
} else {
|
|
260
276
|
self.player.pause()
|
|
277
|
+
if self.player.currentItem != nil && self.player.automaticallyUpdateNowPlayingInfo {
|
|
278
|
+
self.player.updateNowPlayingPlaybackValues()
|
|
279
|
+
}
|
|
280
|
+
self.emit(event: EventType.PlaybackState, body: self.getPlaybackStateBodyKeyValues(state: .paused))
|
|
261
281
|
self.emit(event: EventType.RemotePause)
|
|
262
282
|
}
|
|
263
283
|
return MPRemoteCommandHandlerStatus.success
|
|
@@ -544,8 +564,11 @@ public class RNTrackPlayer: NSObject, AudioSessionControllerDelegate {
|
|
|
544
564
|
public func play(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
545
565
|
if (rejectWhenNotInitialized(reject: reject)) { return }
|
|
546
566
|
player.play()
|
|
567
|
+
// Update Now Playing widget immediately (rate 1, current elapsed) so it never shows "Not Playing".
|
|
568
|
+
if player.currentItem != nil && player.automaticallyUpdateNowPlayingInfo {
|
|
569
|
+
player.updateNowPlayingPlaybackValues()
|
|
570
|
+
}
|
|
547
571
|
resolve(NSNull())
|
|
548
|
-
// Emit PlaybackState immediately so in-app UI (play/pause button) updates without waiting for native state transition.
|
|
549
572
|
emit(event: EventType.PlaybackState, body: getPlaybackStateBodyKeyValues(state: .playing))
|
|
550
573
|
}
|
|
551
574
|
|
|
@@ -554,8 +577,11 @@ public class RNTrackPlayer: NSObject, AudioSessionControllerDelegate {
|
|
|
554
577
|
if (rejectWhenNotInitialized(reject: reject)) { return }
|
|
555
578
|
|
|
556
579
|
player.pause()
|
|
580
|
+
// Update Now Playing widget immediately (rate 0, current elapsed) so it shows "Paused" not "Not Playing".
|
|
581
|
+
if player.currentItem != nil && player.automaticallyUpdateNowPlayingInfo {
|
|
582
|
+
player.updateNowPlayingPlaybackValues()
|
|
583
|
+
}
|
|
557
584
|
resolve(NSNull())
|
|
558
|
-
// Emit PlaybackState immediately so in-app UI (play/pause button) updates without waiting for native state transition.
|
|
559
585
|
emit(event: EventType.PlaybackState, body: getPlaybackStateBodyKeyValues(state: .paused))
|
|
560
586
|
}
|
|
561
587
|
|
|
@@ -211,12 +211,12 @@ public class AudioPlayer: AVPlayerWrapperDelegate {
|
|
|
211
211
|
currentItem = item
|
|
212
212
|
|
|
213
213
|
if (automaticallyUpdateNowPlayingInfo) {
|
|
214
|
-
//
|
|
215
|
-
// the
|
|
216
|
-
nowPlayingInfoController.
|
|
217
|
-
MediaItemProperty.duration(
|
|
218
|
-
NowPlayingInfoProperty.playbackRate(
|
|
219
|
-
NowPlayingInfoProperty.elapsedPlaybackTime(
|
|
214
|
+
// Set initial playback values so the Now Playing widget never shows "Not Playing"
|
|
215
|
+
// (duration/elapsed/rate must be set; use 0 until the player reports real values).
|
|
216
|
+
nowPlayingInfoController.set(keyValues: [
|
|
217
|
+
MediaItemProperty.duration(0),
|
|
218
|
+
NowPlayingInfoProperty.playbackRate(playWhenReady ? 1.0 : 0.0),
|
|
219
|
+
NowPlayingInfoProperty.elapsedPlaybackTime(0)
|
|
220
220
|
])
|
|
221
221
|
loadNowPlayingMetaValues()
|
|
222
222
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-mp3-player",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "React Native audio player with reliable iOS background playback. Media controls, queue, hooks. Built for stability and long-running playback.",
|
|
5
5
|
"main": "lib/src/index.js",
|
|
6
6
|
"types": "lib/src/index.d.ts",
|