Article

Controlling Background Audio

Support controlling background audio from the Control Center and iOS Lock screen.

Overview

If your app plays audio in the background, support remotely controlling playback both in Control Center and from the iOS Lock screen. Along with controlling playback, also provide meaningful information in these interfaces about what’s currently playing. To implement this functionality, you use the Media Player framework’s MPRemoteCommandCenter and MPNowPlayingInfoCenter classes.

Configure the Remote Command Handlers

The MPRemoteCommandCenter class configures objects used for handling remote-control events sent by external accessories and system transport controls. It defines a variety of commands in the form of MPRemoteCommand objects to which you can attach custom event handlers to control playback in your app. For instance, to remotely control your app’s play and pause behaviors, you get a reference to the shared command center and provide handlers for the appropriate commands.

func setupRemoteTransportControls() {
    // Get the shared MPRemoteCommandCenter
    let commandCenter = MPRemoteCommandCenter.shared()

    // Add handler for Play Command
    commandCenter.playCommand.addTarget { [unowned self] event in
        if self.player.rate == 0.0 {
            self.player.play()
            return .success
        }
        return .commandFailed
    }

    // Add handler for Pause Command
    commandCenter.pauseCommand.addTarget { [unowned self] event in
        if self.player.rate == 1.0 {
            self.player.pause()
            return .success
        }
        return .commandFailed
    }
}

The preceding example shows how to add handlers for the command center’s playCommand and pauseCommand using the addTarget(handler:) method. The callback block you give to this method requires that you return a MPRemoteCommandHandlerStatus value, indicating whether the command succeeded or failed.

Provide Display Metadata

After you’ve configured your remote command handlers, the next step is to provide metadata to display on the iOS Lock screen and in Control Center’s transport area. You provide a dictionary of metadata using the keys defined by MPMediaItem and MPNowPlayingInfoCenter and set that dictionary on the default instance of MPNowPlayingInfoCenter. The following example shows you how to set a title and artwork for the currently presented media, along with playback timing values:

func setupNowPlaying() {
    // Define Now Playing Info
    var nowPlayingInfo = [String : Any]()
    nowPlayingInfo[MPMediaItemPropertyTitle] = "My Movie"

    if let image = UIImage(named: "lockscreen") {
        nowPlayingInfo[MPMediaItemPropertyArtwork] =
            MPMediaItemArtwork(boundsSize: image.size) { size in
                return image
        }
    }
    nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = playerItem.currentTime().seconds
    nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = playerItem.asset.duration.seconds
    nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate

    // Set the metadata
    MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
}

This example passes dynamic timing as part of the nowPlayingInfo dictionary, which allows you to present player timing and progress in the remote-control interfaces. When doing so, provide an up-to-date snapshot of this timing as your app enters the background. You can also update the nowPlayingInfo while your app is in the background, if media information or timing changes significantly.

See Also

Working with Background Audio

Enabling Background Audio

Configure your app to continue playing audio when it goes into the background.

Playing Audio from a Video Asset in the Background

Continue playing audio from a video asset when the video moves into the background.