Search code examples
iosiphoneobjective-cvideoavaudiosession

AVAudioSessionInterruptionNotification not fired when Video/Camera is used


I have some SIP application. Until I've used audio only evrything was working correctly, I was receiving AVAudioSessionInterruptionNotification when it was necessary.

Problem appeared when video was used (receiving and sending camera feed). Once I use session with video, notification is never fired again, even if later audio is used only.

How can I fix that? I've found similar topic, but answer is to prompt and I don't fully get it. Also I do not have "camera/capture device" and "AVCaptureSession" since audio and video streaming is provided by closed third party library, but my code have to handle interruptions.

Do I have to change some property to have this notification always fired (linked topic suggest that), or should I use alternative notification.
I was digging in documentation but I've failed to find anything useful for me.

I've tried use dummy object of AVCaptureSession, but this didn't solve the problem.


Edit: Third party library had some additional crashed what exposed that they use AVCAptureSession. I've have contact them ask to change property usesApplicationAudioSession as described in other question and "beg" them to fix it. After longer fight they agreed :).


Solution

  • I used category and method swizzling and it works like charm.

    #import "AVCaptureSession+MethodSwizzling.h"
    #import <objc/runtime.h>
    
    
    static void MethodSwizzle(Class c, SEL origSEL, SEL overrideSEL) {
      Method origMethod = class_getInstanceMethod(c, origSEL);
      Method overrideMethod = class_getInstanceMethod(c, overrideSEL);
      if(class_addMethod(c, origSEL, method_getImplementation(overrideMethod), method_getTypeEncoding(overrideMethod))) {
        class_replaceMethod(c, overrideSEL, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
      } else {
        method_exchangeImplementations(origMethod, overrideMethod);
      }
    }
    
    @implementation AVCaptureSession (MethodSwizzling)
    
    - (id)initMethodSwizzling {
      self = [self initMethodSwizzling]; // it is not recursion it is method swizzling
      self.usesApplicationAudioSession = NO;
      return self;
    }
    
    + (void)load {
      if (class_getInstanceMethod(self, @selector(setUsesApplicationAudioSession:))) {
        // Swizzle methods only when it is possible to change usesApplicationAudioSession property.
        MethodSwizzle(self, @selector(init), @selector(initMethodSwizzling));
      }
    }
    
    @end