There are a lot of questions relating to background music playback in iOS on StackOverflow. None fully explore all edge cases, the aim of this question is to be the final word in background audio question on iOS
All the code, questions and examples refer to ios5.
"background" — The state an app is put into when the user presses the home button or the power button (so the devices displays the lock screen). The app can also be put into background using the multitasking switcher or the multitasking gestures on iPad.
"audio" — Audio played back using AudioQueue (including AVAudioPlayer)
As I understand it there are 2 requirements to get an app to play audio in the background.
UIBackgroundModes
to audio
in the Info.plist
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
My use-case is playing relatively long audio in the background (music). There are potentially hundreds of tracks and the app will play them sequentially. It can be considered that the audio will play indefinitely.
The app will handle interruptions by pausing the playback.
I've had mixed success with:
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:...];
Allowing audio to play in the background. But I'm confused as to if its required and how it differs to:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
Interruptions. If you register to be notified of audio interruptions (phone calls etc), by becoming the delegate of AVAudioPlayer
. For example, if you then pause or stop your audio when an interruption starts and resume when it ends is your app suspended if the interruption exceeds 10 minutes (max time allowed for background tasks to complete)?
The Simulator will stop the audio if Lock or Home are invoked, while using:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
However this works on a device. Is this a known issue?
Go to Settings > Accessibility > Audio/Visual > Background Sounds, then turn on Background Sounds. Set any of the following: Sound: Choose a sound; the audio file downloads to your iPhone. Volume: Drag the slider.
Background Sounds offers six different ambient noises that play on a loop: rain, stream and ocean, as well as bright, balanced and dark noise, which are different pitches of white noise. You can play these by themselves or under any podcast, music or video streaming app.
Apple added new Background Sounds (rain, bright noise, ocean, and more) to the iPhone with iOS 15. To activate, head to Settings > Accessibility > Audio/Visual > Background Sounds > Toggle to on.
With iOS 15 and iPadOS 15 or later, you can play ambient soundscapes in the background with your iPhone, iPad, or iPod touch. Listen to ocean, rain, bright noise sounds, and more.
I have some experience with GPS background mode, and background audio. This is not exactly the same as your situation (you want to play a long audio file, and I play short messages) but here's what I can tell you:
beginBackgroundTaskWithExpirationHandler
This selector has one purpose when being invoked when in background: avoid the application to return to the suspended state in which no code can be invoked anymore (you're "frozen"). So as long as you invoked beginBackgroundTaskWithExpirationHandler
and before you terminated your long running task with beginBackgroundTaskWithExpirationHandler
, you use the CPU, and consume battery.
I really doubt that playing a file in the background should use the battery of the iPhone as if it was running an app so I doubt that beginBackgroundTaskWithExpirationHandler
is really involved in your flow.
Simulator: don't rely on the simulator: it does not fully implement background modes. Actually, when you click on the home button, your app goes in background, but at this stage, you may still be able to execute code in your app. After a while, then, your app will be suspended (=frozen), and your code execution will be suspended in order to save the battery. This suspended state will never occur on the simulator.
Interruptions. It's not up to you to pause/resume the playback when a phone call comes in. the platform is in charge of this, and you can just react to this with your AVAudioSessionDelegate . However, you can influence the way your session is going to interact with other audio sounds by setting property on your audio session (see kAudioSessionProperty_OverrideCategoryMixWithOthers for instance). So the flow is more: your describe the way your audio session should interact with the rest of the system, the system will mix the sounds accordingly to that, and if your session gets interrupted, you'll be notified with the AVAudioSessionDelegate.
Hope this helps.
I have used below code to Device Control -
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
Used to get register for listening the remote control. Once done remove it -
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
[self resignFirstResponder];
make the App canBecomeFirstResponder-
- (BOOL)canBecomeFirstResponder {
return YES;
}
Used delegate method to handle iPhone control, like play and pause while doble tap on the home button
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
//if it is a remote control event handle it correctly
if (event.type == UIEventTypeRemoteControl) {
if (event.subtype == UIEventSubtypeRemoteControlPlay) {
[audioPlayer play];
NSLog(@"play");
} else if (event.subtype == UIEventSubtypeRemoteControlPause) {
[audioPlayer stop];
NSLog(@"pause");
} else if (event.subtype == UIEventSubtypeRemoteControlTogglePlayPause) {
NSLog(@"toggle");
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With