How do Now Playing info, remote commands, Picture in Picture and AirPlay integrate a player with the system?
Predict first
Now Playing info is set and read back. What does the dictionary hold?
import MediaPlayer
MPNowPlayingInfoCenter.default().nowPlayingInfo = [MPMediaItemPropertyTitle: "Song", MPNowPlayingInfoPropertyElapsedPlaybackTime: 12.0]
print(MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPMediaItemPropertyTitle] as? String ?? "nil", MPNowPlayingInfoCenter.default().nowPlayingInfo?.count ?? 0)
- Song 2
- nil 0
- Song 1
Mental model. Now Playing is the label on the jukebox display, and remote commands are the buttons on the front. If the label is wrong or a button does nothing, the system looks broken even when the music is fine.
A media app is not just a player; the system, headphones, the car and other devices all want to know what is playing and to control it. Now Playing: set MPNowPlayingInfoCenter.default().nowPlayingInfo to a dictionary (title, artist, album, artwork as MPMediaItemArtwork, MPMediaItemPropertyPlaybackDuration, MPNowPlayingInfoPropertyElapsedPlaybackTime, MPNowPlayingInfoPropertyPlaybackRate) and the lock screen, Control Center, CarPlay and the Dynamic Island show it; the values round-trip, so reading the dictionary back returns the same entries. Update the elapsed time and rate on state changes (play, pause, seek), not every second, because the system extrapolates from the rate; stale or wrong values are the common bug. If you use AVPlayer with AVPlayerViewController the system manages much of this automatically (updatesNowPlayingInfoCenter), and you add only metadata. Remote commands: MPRemoteCommandCenter.shared() exposes playCommand, pauseCommand, togglePlayPauseCommand, nextTrackCommand, previousTrackCommand, changePlaybackPositionCommand (scrubbing), skipForwardCommand and more: enable the ones you support and add a handler returning .success or a failure status. Headphone buttons, the lock screen and CarPlay all arrive through these, so an unsupported command should be disabled rather than ignored. The prerequisite is an active audio session with a playback category and, for background, the Audio background mode.
Picture in Picture floats the video over other apps. With AVPlayerViewController it is automatic once you have the audio background mode and a playback category; with a custom AVPlayerLayer use AVPictureInPictureController, and implement its delegate to restore your UI when the user taps back (restoreUserInterfaceForPictureInPictureStop), and for custom (non-AVPlayer) rendering use the sample-buffer PiP content source, which suits video calls and custom players. Starting PiP automatically when the app backgrounds is a property to set (canStartPictureInPictureAutomaticallyFromInline). AirPlay sends audio or video to another device: AVPlayer supports it natively (allowsExternalPlayback), you add the route picker (AVRoutePickerView) and the system shows the control, and for mirroring-only content you need nothing. With AVPlayer, AirPlay playback happens on the receiver (it fetches the stream itself), so tokens and URLs must work from another device and network. Practical advice: test on a device with the lock screen, a Bluetooth headset, CarPlay if you support it, a PiP-capable iPad or iPhone and an Apple TV, handle audio interruptions consistently across all of them, keep Now Playing in sync after route changes, and fall back gracefully where a feature is unavailable (PiP is not supported for some content or when FairPlay restrictions apply).
The dictionary round-trips: the title and the elapsed time are both stored.
Common traps
- Updating Now Playing every second. Set elapsed time and rate on state changes; the system extrapolates.
- Leaving unsupported remote commands enabled. The buttons appear but do nothing; disable what you do not handle.
They might follow up with
- What do PiP and Now Playing both need? An active playback audio session, and the Audio background mode for background use.
- Where does AirPlay playback happen for an
AVPlayer? On the receiver, which fetches the stream itself.
Related questions
- 18.4.1 How does HLS adaptive streaming work, why do stalls happen, and what does FairPlay add?
- 18.2.1 What is the AVAudioSession, how do categories and modes decide behaviour, and how do you handle interruptions…
- 18.6.2 How would you design and operate a playback platform shared by many apps: quality metrics, startup time…
← How does HLS adaptive streaming work, why do stalls happen, and what…