20

I want to know when my AVAudioRecorder is inaccessible (e.g when music starts playing).

As audioRecorderEndInterruption will be deprecated with iOS 9 I am focusing on AVAudioSession's interruption notification (but neither is working as expected).

The issue is that the interruption notification is never called if the app was and remains in the foreground when the interruption occurs.

E.g: The user starts and stops playing music without moving the application into the background.

To detect any interruptions I am using:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionWasInterrupted:) name:AVAudioSessionInterruptionNotification object:nil];
...
- (void)audioSessionWasInterrupted:(NSNotification *)notification {
    if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) {
        NSLog(@"Interruption notification");

        if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeBegan]]) {
            NSLog(@"InterruptionTypeBegan");
        } else {
            NSLog(@"InterruptionTypeEnded");
        }
    }
}

I get InterruptionTypeBegan as expected, but InterruptionTypeEnded isn't called if the app is still in the foreground (meaning it won't be called until the app is placed in the background and back into the foreground).

How may I receive InterruptionTypeEnded notification when the interruption occurs while the app is in the foreground?

Aleksander Azizi
  • 9,829
  • 9
  • 59
  • 87
  • This link may help you :- http://stackoverflow.com/questions/23586056/audio-interruption-when-ios-application-is-recording-in-background – Bharat Nakum Aug 12 '15 at 09:38
  • 5
    From the apple documentation: "There is no guarantee that a begin interruption will have an end interruption. Your app needs to be aware of switching to a foreground running state or the user pressing a play button. In either case, determine whether your app should reactivate its audio session." – Fennelouski Aug 12 '15 at 14:38

3 Answers3

9

This is a widespread problem affecting any app using AV framework components (the same goes for native iOS apps).

As explained in 's documentation on the subject of audio interruptions, the InterruptionTypeEnded should actually be applied in the scenario mentioned:

If the user dismisses the interruption ... the system invokes your callback method, indicating that the interruption has ended.

However, it also states that the InterruptionTypeEnded might not be called at all:

There is no guarantee that a begin interruption will have an end interruption.

Therefore, a different approach is needed in the scenario mentioned.


When it comes to handling music interruptions, the issue won't be around for long. iOS 9 effectively prevents outside audio sources to be used while the app's audio handler is invoked.

A way to handle the exact issue of media interruption could be to listen to MPMusicPlayerController's playbackState, as shown in this stackoverflow question: Detecting if music is playing?.


A more direct way to handle the issue of interruptions would be to either:

Block outside audio interruptions completely by re-invoking your audio component at the time of InterruptionTypeBegan.

Or by giving a UI indication that an outside media source has interrupted the audio session (for example showing an inactive microphone).


Hopefully  will come up with a better solution to the problem, but in the meantime this should give you some options to solve the interruption issue.

Community
  • 1
  • 1
Aleksander Azizi
  • 9,829
  • 9
  • 59
  • 87
  • Thank @Aleksander Azizi! Btw could you explain more about 'Block outside audio interruptions completely by re-invoking your audio component at the time of InterruptionTypeBegan.' ? – nahung89 Jul 09 '16 at 01:21
  • @nahung89 Once `InterruptionTypeBegan` is called you can initialize the audio engine again. Affectively blocking any other audio source. – Aleksander Azizi Jul 09 '16 at 10:40
  • I see. Actually I tried it before but didn't work. Phone call / alarm / reminder... always have higher priority in audio session. Right after we setup the audio player again, it will be stopped immediately. – nahung89 Jul 10 '16 at 04:43
  • I found that .play() CANNOT be called within the interruption handler as that prevents audioPlayerEndInterruption to be called. The .play() must called ONLY within audioPlayerEndInterruption() to make resume to work. Please check out my conversation here for details http://stackoverflow.com/a/38800403/1827488. – rockhammer Aug 08 '16 at 13:45
  • 1
    another work around is to listen to the route change notification. If you have an unmatched BeginInterruption and the Route Changes, you can attempt to restart. – yano Jun 11 '18 at 22:58
-1

If you haven't already, try setting your AVCaptureSession's property usesApplicationAudioSession to NO.

This question & answer may act as a good reference if you're looking for any more detail.

Community
  • 1
  • 1
ChrisHaze
  • 2,800
  • 16
  • 20
  • 1
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. – LeftyX Aug 14 '15 at 08:53
  • Thanks for your feedback @LeftyX I hadn't considered your concerns and will take that into account from now on in my answers. I am somewhat confused as to why my response was down voted though, being that it did include a working solution. – ChrisHaze Aug 14 '15 at 16:32
  • I didn't down-vote. I hardly down-vote answers. It's always better to give a full explanation in your answer. – LeftyX Aug 14 '15 at 16:46
  • @LeftyX I didn't mean to imply that you had. Thanks again and I will be sure to include detailed explanations in my responses from now on. – ChrisHaze Aug 14 '15 at 16:56
-1

I try this and find InterruptionTypeEnded may called after music pause in some app, but other not called when pause.

My solution is update the UI to let user know record has stopped and do some related work such as file operation. When interruption ends, active AVAudioSession, if doesn't have error, start a new record.

If you want to join the file before and after interrupt, the answer to this question: AVAudioRecorder records only the audio after interruption may be helpful to you.

Community
  • 1
  • 1
NSDeveloper
  • 1,630
  • 15
  • 25