I want to make app which continuously records voice in background. App like heard does exactly that.
But I am stuck on interruptions. The app fail to resume recording when it faces interruptions.
I have used this for notification :
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleAudioSessionInterruption:)
name:AVAudioSessionInterruptionNotification
object:nil];
and to resume recording I have:
- (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
NSLog(#"Audio has stopped, already inactive");
NSLog(#"is recording: %#",recorder.isRecording?#"yes":#"no");
[self.recorder pause];
NSLog(#"is recording after pause: %#",recorder.isRecording?#"yes":#"no");
//[recorder pause];
} break;
case AVAudioSessionInterruptionTypeEnded:{
// • Make session active
// • Update user interface
// • AVAudioSessionInterruptionOptionShouldResume option
if (interruptionOption.unsignedIntegerValue == AVAudioSessionInterruptionOptionShouldResume) {
// Here you should continue playback.
//NSLog(#"completed");
NSLog(#"start recording again %d");
//NSLog(#"completed: %d",[recorder record]);
// Set the audio file
[self.recorder record];
NSLog(#"is recording after again : %#",recorder.isRecording?#"yes":#"no");
//[player play];
}
} break;
default:
break;
}
}
Add in the plist the UIBackgroundModes an 'audio' as Item 0. Hope it will help - at least it works for me when playing audio.
Related
I have a video camera app and I would like it to allow users to capture content while on the phone.
I can do this by disconnecting the audio capture when the phone call is received and the session is interrupted, but because the session is no longer interrupted, I now have no way of knowing when the phone call ends and it is ok to reconnect the audio device.
If I use this callbacks for AVCaptureSessionWasInterruptedNotification and AVCaptureSessionInterruptionEndedNotification:
- (void)sessionWasInterrupted:(NSNotification *)notification {
NSLog(#"session was interrupted");
// disconnect the audio device when a call is started
AVCaptureDevice *device = [[self audioInput] device];
if ([device hasMediaType:AVMediaTypeAudio]) {
[[self session] removeInput:[self audioInput]];
[self setAudioInput:nil];
}
}
- (void)sessionInterruptionEnded:(NSNotification *)notification {
NSLog(#"session interuption ended");
// reconnect the audio device when the call ends
// PROBLEM: disconnecting the audio device triggers this callback before the phone call ends...
AVCaptureDevice *device = [[self audioInput] device];
if ([device hasMediaType:AVMediaTypeAudio]) {
if ([[self session] canAddInput:[self audioInput]])
[[self session] addInput:[self audioInput]];
}
}
I get an infinite loop of both of them being called one after another for the entire duration of the phone call and the camera is frozen. If I don't reconnect the device in the second function, the camera keeps working, but sessionInterruptionEnded is not called again when the phone call ends.
Is there a callback for when the phone call ends?
I'm working on an app that plays audio in the background while using other apps using an AVAudioPlayer. When the camera is opened the music is silenced but none of the methods in the AppDelegate for app lifecycle get called so I can't save the playlist position or the playback time for the song.
In addition when the camera is dismissed I would like to have the app resume playing background music but again I haven't found any callback method to allow my to observe this change.
Do you know how to observe that the camera did become active and that the camera was dismissed while the app is running in background mode?
Here's how i solved it.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleAudioSessionInterruption:)
name:AVAudioSessionInterruptionNotification
object:[AVAudioSession sharedInstance]];
Handle the interuption.
-(void)handleAudioSessionInterruption:(NSNotification*)notification
{
//NSLog(#"%#",notification);
NSNumber *interruptionType = [[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey]; //1 Interuption Start, 0 Interuption Ends
NSNumber *interruptionOption = [[notification userInfo] objectForKey:AVAudioSessionInterruptionOptionKey];
if ([interruptionType integerValue] == AVAudioSessionInterruptionTypeBegan)
{
NSLog(#"Player %d interupted",playerNumber);
// • Audio has stopped, already inactive
// • Change state of UI, etc., to reflect non-playing state
[self.playPauseButton setTitle:#">" forState:UIControlStateNormal];
self.playingAudio = NO;
return;
}
if ([interruptionType integerValue] == AVAudioSessionInterruptionTypeEnded)
{
if ([interruptionOption integerValue] == AVAudioSessionInterruptionOptionShouldResume)
{
NSLog(#"Player %d Resume",playerNumber);
[self.playPauseButton setTitle:#"||" forState:UIControlStateNormal];
self.playingAudio = YES;
NSError *error = nil;
AVAudioSession *aSession = [AVAudioSession sharedInstance];
[aSession setMode:AVAudioSessionModeDefault error:&error]; //& means value at address
[aSession setCategory:AVAudioSessionCategoryPlayback error:&error];
//[aSession setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error];
//[aSession setMode:AVAudioSessionModeSpokenAudio error:&error];
[aSession setActive: YES error: &error];
[self.audioPlayer play];
}
// • Make session active
// • Update user interface
// • AVAudioSessionInterruptionOptionShouldResume option
}
I want to play a song through speaker while being able to receive a video call using Quickblox.
My audio rates are getting messed up.
And also a bigger a problem is when the call ends quickblox framework sets audio session to deactivated state. i.e
[Avaudiosession sharedInstance]setActive:NO....
How do I stop this from happening?
Or is there a way the above mentioned scenario can be handled.??
I have read through google for a month now and still didn't find any suitable answers or any guidelines.
Can anyone help me with this problem/??
First, to allow AVAudioSession to work with other AVAudioSessions, you'll need to set up the option AVAudioSessionCategoryOptionMixWithOthers when initializing it:
NSError *sessionError = NULL;
BOOL success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback
withOptions:AVAudioSessionCategoryOptionMixWithOthers
error:&sessionError];
if(!success) {
NSLog(#"Error setting category Audio Session: %#", [sessionError localizedDescription]);
}
To handle interruptions (a call, alarm, etc..), you should set up an observer for interruptions to the NSNotificationCenter where you'll be able to handle the activation/deactivation of the AVAudioSession if necessary:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleAudioSessionInterruption:)
name:AVAudioSessionInterruptionNotification
object:[AVAudioSession sharedInstance]];
The NSNotification will carry the Type of Interruption and Key:
- (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
NSLog(#"AVAudioSessionInterruptionTypeBegan");
} break;
case AVAudioSessionInterruptionTypeEnded:{
// • Make session active
// • Update user interface
// • AVAudioSessionInterruptionOptionShouldResume option
NSLog(#"AVAudioSessionInterruptionTypeEnded");
if (interruptionOption.unsignedIntegerValue == AVAudioSessionInterruptionOptionShouldResume) {
// Here you should continue playback.
}
} break;
default:
break;
}
}
So I have a music app that uses an AVAudioSession to allow it to play when it is in the background. I use this call:
[audioSession setActive:YES
withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
error:nil];
My problem now is if I go to another app and it steals the audio session (thus now stopping music playback from my app and playing something else), and I come back to my app, no matter what I do to reset my audio session or my audio units, my app's sound is gone.
Does anyone know what to do?
So after registering for the AVAudioSession notifications:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleAudioSessionInterruption:)
name:AVAudioSessionInterruptionNotification
object:aSession];
You need to resume/restart you need to restart your player in the handler interruption type is AVAudioSessionInterruptionTypeEnded:
- (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
} break;
case AVAudioSessionInterruptionTypeEnded:{
// • Make session active
// • Update user interface
// • AVAudioSessionInterruptionOptionShouldResume option
if (interruptionOption.unsignedIntegerValue == AVAudioSessionInterruptionOptionShouldResume) {
// Here you should continue playback.
[player play];
}
} break;
default:
break;
}
}
You can see a complete explanation here: AVplayer resuming after incoming call
I am developing the chat application , If someone sends any message to me & my app is in background then i receive that message and i play the tone whenever message received,while tone is playing in mean while application is opened then music is getting stopped . How to make it continue when app comes to foreground also. (Tone must be complete as per duration available init). How to solve this issue. Waiting for the answer.
You have to work on remote control received events with notification..
- (void)remoteControlReceivedWithEvent:(UIEvent *)theEvent {
if (theEvent.type == UIEventTypeRemoteControl) {
switch(theEvent.subtype) {
case UIEventSubtypeRemoteControlPlay:
[[NSNotificationCenter defaultCenter] postNotificationName:#"TogglePlayPause" object:nil];
break;
case UIEventSubtypeRemoteControlPause:
[[NSNotificationCenter defaultCenter] postNotificationName:#"TogglePlayPause" object:nil];
break;
case UIEventSubtypeRemoteControlStop:
break;
case UIEventSubtypeRemoteControlTogglePlayPause:
[[NSNotificationCenter defaultCenter] postNotificationName:#"TogglePlayPause" object:nil];
break;
default:
return;
}
}
}
you can view complete answer here
You will have to use AVAudioSession. You can have the music temporarily pause or lower in volume while alert plays, then it'll resume full force!
First to initialize audio:
AVAudioSession* audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]
[audioSession setActive:NO error:nil];
Playing the sound (AVAudioPlayer's play/prepareToPlay will activate the audio session for you):
AVAudioPlayer* audioPlayer = [[[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:nil];
[audioPlayer play];
Stopping the alert sound:
[audioPlayer stop];
[[AVAudioSession sharedInstance] setActive:NO withFlags:AVAudioSessionSetActiveFlags_NotifyOthersOnDeactivation error:nil];
The flag kAudioSessionSetActiveFlag_NotifyOthersOnDeactivation tells the system to notify background audio to resume playing after the sound is played.