MPRemoteCommandCenter not working with MPMusicPlayerController applicationMusicPlayer

Hey guys,

I'm working on an App that plays Apple Music tracks. Therefore I'm using

MPMusicPlayerController.applicationMusicPlayer

everything is working great so far - including setting the

musicPlayer.currentPlaybackRate

which is kind of important for my use case.

Now I'm trying to setup of the lock screen-controls for my App correctly, especially because using the default ones will reset the currentPlaybackRate to 1.0 after play/pausing. Also I have to sync my internal playState if "pause" is pressed in the lock screen.

Here is what I wrote:

class AudioPlayerViewModel {
...
    private let commandCenter = MPRemoteCommandCenter.shared()
    init(album: LibraryAlbum? = nil) {
        ...
        self.setupRemoteCommandCenter()

    }

...
func setupRemoteCommandCenter() {
        debugPrint("setupRemoteCommandCenter()")
        
        commandCenter.previousTrackCommand.isEnabled = false
        commandCenter.previousTrackCommand.addTarget { event in
            debugPrint("remote previousTrackCommand")
            self.previousTrack()
            return .success

        }

        commandCenter.nextTrackCommand.isEnabled = false
        commandCenter.nextTrackCommand.addTarget { event in
            debugPrint("remote nextTrackCommand")
            self.nextTrack()
            return .success
        }

        commandCenter.pauseCommand.isEnabled = false
        commandCenter.pauseCommand.addTarget { event in
            debugPrint("remote pauseCommand")
            self.isPlaying = false
            self.pausePlayback()
            return .success
        }

        commandCenter.playCommand.isEnabled = false
        commandCenter.playCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
            debugPrint("remote playCommand")
            self.isPlaying = true
            self.continuePlayback()
            return .success
        }
    }
}

I call setupRemoteCommandCenter() once(!) before playing anything in MPMusicPlayerController.applicationMusicPlayer

My problem is these handlers never get called. The lock screen-controls always remain the default ones. My code has no effect, but also throws no errors.

I find several posts about this. The Apple Documentation (https://developer.apple.com/documentation/mediaplayer/handling_external_player_events_notifications) states the this should be possible.

What am I doing wrong?

Any help would be greatly appreciated.

Replies

Sorry, about that link. That states that it is NOT possible. But I know that it is, because https://apps.apple.com/de/app/ecoute/id536882653 is able to do it.

To add to this. THIS is the actual article that mentions that this should work: https://developer.apple.com/documentation/mediaplayer/mpmusicplayercontroller (under „Using Remote-Control Events with a Music Player“). But the Internet is still unsure if this really works. From my experience it seems not to.

What does indeed work is using NotificationCenter. That way it is at least possible to update playbackRate back from 1.0 again:

...
    func setupNotificationCenter() {

        debugPrint("setupNotificationCenter()")

        NotificationCenter.default.addObserver(self, selector: #selector(handleNowPlayingItemDidChange), name: .MPMusicPlayerControllerNowPlayingItemDidChange, object: nil)

        NotificationCenter.default.addObserver(self, selector: #selector(handlePlaybackStateDidChange), name: .MPMusicPlayerControllerPlaybackStateDidChange, object: nil)

    }

    

    @objc func handleNowPlayingItemDidChange(notification: NSNotification) {

        debugPrint("handleNowPlayingItemDidChange()")

        updateCurrentTrack()

    }

    

    @objc func handlePlaybackStateDidChange(notification: NSNotification) {

        debugPrint("handlePlaybackStateDidChange()")

        if musicPlayer.playbackState == .playing {

            handleContinuePlayback()

        } else {

            handlePause()

        }

    }

Still I'd appreciate any help, if customizing the MPRemoteCommandCenter is actually possible.

When trying the "old way" of using

commandCenter.previousTrackCommand.addTarget(self, action: #selector(handlePreviousTrackCommand))

I noticed that I always get an methodSignatureForSelector not found - error. Can't tell why this happens, the method does definitely exist.

Ok, to settle this once and for all: I talked to Apple via Support. Their engineers say that customising MPRemoteCommandCenter is NOT supposed to work with any of this.

Notifications work fine though. So that is a dead end.