Handle Remote Control Commands

iOS Applications that play audio in background mode, can be controlled from remote control commands inside command center or the lock screen of device.

We will need to import MediaPlayer initially.

import MediaPlayer

And also player in our UIViewController subclass

var player: AVPlayer?

We will need setup function which can enable/disable remote commands

func setupRemoteCommandCenter(enable: Bool) {

    let remoteCommandCenter = MPRemoteCommandCenter.shared()

    if enable {

        remoteCommandCenter.pauseCommand.addTarget(self, action: #selector(remoteCommandCenterPauseCommandHandler))
        remoteCommandCenter.playCommand.addTarget(self, action: #selector(remoteCommandCenterPlayCommandHandler))
        remoteCommandCenter.stopCommand.addTarget(self, action: #selector(remoteCommandCenterStopCommandHandler))
        remoteCommandCenter.togglePlayPauseCommand.addTarget(self, action: #selector(remoteCommandCenterPlayPauseCommandHandler))

    } else {

        remoteCommandCenter.pauseCommand.removeTarget(self, action: #selector(remoteCommandCenterPauseCommandHandler))
        remoteCommandCenter.playCommand.removeTarget(self, action: #selector(remoteCommandCenterPlayCommandHandler))
        remoteCommandCenter.stopCommand.removeTarget(self, action: #selector(remoteCommandCenterStopCommandHandler))
        remoteCommandCenter.togglePlayPauseCommand.removeTarget(self, action: #selector(remoteCommandCenterPlayPauseCommandHandler))

    }

    remoteCommandCenter.pauseCommand.isEnabled = enable
    remoteCommandCenter.playCommand.isEnabled = enable
    remoteCommandCenter.stopCommand.isEnabled = enable
    remoteCommandCenter.togglePlayPauseCommand.isEnabled = enable

}

This function will be called with true to enable

setupRemoteCommandCenter(enable: true)

And should be called with false in deinit to stop handling remote commands

deinit {        
    setupRemoteCommandCenter(enable: false)
}

And the actual function selectors to handle remote commands

func remoteCommandCenterPauseCommandHandler() {

    // handle pause
    player?.pause()

}

func remoteCommandCenterPlayCommandHandler() {

    // handle play
    player?.play()

}

func remoteCommandCenterStopCommandHandler() {

    // handle stop
    player?.pause()

}

func remoteCommandCenterPlayPauseCommandHandler() {

    // handle play pause
    if player?.rate == 0.0 {
        player?.play()
    } else {
        player?.pause()
    }

}

We will need setup player function

func setupPlayer() {

    let streamURL = URL(string: "https://audio.stream.m3u8")!
    self.player = AVPlayer(url: streamURL)
    self.player?.play()

}

And in our example, we have a button selector function to call necessary code

@IBAction func playButtonHandler(btn: UIButton) {

    setupRemoteCommandCenter(enable: true)

    setupPlayer()

}

Here is gist for the example

// https://hashaam.com/2017/07/19/handle-remote-control-commands/
import UIKit
import MediaPlayer
class ViewController: UIViewController {
var player: AVPlayer?
func setupRemoteCommandCenter(enable: Bool) {
let remoteCommandCenter = MPRemoteCommandCenter.shared()
if enable {
remoteCommandCenter.pauseCommand.addTarget(self, action: #selector(remoteCommandCenterPauseCommandHandler))
remoteCommandCenter.playCommand.addTarget(self, action: #selector(remoteCommandCenterPlayCommandHandler))
remoteCommandCenter.stopCommand.addTarget(self, action: #selector(remoteCommandCenterStopCommandHandler))
remoteCommandCenter.togglePlayPauseCommand.addTarget(self, action: #selector(remoteCommandCenterPlayPauseCommandHandler))
} else {
remoteCommandCenter.pauseCommand.removeTarget(self, action: #selector(remoteCommandCenterPauseCommandHandler))
remoteCommandCenter.playCommand.removeTarget(self, action: #selector(remoteCommandCenterPlayCommandHandler))
remoteCommandCenter.stopCommand.removeTarget(self, action: #selector(remoteCommandCenterStopCommandHandler))
remoteCommandCenter.togglePlayPauseCommand.removeTarget(self, action: #selector(remoteCommandCenterPlayPauseCommandHandler))
}
remoteCommandCenter.pauseCommand.isEnabled = enable
remoteCommandCenter.playCommand.isEnabled = enable
remoteCommandCenter.stopCommand.isEnabled = enable
remoteCommandCenter.togglePlayPauseCommand.isEnabled = enable
}
deinit {
setupRemoteCommandCenter(enable: false)
}
func remoteCommandCenterPauseCommandHandler() {
// handle pause
player?.pause()
}
func remoteCommandCenterPlayCommandHandler() {
// handle play
player?.play()
}
func remoteCommandCenterStopCommandHandler() {
// handle stop
player?.pause()
}
func remoteCommandCenterPlayPauseCommandHandler() {
// handle play pause
if player?.rate == 0.0 {
player?.play()
} else {
player?.pause()
}
}
func setupPlayer() {
let streamURL = URL(string: "https://audio.stream.m3u8")!
self.player = AVPlayer(url: streamURL)
self.player?.play()
}
@IBAction func playButtonHandler(btn: UIButton) {
setupRemoteCommandCenter(enable: true)
setupPlayer()
}
}


Posted

in

by

Comments

4 responses to “Handle Remote Control Commands”

  1. Carl Smith Avatar
    Carl Smith

    Helped me isolate a problem I was having with my code which used MPRemoteCommandCenter. Turns out the problem was not in the handler code itself, which building a project from your straightforward code above showed me. Many thanks!

    Like

    1. chashaam Avatar

      Appreciate the feedback. Glad to help. By the way, I have started my youtube channel to cover complete in-depth series to develop apps.

      Like

  2. Wayne H. Avatar
    Wayne H.

    Thanks for this! I had buggy Now Playing lockscreen controls and your post helped me sort out my issues. I also like how you implemented a Boolean argument for enabling/disabling MPRemoteCommandCenter; I never thought about doing that but that’s exactly what I needed to do.

    Like

    1. Hashaam Siddiq Avatar

      Glad you found this helpful.

      Like

Leave a comment