Detección de AVAudioSessions activas en dispositivo iOS

Estoy tratando de averiguar si esto es posible: mi aplicación activa una session de audio que se inicializa como:

[[[AVAudioSession alloc] init] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error]; 

Me gustaría poder comprender cuándo se está reproduciendo una session de audio adicional que se originó en otra aplicación o el sistema operativo.

Sé acerca de la capacidad de implementar los methods de delegado beginInterruption: y endInterruption pero estos no se invocarán debido a la opción AVAudioSessionCategoryOptionMixWithOthers que estoy usando.

¿Hay alguna forma de lograr esto sin usar API privada?

Gracias por adelantado.

La forma en que administra la session de audio de su aplicación ha tenido algunos cambios significativos desde iOS 6.0 , y merece una breve mención primero. Antes de iOS 6.0 , utilizarías las classs AVAudioSession y AudioSessionServices , incorporando la delegación y la propiedad de escuchar, respectivamente. Desde iOS 6.0 en adelante, use la class AVAudioSession e incorpore notifications.

Lo siguiente es para iOS 6.0 en adelante.

Para saber si se está reproduciendo otro audio fuera de las aplicaciones que sandbox usa,

 // query if other audio is playing BOOL isPlayingWithOthers = [[AVAudioSession shanetworkingInstance] isOtherAudioPlaying]; // test it with... (isPlayingWithOthers) ? NSLog(@"other audio is playing") : NSLog(@"no other audio is playing"); 

En cuanto al event handling la interrupción, deberá observar AVAudioSessionInterruptionNotification y AVAudioSessionRouteChangeNotification . Entonces, en la class que administra su session de audio, puede poner algo como lo siguiente: esto debería llamarse una vez al comienzo del ciclo de vida de la aplicación y no olvide quitar el observador en el método dealloc de la misma class.

 // ensure we already have a singleton object [AVAudioSession shanetworkingInstance]; // register for notifications [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(interruption:) name:AVAudioSessionInterruptionNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(routeChange:) name:AVAudioSessionRouteChangeNotification object:nil]; 

Y, finalmente, agregue la siguiente interruption: selectores interruption: y routeChange: estos recibirán un object NSNotification que tiene una propiedad llamada userInfo del tipo NSDictionary que lee para ayudar a cualquier condicional que tenga su aplicación.

 - (void)interruption:(NSNotification*)notification { // get the user info dictionary NSDictionary *interuptionDict = notification.userInfo; // get the AVAudioSessionInterruptionTypeKey enum from the dictionary NSInteger interuptionType = [[interuptionDict valueForKey:AVAudioSessionInterruptionTypeKey] integerValue]; // decide what to do based on interruption type here... switch (interuptionType) { case AVAudioSessionInterruptionTypeBegan: NSLog(@"Audio Session Interruption case started."); // fork to handling method here... // EG:[self handleInterruptionStarted]; break; case AVAudioSessionInterruptionTypeEnded: NSLog(@"Audio Session Interruption case ended."); // fork to handling method here... // EG:[self handleInterruptionEnded]; break; default: NSLog(@"Audio Session Interruption Notification case default."); break; } } 

Y de manera similar …

 - (void)routeChange:(NSNotification*)notification { NSDictionary *interuptionDict = notification.userInfo; NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue]; switch (routeChangeReason) { case AVAudioSessionRouteChangeReasonUnknown: NSLog(@"routeChangeReason : AVAudioSessionRouteChangeReasonUnknown"); break; case AVAudioSessionRouteChangeReasonNewDeviceAvailable: // a headset was added or removed NSLog(@"routeChangeReason : AVAudioSessionRouteChangeReasonNewDeviceAvailable"); break; case AVAudioSessionRouteChangeReasonOldDeviceUnavailable: // a headset was added or removed NSLog(@"routeChangeReason : AVAudioSessionRouteChangeReasonOldDeviceUnavailable"); break; case AVAudioSessionRouteChangeReasonCategoryChange: // called at start - also when other audio wants to play NSLog(@"routeChangeReason : AVAudioSessionRouteChangeReasonCategoryChange");//AVAudioSessionRouteChangeReasonCategoryChange break; case AVAudioSessionRouteChangeReasonOverride: NSLog(@"routeChangeReason : AVAudioSessionRouteChangeReasonOverride"); break; case AVAudioSessionRouteChangeReasonWakeFromSleep: NSLog(@"routeChangeReason : AVAudioSessionRouteChangeReasonWakeFromSleep"); break; case AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory: NSLog(@"routeChangeReason : AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory"); break; default: break; } } 

No hay necesidad de sondear nada, siempre y cuando compruebe el estado de la session de audio de sus aplicaciones, por ejemplo, en la viewDidLoad de su controller de vista raíz, al comienzo de su ciclo de vida de aplicaciones. Cualquier cambio desde allí en adelante a la session de audio de sus aplicaciones se conocerá a través de estas dos notifications principales. Reemplace las sentencias de NSLog con lo que su código necesite hacer según los casos contenidos en el conmutador.

Puede encontrar más información sobre AVAudioSessionInterruptionTypeKey y AVAudioSessionRouteChangeReasonKey en la documentation de reference de la class AVAudioSession .

Mis disculpas por la larga respuesta, pero creo que la administración de Audio Session en iOS es bastante complicada y la Guía de progtwigción de la session de audio de Apple, al momento de escribir esto, no incluye ejemplos de códigos que utilizan notifications para el event handling interrupciones.

Puede comprobar si se está reproduciendo otro audio como este:

 UInt32 otherAudioIsPlaying; UInt32 propertySize = sizeof (otherAudioIsPlaying); AudioSessionGetProperty (kAudioSessionProperty_OtherAudioIsPlaying, &propertySize, &otherAudioIsPlaying ); [self handleIfAudioIsPlaying: otherAudioIsPlaying]; 

Luego puede agregar un ciclo y verificar cada X segundo si algo cambió.