Turning off audio background mode triggers kMIDINotPermitted even though background audio is not needed - audiokit

I've got a MIDISampler that is triggered by a MIDICallbackInstrument. I don't want my app to work in the background since it is an interactive ear training game. Unfortunately if I disable "Audio, AirPlay, and Picture in Picture" I get the following error:
CheckError.swift:CheckError(_:):176:kMIDINotPermitted: Have you enabled the audio background mode in your ios app?
Also the sampler plays fixed pitch sine waves instead of samples.
The solution would be to just turn on the audio background mode though it is not needed. Everything works fine, no errors. Unfortunately Apple is rejecting my app in that case since it's not using background audio.
Does anyone know a work around for this?

You need background audio enabled for MIDISampler. As long as your app is stopping the audio engine when the app moves into the background, they should allow it. I would explain your use case and appeal the rejection.

Related

HLS audio stream fails to resume play after time in background (AVPlayer refuses to buffer)

I have an iOS app that is designed to play HLS audio stream content.
The app supports time-shifting - you can skip backward, skip forward, scrub backward/forward, as well as pause the stream and unpause to where you left off.
The app works fine when operating in the foreground. It also works fine when actovely playing in the background (I have the background audio entitlement set correctly).
However, if the app is put into the background for more than a few moments (~30 seconds seems to do it) with the audio paused and either A) the user un-pauses the audio, or B) the user returns the app to the foreground and attempts to un-pause it from there, the audio does not play even after waiting a few moments. Note that the app process is not killed during this time.
To pause and unpause, I am using AVPlayer's pause and play methods.
While looking into it, I verified that the buffer (determined by looking at loadedTimeRanges) is filled during normal playback, but is quickly emptied shortly after the paused app is put in the background. If the app is returned to the foreground quickly enough, the buffer begins to fill again and playback can resume. Otherwise - if the user moves the app to the background for ~30 seconds - the buffer never refills at all and attempting to play again fails until the AVPlayerItem is re-configured.
I realize that there is no guarantee that the buffer will always have content (ie. it could be emptied to minimize memory footprint, which I suspect is the case here), but would expect AVPlayer to begin to start loading audio from it again as needed when playback resumes. Even if it has been in the background for a while.
Does anybody have an idea why this is occurring or how to work around it?
Note: I have created a simple sample iOS 14+ Xcode project that exhibits the problem using a known HLS stream. Tap 'Configure' to load the URL, then play/pause to exhibit the issue (I added console output showing the state of loadedTimeRanges).
https://tapestryapps.com/AudioTestbed.zip
Thank you.
If anyone is still experiencing this when working with HLS and changing the playerViewController?.player?.currentItem?.preferredPeakBitRate = 1 to safe data when backgrounding the application a workaround for this is to lower the buffer size playerViewController?.player?.currentItem?.preferredForwardBufferDuration = 10
When returning back to foreground all values can be set again to the default of 0
As an alternative you could also replace the playerViewController?.player?.currentItem but this would then result in video and audio buffering again.
The code works for me on iOS 13.5.1 and iOS 14.4, but fails on 14.0.1.
It looks like an iOS bug. You could work around this by recreating the AVPlayerItem when returning to the foreground on affected systems.

How to resume audio playback of other apps after deactiving the audio session and how to start audio playback in the background without mixing?

I am building a iOS app with Ionic and Capacitor. I use AVFoundation inside a Capacitor plugin which provides a public method to play an audio file accessible at a remote URL. The basics work, the audio file is successfully played. Now I want to correctly handle interruptions and background audio. By background audio I mean start playing an audio file while the app is in the background and not continue playing it in the background when it was started in foreground before. To summarize, the app should behave the following way:
If another app (e.g. Spotify) is playing audio and my app wants to play audio, the other app should be interrupted and my app's audio should start playing without mixing.
If my app's audio is finished playing, the other app's audio should resume.
My app must be able to start playing audio without mixing when it is in the background.
I want to show a play/pause button and the audio title on the lockscreen and in the notification center.
I added the background mode audio capability. I use AVPlayer, AVAudioSession, MPNowPlayingInfoCenter and MPRemoteCommandCenter, followed best practices, especially regarding activation and deactivation of an audio session and interruption handling. I followed this question and this question. I tried several solutions, but never managed to achieve all of the above goals. What I found out so far is the following:
Goal 1. above is easy to achieve. Simply activate an audio session without mixing and start playing the audio.
After the audio of my app is finished, I deactivate the audio session. Unfortunately, I can only achieve goal 2. above if I don't use remote commands nor notification info. This means, my app then has no audio control UI on the lockscreen nor in the notification center. Somehow the configurations of MPNowPlayingInfoCenter and MPRemoteCommandCenter seem to affect the interruption behavior. As far as I could see, Apple documentation doesn't say anything about this.
I only manage to start playing audio in the background when setting the option .mixWithOthers. Apple documentation doesn't say anything about this, either.
Any help would be greatly appreciated.
Rony

Using the TTS Synthesizer in iOS when the app is ALREADY on the background

I would like to play a sound and use the AVSpeechSynthesizer to speak out some strings. The point is that I want these to happen when the device is already locked and then some events happen which triggers them.
I've found lots of info about how to play sound on the background, but this means that playback starts when the app is active and then the playback could continue, if the screen is being locked (after the start of playback). I've done all the tricks but can't hear a sound, which is triggered when the device is locked (and app is already on the background). However this works with iOS 8.3 simulator almost out-of-the-box, but not with a device.
So how to resolve this? Should I actually use some notification stuff to produce the desired outcome? I'm not too familiar with the notifications, so is there any other workarounds or is the notifications way easier than I think?
Cheers,
Mikko

Play Audio when suspending to background

I have an app that under certain circumstances needs to play audio the moment it is pushed into background.
I can't use any background key, as I don't fulfill any requirements for these and Apple rejected my app, when I tried to use the background audio key.
Currently I'm start playing the audio file and then request extra processing time within applicationDidEnterBackground: The audio never gets played even though I have the processing time and the app is still running (I've used an NSTimer to check every 2 seconds).
As audio mode I'm using AVAudioSessionCategoryPlayback with AVAudioSessionCategoryOptionMixWithOthers.
With active background audio mode this works fine.
I also know, that I could use local notification and play the audio file there (as it is under 30 seconds), but that would be my last resort.
Does Apple prevent audio from being played in applicationDidEnterBackground: ?
I get a callback for audioPlayerBeginInterruption: immediately.
I've seen:
Why does the following code to play audio in the background not work?
But this doesn't seem to work anymore on iOS8.
Thanks :)
Your app should not be playing a sound (and certainly not a sound of any length) just because the user backgrounds it, and now Apple has succeeded in stopping you from doing this. You should accept this, abandon your attempts to work around this perfectly reasonable restriction, and move on.

Prevent AirPlay from sleeping

I have an app that uses AirPlay. I am using the iPad to present data on a TV. The user sets up the demo and then puts the device down and the app should take care of updating the TV even in the background state. The app is processing data in the background and I can see it is always being updated. However the AirPlay disconnects after a few minutes if nothing on the screen changes.
How can I prevent AirPlay from disconnecting?
Note:
I am not streaming video or audio. I am only presenting data using views.
Update:
After more twiddling I found that the background task dies after 10 minutes and that is when the screen dies. I tried to play a sound like https://stackoverflow.com/a/15732710/1449607 described but the AirPlay still disconnected. I am now toggling a pixel and now it seems that the screen is staying connect. There must be a better solution for displaying slowly updating data to AirPlay.

Resources