Detecte el cambio de position del anillo / cambio silencioso

Estoy trabajando en una aplicación para la cual quisiera:

  1. Respete el anillo / interruptor silencioso cuando reproduzca audio, y

  2. muestra un ícono que indica que el sonido está silenciado cuando el conmutador de timbre / silencio está configurado en silencio.

El Requisito 1 es fácil: AVAudioSessionSoloAmbient como la categoría de session de audio de mi aplicación, de modo que mi session de audio se silenciará cuando el conmutador ring / silent esté apagado.

El requisito 2 parece considerablemente más difícil, porque necesito algún tipo de callback, notificación o KVO que me permita controlar la position del conmutador, pero Apple ha dejado en claro que no está dispuesto a ofrecer una forma oficialmente expuesta de hacerlo. Dicho esto, si puedo encontrar una manera no intrusiva de controlar la position del interruptor, incluso uno técnicamente prohibido (como, por ejemplo, una NSNotification interna), estaría dispuesto a ejecutarlo por Apple.

Además, preferiría no implementar algunas de las soluciones de sondeo que he encontrado en otros lugares. Consulte la sección de preguntas relacionadas para ver un ejemplo.


Lo que he aprendido (también conocido como lo que no funciona)

  • En las versiones de iOS 4 y 5, al less, había un truco que se podía utilizar para get la position del conmutador observando la propiedad de la ruta de la session de audio actual . Además de estar en desuso por la class AVAudioSession , puedo confirmar que este truco ya no es una opción. La ruta actual, tanto como lo informan las funciones C que comprenden la API de Audio Session desuso y la class AVAudioSession actual, no cambia cuando se AVAudioSession el conmutador de timbre / silencio.

  • AVSystemController es una class interna que parece ser muy prometedora. Invocando - (BOOL)toggleActiveCategoryMuted en shanetworkingAVSystemController hecho silencia el audio de mi aplicación. Además, el singleton compartido publica una notificación AVSystemController_SystemVolumeDidChangeNotification cuando se cambia el volumen del sistema a través de los botones de volumen. Lamentablemente, esta notificación no se publica en respuesta a cambios en el conmutador ring / silent (aunque esta fuente dudosa atribuye que debería ).

  • Hasta donde puedo decir, no hay ninguna NSNotification publicada por ningún object en respuesta a los cambios de position del conmutador ring / silent. Llegué a esta conclusión después de agregarme como observador a todas las notifications en el centro pnetworkingeterminado:

     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:nil object:nil]; 

    y luego alternar el anillo / interruptor silencioso. Nada.

  • La class AVSystemController tiene un método prometedor con la firma:

     - (BOOL)getActiveCategoryMuted:(BOOL*)arg1; 

    Sin embargo, hay dos problemas con esto:

    1. Ni el valor de retorno ni el BOOL apuntado por arg1 parecen cambiar en respuesta a la conmutación del conmutador ring / silent.
    2. Debido a la firma del método, este método no es (en lo que yo entiendo) un candidato para KVO.

  • Sospecho que algún object envía algún otro object (s) a GSEventRef cuando se cambia el conmutador de silencio, porque veo lo siguiente en la statement para los types de evento:

     kGSEventRingerOff = 1012, kGSEventRingerOn = 1013, 

    Sin embargo, estoy bastante seguro de que no puedo interceptar esos posts, e incluso si pudiera, eso sería un poco más que "un poco" intrusivo.


Por qué creo que esto es posible

En pocas palabras: la aplicación de Instagram muestra esencialmente este comportamiento. Cuando mira un video, respeta la configuration del interruptor de timbre / silencio, pero muestra un icono cuando el interruptor está apagado. El ícono desaparece y vuelve a aparecer tan inmediatamente después de mover el interruptor que supongo que debe estar basado en events, no sondeos.


preguntas relacionadas

  • Esta pregunta se remonta a iOS 4 y usa los methods que mencioné en mi primera viñeta anterior.

  • Esta pregunta es muy similar a la anterior.

  • Esta pregunta es (mucho) más actual, preguntando sobre iOS 7. Sin embargo, como estoy dispuesto a aceptar una ruptura mínimamente intrusiva de las reglas de la API privada, afirmaría que esta es una pregunta diferente de la mía.

  • Esta respuesta sugiere utilizar un método de sondeo que preferiría evitar.