Topics

#123: Playing Audio in the Background πŸ”Š

Topics

Sometimes we want to play audio in our apps. It might be a podcast, a song, or a voice memo. Usually, our users will expect this audio to keep playing if they press the home button on their device. Today we'll look at how to get this working. Let's get started:

First let's setup the boilerplate basic audio playback code:

func playAudioWithData(audioData: NSData) {
  do {
    self.player = try AVAudioPlayer(data: audioData)
  } catch let error as NSError {
    self.showPlaybackFailedErrorAlert(error)
    self.player = nil
  } catch {
    self.showGenericErrorAlert("Playback Failed.")
    self.player = nil
  }

  guard let player = player else {
    self.showGenericErrorAlert("Playback Failed."); return
  }

  player.delegate = self

  guard player.prepareToPlay() && player.play() else {
    self.showGenericErrorAlert("Playback Failed."); return
  }
}

func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) {
  do { try AVAudioSession.sharedInstance().setActive(false) } catch { }
  self.player = nil
}

(Making this code "safe" in Swift can get a little ugly. πŸ˜•)

Next, we'll add a function that we'll call before we begin playback that configures our app's shared AVAudioSession to be in the β€œPlayback” category, and then we'll set the audio session to be active.

  func prepareForPlaybackWithData(audioData: NSData) {
    do {
      try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)

      do {
        try AVAudioSession.sharedInstance().setActive(true)
      } catch let error as NSError {
        self.showPlaybackFailedErrorAlert(error)
      }
    } catch let error as NSError {
      self.showPlaybackFailedErrorAlert(error)
    }
  }

Finally, we'll head over to our project's Capabilities tab in Xcode and enable the "Audio, AirPlay and Picture in Picture" background mode.

Success! Now when we send our app to the background, its audio continues playing.