How to pause background player in iOS - ios

I have this scenario:
In the background the default iPhone audio player (or any other audio player) is playing some music.
In the foreground my application is running. Then, under certain circumstances, my application has to play audio file (bit like a GPS navigator).
I want my application to pause the background player (ducking is not enough), to play its file and then to continue playing the background player.
Is this possible?
Thank you,
donescamillo#gmail.com

From iOS 6 onwards you can set your audio session active, play your file and then deactivate your session with options using the AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation flag. Make sure you set a non-mixable category when you need to play audio so background audio stops.
In simple steps -
// Configure audio session category and activate ready to output some audio
[[AVAudioSession sharedInstance] setActive:YES error:nil];
// Play some audio, then when completed deactivate the session and notify other sessions
[[AVAudioSession sharedInstance] setActive:NO withOptions: AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];
From Apple's documentation-
When passed in the flags parameter of the setActive:withOptions:error: instance method, indicates that when your audio session deactivates, other audio sessions that had been interrupted by your session can return to their active state.
This flag is used only when deactivating your audio session; that is, when you pass a value of NO in the beActive parameter of the setActive:withOptions:error: instance method
and also-
Deactivating your session will fail if any associated audio objects (such as queues, converters, players or recorders) are currently running.
EDIT: A more detailed example -
Configure a mixable audio session at the start of your applications lifecycle
// deactivate session
BOOL success = [[AVAudioSession sharedInstance] setActive:NO error: nil];
if (!success) { NSLog(#"deactivationError"); }
// set audio session category AVAudioSessionCategoryPlayAndRecord
success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];
if (!success) { NSLog(#"setCategoryError"); }
// set audio session mode to default
success = [[AVAudioSession sharedInstance] setMode:AVAudioSessionModeDefault error:nil];
if (!success) { NSLog(#"setModeError"); }
// activate audio session
success = [[AVAudioSession sharedInstance] setActive:YES error: nil];
if (!success) { NSLog(#"activationError"); }
When your application wants to output audio without any background audio playing, change the audio session category first like this
// activate a non-mixable session
// set audio session category AVAudioSessionCategoryPlayAndRecord
BOOL success;
AVAudioSessionCategoryOptions AVAudioSessionCategoryOptionsNone = 0;
success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionsNone error:nil];
if (!success) { NSLog(#"setCategoryError"); }
// set audio session mode default
success = [[AVAudioSession sharedInstance] setMode:AVAudioSessionModeDefault error:nil];
if (!success) { NSLog(#"setModeError"); }
// activate audio session
success = [[AVAudioSession sharedInstance] setActive:YES error: nil];
if (!success) { NSLog(#"activationError"); }
// commence playing audio here...
And when your application has completed playing audio you can deactivate your audio session
// deactivate session and notify other sessions
// check and make sure all playing of audio is stopped before deactivating session...
BOOL success = [[AVAudioSession sharedInstance] setActive:NO withOptions: AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error: nil];
if (!success) { NSLog(#"deactivationError"); }
I can confirm that the above code works, tested with the Music App playing on an iPhone 5 running iOS 7.0.4, however this is not guaranteed because there are other considerations such as user actions. For example if I plug in a headset the background audio from the music app routes to the headset and continues to play, but if I remove the headset the background audio produced by the music app pauses.
For more info read AVAudioSession Class Reference

Related

iOS when finished recording, turn off red status bar for AV Audio Recorder

My app both records with and asks permission to use, background recording. I enjoy the red status bar while recording despite the fact that no one else seems to. My problem is turning it off...
This is the code I use when I am finished with the recording process:
- (void)stopRecording {
[self.recorder pause];
[self.recorder stop];
self.recorder = nil;
[self.audioSession setActive:NO error:nil];
self.audioSession = nil;
}
I want this red bar to be gone once the recording is done (or at least shortly thereafter) to let the user know it has finished. Obviously it refuses and a quick Google search will show that a number of other people have had similar problems. Can anyone tell me what the solution is because I have at least 2 apps I have found that respond properly to stopping a recording and shutting it off at an appropriate time.
Turns out I was missing just a few lines of code... here they are:
- (void)stopRecording {
[self.recorder pause];
[self.recorder stop];
self.recorder = nil;
[self.audioSession setActive:NO error:nil];
[self.audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
self.audioSession = nil;
}

my app media play in background mode didn't play if once I open apple music app

I have problem with media play in background mode.
In my app I have to play media play in background mode when server send any notification through socket connection.
In my case media player working fine when app in background mode.
Problem is when app in background mode if I play music app and stop the music player and send notification to my app .Than my app didn't play media player.
I added in plist this one "App plays audio or streams audio/video using AirPlay"
I am using "AVPlayer"
Please help me.
Thanks.
If you look into the AVPlayer documentation it says that it can only play one asset at a time. I think Apple Music uses if not the same API something that is related to this.
AVPlayer is intended for playing a single media asset at a time. The
player instance can be reused to play additional media assets using
its replaceCurrentItem(with:) method, but it manages the playback of
only a single media asset at a time
1). Put this code in you AppDelegate.m (didFinishLaunchingWithOptions) methods :
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
2). After that set Background Modes active for Audio, Airplay and Picture in Picture
Might be, its due to Interruption with current AVplayer running item.
Also, take care you implemented it(Below code)before loading any item to AVPlayer. AND enabled Capabilities to Play audio in background.
NSError *myErr;
[self becomeFirstResponder];
[[UIApplication sharedApplication]beginReceivingRemoteControlEvents];
AVAudioSession *aSession = [AVAudioSession sharedInstance];
[aSession setCategory:AVAudioSessionCategoryPlayback error:&myErr];
[aSession setMode:AVAudioSessionModeDefault error:&myErr];
[aSession setActive: YES error: &myErr];
Implement and Add Interruption handler, so you can re-play your stopped audio after another audio/interruption stopped. and below listener of it will call.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleAudioSessionInterruption:)
name:AVAudioSessionInterruptionNotification
object:aSession];
And manage AVplayer play/pause again in it:
- (void)handleAudioSessionInterruption:(NSNotification*)notification {
NSNumber *interruptionType = [[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey];
NSNumber *interruptionOption = [[notification userInfo] objectForKey:AVAudioSessionInterruptionOptionKey];
switch (interruptionType.unsignedIntegerValue) {
case AVAudioSessionInterruptionTypeBegan:{
// • Audio has stopped, already inactive
// • Change state of UI, etc., to reflect non-playing state
IsInteruptionOccured=YES;
} break;
case AVAudioSessionInterruptionTypeEnded:{
// • Make session active
// • Update user interface
// • AVAudioSessionInterruptionOptionShouldResume option
IsInteruptionOccured=NO;
[[AVAudioSession sharedInstance] setActive: YES error: nil];
if (interruptionOption.unsignedIntegerValue == AVAudioSessionInterruptionOptionShouldResume) {
// Here you should continue playback.
// Resume after exteranl interruption.
[_audioPlayer play];
BOOL isPlayingWithOthers = [[AVAudioSession sharedInstance] isOtherAudioPlaying];
// test it with...
NSLog(#"other audio is playing %d",isPlayingWithOthers);
}
} break;
default:
break;
}
}

Detecting inputs and outputs after app moves to background

I'm trying to detect when headphones are plugged into the iPhone. I do this buy the following approach.
//Init the AVAudioSession
-(void)viewDidLoad
{
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error];
NSError *activationError = nil;
[[AVAudioSession sharedInstance] setActive: YES error: &activationError];
}
//Get the current audio session route
-(void)viewWillAppear
{
AVAudioSessionRouteDescription *route = [[AVAudioSession sharedInstance] currentRoute];
}
This works fine and the route.inputs and route.outputs will contain the headphones and the microphone for a wired iPhone headset and will show the built in receiver and built in microphone when the headphones are unplugged. The problem I'm running into is when I press the home button on my app and it moves to the background. When I bring the app back into the foreground the route.inputs is always empty. My question is: Do I need to set the [[AVAudioSession sharedInstance] setActive:NO error: &activiationError] in my appDelegate when applicaionWillResign active is called? Because when route.inputs comes back empty, the headphones are still plugged in and should be detected. Any help would be appreciated. Thank you.
I think a better approach is this :
- (BOOL)isHeadsetPluggedIn
{
AVAudioSessionRouteDescription* route = [[AVAudioSession sharedInstance] currentRoute];
for (AVAudioSessionPortDescription* desc in [route outputs])
{
if ([[desc portType] isEqualToString:AVAudioSessionPortHeadphones])
return YES;
}
return NO;
}
I just tested this and this works even when coming back to foreground from background, and also on viewDiDLoad
Link to Original Answer

Starting AVQueuePlayer from background

Can't make AVQueuePlayer start playing sound queue when it's starting after the app went into the background.
The basic question is: how to start sound from newly created AVQueuePlayer instance from background?
It's for navi-like app that need to play couple of combined sounds with appropriate directions when the time comes. And most of the time the app works in background...
The details are below...
It plays just fine when I start it from active application, and finishes playing sound even after app went to background.
What I did so far:
In AppDelegate inside didFinishLaunchingWithOptions I added:
NSError *sessionError = nil;
[[AVAudioSession sharedInstance] setDelegate:self];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&sessionError];
// Change the default output audio route
UInt32 doChangeDefaultRoute = 1;
AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,
sizeof(doChangeDefaultRoute), &doChangeDefaultRoute);
After the app started I clicked the home button so the app went into the background.
When the time came this code executes (the app is still in background, but note, that I have enabled Audio and AirPlay background mode):
-(void)playTrainingFinishedSound
{
NSMutableArray *queue = [NSMutableArray array];
[queue addObject:[AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:#"alertkoniectreningu" withExtension:#"m4a"]]];
[self initializeAudioPlayerWithQueue:queue];
[self.appDelegate.audioPlayer play];
}
-(void)initializeAudioPlayerWithQueue:(NSArray *)queue
{
self.appDelegate.audioPlayer = [[AVQueuePlayer alloc] initWithItems:queue];
self.appDelegate.audioPlayer.actionAtItemEnd = AVPlayerActionAtItemEndAdvance;
}
Unfortunately this code doesn't make any sound, opposite to the situation when the app was in foreground.
Oh God, there was just one line missing in the AppDelegate didFinishLaunchingWithOptions [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
so it looks now like:
audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
if (audioSession) [audioSession setActive:YES error:nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
// Change the default output audio route
UInt32 doChangeDefaultRoute = 1;
AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,
sizeof(doChangeDefaultRoute), &doChangeDefaultRoute);
The reason the AVPlayer is failing is because you can't create/initialize an Audio Unit while an application is in the background, which is what the AVPlayer is attempting to do under the hood. The exception to this rule is of course audio-playing applications which can be started/resumed via the "Play" buttons built into the OS, while they are in the background. Thus, applications which subscribe to remote control events have the capability to start Audio Units in the background, which is why subscribing to these events appears to solve the problem.
It's unclear whether Apple is OK with using the API feature in this way.

background mode in ios by audio being killed by other apps

Recently,I try to make an app needs working in background and I use audio to protect the app from being killed by ios.Neither voip nor bluetooth,and not a Luckily,the demo works well until a new app execute which also run in background and also run by something audio.Then the demo was killed after 10 mins later,can anyone help me with the trouble?There must be other Thanks!!later i found an new app which do well in background mode.And here is the url :https://itunes.apple.com/us/app/pacer-pedometer-plus-weight/id600446812?mt=8 ,Sorry ,i'm not good at in English..
- (void)applicationDidEnterBackground:(UIApplication *)application{
if(counter==0){
[player play];
// Registers this class as the delegate of the audio session.
[[AVAudioSession sharedInstance] setDelegate: self];
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
UInt32 doSetProperty = 0;
//The C Style function call
AudioSessionSetProperty (
kAudioSessionProperty_OverrideCategoryMixWithOthers,
sizeof (doSetProperty),
&doSetProperty
);
// Activates the audio session.
NSError *activationError = nil;
[[AVAudioSession sharedInstance] setActive: YES error: &activationError];
[player setDelegate:self];
//play audio
[player play];
[self backgroundHandler];
}
}

Resources