iosswiftavaudiosessionavaudioenginempremotecommandcenter

Is there a way to show lock screen controls using AVAudioEngine and AVAudioPlayerNode?


I am handling audio playback using AVAudioEngine and AVAudioPlayerNode in my app, and I want to implement remote controls. Background audio is configured and working.

Control center controls work, but the play/pause button does not update when I play/pause the music from inside the app. I am testing on a real device.

Control center screenshot

Here is my AVAudioSession setup code:

func setupAudioSession() {

    UIApplication.shared.beginReceivingRemoteControlEvents()

    do {
        try AVAudioSession.sharedInstance().setActive(true)
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
    } catch let sessionError {
        print("Failed to activate session:", sessionError)
    }
}

MPRemoteCommandCenter setup:

func setupRemoteControl() {

    let commandCenter = MPRemoteCommandCenter.shared()

    commandCenter.playCommand.isEnabled = true
    commandCenter.playCommand.addTarget { (_) -> MPRemoteCommandHandlerStatus in
        self.audioPlayerNode.play()
        return .success
    }

    commandCenter.pauseCommand.isEnabled = true
    commandCenter.pauseCommand.addTarget { (_) -> MPRemoteCommandHandlerStatus in
        self.audioPlayerNode.pause()
        return .success
    }
}

Lock screen controls - never appeared.


Solution

  • So here is the solution to my problem, I was starting my AVAudioEngine together with its setup function called from viewDidLoad(), that was the issue, and i used .play()/.pause() methods on my AVAudioPlayerNode to manipulate the audio, however AVAudioPlayerNode does not emit master audio, outputNode of AVAudioEngine does.

    So whenever you want to play/pause audio from inside your app or from command center, if you are using AVAudioEngine to handle audio in you application, don’t forget to call .stop()/.start() methods on your AVAudioEngine. Lock screen controls should show up and play/pause buttons should update properly in command center/lock screen even without a single property set to MPNowPlayingInfoCenter.default().nowPlayingInfo.

    MPRemoteCommandCenter setup:

    func setupRemoteControl() {
    
        let commandCenter = MPRemoteCommandCenter.shared()
    
        commandCenter.playCommand.isEnabled = true
        commandCenter.playCommand.addTarget { (_) -> MPRemoteCommandHandlerStatus in
            try? self.audioEngine.start()
            return .success
        }
    
        commandCenter.pauseCommand.isEnabled = true
        commandCenter.pauseCommand.addTarget { (_) -> MPRemoteCommandHandlerStatus in
            self.audioEngine.stop()
            return .success
        }
    }