3

I use AVPlayerViewController to play short videos in my app.

If there is an app playing audio in background before user plays a video in my app, I want the background audio playing of the other app to resume after my video player is dismissed. I currently use AVAudioSession.setActive(false, with: .notifyOthersOnDeactivation) to do that.

Even though Apple's Music app and Podcasts app do resume playing after I call AVAudioSession.setActive(false, with: .notifyOthersOnDeactivation)—won't resume without the call so it means this call does have effect—none of the 3rd party music or podcast apps that I tested(Spotify, SoundCloud, Amazon Music, Overcast) do.

Here is my code:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    // I know it's not the best place to call setActive nor it covers all the cases. It's just a convenient place to put the code to test its effect after dismissing the video player.
    do {
        try AVAudioSession.sharedInstance().setActive(false, with: .notifyOthersOnDeactivation)
    } catch {
        print(error)
    }
}

@IBAction func play(_ sender: Any) {
    do {
        try AVAudioSession.sharedInstance().setActive(true)
    } catch {
        print(error)
    }

    let playerController = AVPlayerViewController()
    playerController.player = AVPlayer(url: URL(string: "http://gslb.miaopai.com/stream/UkjiD45ddxZFQ79I2bLaGg__.mp4")!)
    playerController.player?.play()
    present(playerController, animated: true)
}

At first I thought it might be these 3rd party apps' fault. But then I tested them with the official Twitter app and found they can resume audio playback after video playing in Twitter app.

So what did I miss? What should I do to make these 3rd party apps resume audio playback after video playing in my app, just as Twitter app does?

PS: here is the complete project so anyone interested can try it.

an0
  • 17,191
  • 12
  • 86
  • 136

3 Answers3

4

I want the background audio playing of the other app to resume after my video player is dismissed

You need to accept that that isn't up to you. All you can do is manage your audio session properly. Whether some other app "takes the hint" and resumes its audio is not in your control.

However, you are not quite managing your audio session properly. You should:

  • Use a noninterfering category in general (such as Ambient).

  • Change to your Playback category and activate it only when you need it (i.e. only when we are actually just about to play)

  • When you are done playing, deactivate with notifyOthersOnDeactivation and then switch back to a non-interfering audio category (such as Ambient) and activate it.

Once you've done those things, you've done all you can do. Some apps will resume, others won't.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • 2
    Hi, thanks for your answer. Did you test your way with any 3rd party apps? As I said, if only for Apple's Music and Podcasts apps, simply deactivating with `notifyOthersOnDeactivation` is enough. I've updated my code according to your advice but it still couldn't resume 3rd party apps. Initially I also suspected it's those apps' fault but then I tested them with Twitter app and found they can resume after playing videos in Twitter. So there must be something we missed. – an0 Feb 23 '17 at 17:33
  • I tested with _my_ app that listens for interruptions that end with the `shouldResume` option, and what I said does work. Obviously I don't know what Twitter does. – matt Feb 23 '17 at 17:47
  • Interesting. So none of these popular 3rd party apps implements audio playback resuming correctly but Twitter somehow found a workaround for their mistakes? Thanks anyway. – an0 Feb 23 '17 at 17:57
  • @an0 I dont think that is true. `AVAudioSession` is a OS session queue, Twitter is not doing anything out of the ordinary, they simply have it implemented correctly. I tested Twitter with Apple Music, Spotify and bunch of other music app and it worked fine. But My app wasn't able to resume the background music, or sometime it did resume and then paused after a brief while when a video showed in muted status. This told me that I was doing something wrong, and I sure was. – Anjan Biswas Apr 30 '18 at 03:13
3

Now I can confirm it is a bug: https://openradar.appspot.com/31733529. And this bug is fixed in iOS 11.

an0
  • 17,191
  • 12
  • 86
  • 136
  • I'm currently still seeing this issue interrupting Spotify on iOS 11 using AVPlayer, AVAudioPlayer, and AVAudioEngine (after interruption, it doesn't resume). Your project isn't online anymore. Have you verified that it's fixed in iOS 11? – Rob Napier Mar 09 '18 at 17:04
  • I don’t have the code with me but I’m sure this bug of `AVPlayerViewController` is fixed in iOS 11. My app is using it and it works fine. I’m not sure about using `AVPlayer` directly. – an0 Mar 09 '18 at 17:15
  • I think the issue has to do with remote control events; were you using MPRemoteCommandCenter or beginReceivingRemoteControlEvents? – Rob Napier Mar 09 '18 at 17:16
  • No I’m not using that. Sorry I couldn’t help. – an0 Mar 09 '18 at 17:34
  • 1
    I think the issue still exists with `AVPlayer`. – Anjan Biswas Apr 30 '18 at 03:24
  • I don't think the bug has ever been fixed. It's still reproducible in iOS 14. But turns out, adding this one line of code `playerViewController.updatesNowPlayingInfoCenter = false` is well enough to resolve the issue, although you can no longer showing content on the Now Playing center. – Jonny Oct 12 '20 at 14:08
0

You need to implement the AVAudioSession Notifications. . For each interruption or when your app is done with playing the media file, it will fire the notification and from there you can resume the already paused media file from device libraries.

Ankur JAIN
  • 111
  • 8
  • `AVAudioSessionDelegate`? From the doc: "The use of this protocol is deprecated in iOS 6 and later. Instead, you should use the notifications declared in AVAudioSession." – an0 Feb 23 '17 at 15:26