14

In iOS 11 my music app would show the lock screen controls when I locked my iPhone. I was able to see the currently playing song and play/pause skip forward and backwards. However in upgrading to Xcode 10/iOS 12 I can no longer see the lock screen controls just the date and time...

However, if I swipe up and get that widget screen (where you can turn on airplane mode etc) I CAN see the now playing info.

Here is what I have

In the Background Modes

Modes

I have updated my code to the following:

Called in my viewDidLoad

do {
  try AVAudioSession.sharedInstance().setCategory(.soloAmbient, mode: .default, options: .allowAirPlay)
print("Playback OK")
  try AVAudioSession.sharedInstance().setActive(true)
  print("Session is Active")
} catch {
  print(error)
}


UIApplication.shared.beginReceivingRemoteControlEvents()
self.becomeFirstResponder()

I did not previously have the following code in the last working version but I added it because I found similar posts suggesting I do it

if let songInfo = self.mediaPlayer.nowPlayingItem {
  nowPlayingInfoCenter.nowPlayingInfo = [
    MPMediaItemPropertyTitle: songInfo.title ?? "",
    MPMediaItemPropertyArtist: songInfo.artist ?? "",
    MPMediaItemPropertyArtwork : songInfo.artwork?.image(at: CGSize(width: 400, height: 400)) ?? #imageLiteral(resourceName: "emptyArtworkImage")]
}

I put breakpoints on the do try it does not print either of the print functions and skips the try

Did I convert my code wrong?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
RubberDucky4444
  • 2,330
  • 5
  • 38
  • 70

1 Answers1

17

Don't forget setting up the MPRemoteCommandCenter:

import MediaPlayer

//Use an AVPlayer
var player: AVPlayer!
var playerItem: AVPlayerItem!

You may setup the AVPlayer in viewDidLoad

override func viewDidLoad() {
    super.viewDidLoad()

    let path = Bundle.main.path(forResource: "My Heart Will Go On", ofType:"mp3")!
    let url = URL(fileURLWithPath: path)
    playerItem = AVPlayerItem(url: url)
    player = AVPlayer(playerItem: playerItem)
    setupAudioSession()
}

Set the audio session like so:

func setupAudioSession() {
    do {
        try AVAudioSession.sharedInstance().setCategory(.soloAmbient, mode: .default, options: .allowAirPlay)
        try AVAudioSession.sharedInstance().setActive(true)
    } catch {
        print("Error setting the AVAudioSession:", error.localizedDescription)
    }
}

Play the audio file

func play() {
    player.play()
    setupNowPlaying()
    setupRemoteCommandCenter()
}

Which sets up the MPNowPlayingInfoCenter (customize this to your code):

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

    nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = playerItem.currentTime().seconds
    nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = playerItem.asset.duration.seconds
    nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate

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

And the MPRemoteCommandCenter:

func setupRemoteCommandCenter() {
    let commandCenter = MPRemoteCommandCenter.shared();
    commandCenter.playCommand.isEnabled = true
    commandCenter.playCommand.addTarget {event in
        self.player.play()
        return .success
    }
    commandCenter.pauseCommand.isEnabled = true
    commandCenter.pauseCommand.addTarget {event in
        self.player.pause()
        return .success
    }
}
ielyamani
  • 17,807
  • 10
  • 55
  • 90
  • 1
    Using isEnabled solved this for me. Thank you. Why isn't this in Apple's own documentation? https://developer.apple.com/documentation/avfoundation/media_assets_playback_and_editing/creating_a_basic_video_player_ios_and_tvos/controlling_background_audio – Paul Mar 15 '20 at 20:54
  • How could this be done if you have multiple AVPlayers or AVAudioPlayers? – pretz Aug 09 '20 at 01:20
  • @Paul Here is the official documentation from Apple. Please check: https://developer.apple.com/documentation/avfoundation/media_playback_and_selection/creating_a_basic_video_player_ios_and_tvos/controlling_background_audio – Istiak Morsalin Aug 05 '21 at 11:26