vibracion - ¿Cómo detectar mediante programación el interruptor de silenciamiento del iPhone?
se descompuso el boton de silencio de mi iphone (10)
Para Swift
El marco debajo funciona perfectamente en el dispositivo
https://github.com/akramhussein/Mute
Simplemente instale usando pod o descargue desde Git
pod ''Mute''
y usar como código debajo
import UIKit
import Mute
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel! {
didSet {
self.label.text = ""
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Notify every 2 seconds
Mute.shared.checkInterval = 2.0
// Always notify on interval
Mute.shared.alwaysNotify = true
// Update label when notification received
Mute.shared.notify = { m in
self.label.text = m ? "Muted" : "Not Muted"
}
// Stop after 5 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
Mute.shared.isPaused = true
}
// Re-start after 10 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 10.0) {
Mute.shared.isPaused = false
}
}
}
Parece que no puedo encontrar en el SDK cómo detectar programáticamente el botón de silencio / interruptor en el iPhone. Cuando mi aplicación reproduce música de fondo, responde correctamente al botón de volumen sin que yo tenga ningún código para seguir eso, pero cuando uso el interruptor de silencio, simplemente sigue jugando.
¿Cómo pruebo la posición de mute?
(NOTA: Mi programa tiene su propio interruptor de silencio, pero me gustaría que el interruptor físico lo anule).
¡Gracias!
Aquí hay dos ejemplos de cómo utilizar AudioSessionInitialize: http://www.restoroot.com/Blog/2008/12/25/audiosessioninitialize-workarounds/
El uso del modo Ambiente para reproducir un video y el modo PlayAndRecord para grabar un video en la pantalla de la cámara resuelven el problema en nuestro caso.
El código en la aplicación: didFinishLaunchingWithOptions:
NSError *error = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&error];
[[AVAudioSession sharedInstance] setMode:AVAudioSessionModeVideoRecording error:&error];
[[AVAudioSession sharedInstance] setActive:YES error:&error];
El código en vista aparecerá en CameraController, si tiene que usar la cámara o grabar en su aplicación
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
El código a la vista desaparecerá en la cámara Controlador
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
Usando estas líneas, nuestra aplicación registra y reproduce un interruptor de video y mute que funciona perfectamente tanto en iOS8 como en iOS7.
Gracias, JPM. De hecho, el enlace que proporciona conduce a la respuesta correcta (eventualmente;) Para completar (¡porque SO debería ser una fuente de respuestas RÁPIDAS!) ...
// "Ambient" makes it respect the mute switch
// Must call this once to init session
if (!gAudioSessionInited)
{
AudioSessionInterruptionListener inInterruptionListener = NULL;
OSStatus error;
if ((error = AudioSessionInitialize (NULL, NULL, inInterruptionListener, NULL)))
{
NSLog(@"*** Error *** error in AudioSessionInitialize: %d.", error);
}
else
{
gAudioSessionInited = YES;
}
}
SInt32 ambient = kAudioSessionCategory_AmbientSound;
if (AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof (ambient), &ambient))
{
NSLog(@"*** Error *** could not set Session property to ambient.");
}
Olie,
Creo que puedes encontrar la respuesta a tu pregunta aquí:
https://devforums.apple.com/message/1135#1135
Asumo que tienes acceso a los foros de desarrolladores en Apple.com :)
Para averiguar el estado del interruptor de silencio y el control de volumen, escribí estas dos funciones. Estos son ideales si desea advertir al usuario antes de que intenten crear una salida de audio.
-(NSString*)audioRoute
{
CFStringRef state;
UInt32 propertySize = sizeof(CFStringRef);
OSStatus n = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
if( n )
{
// TODO: Throw an exception
NSLog( @"AudioSessionGetProperty: %@", osString( n ) );
}
NSString *result = (NSString*)state;
[result autorelease];
return result;
}
-(Float32)audioVolume
{
Float32 state;
UInt32 propertySize = sizeof(CFStringRef);
OSStatus n = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputVolume, &propertySize, &state);
if( n )
{
// TODO: Throw an exception
NSLog( @"AudioSessionGetProperty: %@", osString( n ) );
}
return state;
}
Parte del código en otras respuestas (incluida la respuesta aceptada) puede no funcionar si no está en el modo ambiente, donde se respeta el interruptor de silencio.
Escribí la siguiente rutina para cambiar a ambiente, leer el interruptor y luego volver a la configuración que necesito en mi aplicación.
-(BOOL)muteSwitchEnabled {
#if TARGET_IPHONE_SIMULATOR
// set to NO in simulator. Code causes crashes for some reason.
return NO;
#endif
// go back to Ambient to detect the switch
AVAudioSession* sharedSession = [AVAudioSession sharedInstance];
[sharedSession setCategory:AVAudioSessionCategoryAmbient error:nil];
CFStringRef state;
UInt32 propertySize = sizeof(CFStringRef);
AudioSessionInitialize(NULL, NULL, NULL, NULL);
AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
BOOL muteSwitch = (CFStringGetLength(state) <= 0);
NSLog(@"Mute switch: %d",muteSwitch);
// code below here is just restoring my own audio state, YMMV
_hasMicrophone = [sharedSession inputIsAvailable];
NSError* setCategoryError = nil;
if (_hasMicrophone) {
[sharedSession setCategory: AVAudioSessionCategoryPlayAndRecord error: &setCategoryError];
// By default PlayAndRecord plays out over the internal speaker. We want the external speakers, thanks.
UInt32 ASRoute = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,
sizeof (ASRoute),
&ASRoute
);
}
else
// Devices with no mike don''t support PlayAndRecord - we don''t get playback, so use just playback as we don''t have a microphone anyway
[sharedSession setCategory: AVAudioSessionCategoryPlayback error: &setCategoryError];
if (setCategoryError)
NSLog(@"Error setting audio category! %@", setCategoryError);
return muteSwitch;
}
Respondí una pregunta similar aquí (enlace) . El código relevante:
-(BOOL)silenced {
#if TARGET_IPHONE_SIMULATOR
// return NO in simulator. Code causes crashes for some reason.
return NO;
#endif
CFStringRef state;
UInt32 propertySize = sizeof(CFStringRef);
AudioSessionInitialize(NULL, NULL, NULL, NULL);
AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
if(CFStringGetLength(state) > 0)
return NO;
else
return YES;
}
Seguí la teoría general aquí y conseguí que esto funcionara http://inforceapps.wordpress.com/2009/07/08/detect-mute-switch-state-on-iphone/
Aquí hay un resumen: reproduce un sonido corto y silencioso. Tiempo cuánto tiempo lleva jugar. Si el interruptor de silencio está activado, la reproducción del sonido será mucho más breve que el sonido en sí. Usé un sonido de 500 ms y si el sonido se reprodujo en menos de este tiempo, entonces el interruptor de silencio estaba activado. Uso Audio Services para reproducir el sonido silencioso (que siempre respeta el interruptor de silencio). Este artículo dice que puedes usar AVAudioPlayer para reproducir este sonido. Si utilizas AVAudioPlayer, supongo que necesitarás configurar la categoría de tu AVAudioSession para cumplir con el cambio de silenciamiento, pero no lo he intentado ".
-(BOOL)isDeviceMuted
{
CFStringRef state;
UInt32 propertySize = sizeof(CFStringRef);
AudioSessionInitialize(NULL, NULL, NULL, NULL);
AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
return (CFStringGetLength(state) > 0 ? NO : YES);
}