Come rilevare a livello di codice l’interruttore di distriggerszione dell’iPhone?

Non riesco a trovare nell’SDK come percepire in modo programmatico il pulsante / interruttore muto sull’iPhone. Quando la mia app riproduce musica di sottofondo, risponde correttamente al pulsante del volume senza che io abbia alcun codice per seguirla ma, quando uso l’interruttore di silenziamento, continua a giocare.

Come posso testare la posizione di muto?

(NOTA: il mio programma ha il suo interruttore di silenziamento, ma mi piacerebbe che il passaggio fisico lo sovrascriva.)

Grazie!

Grazie, JPM. In effetti, il link che fornisci conduce alla risposta corretta (eventualmente.) Per completezza (perché SO dovrebbe essere una fonte di risposte RAPIDE!) …

// "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."); } 

Ho risposto a una domanda simile qui (link) . Il codice pertinente:

  -(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; } 

Parte del codice in altre risposte (inclusa la risposta accettata) potrebbe non funzionare se non ci si trova in modalità ambiente, dove l’interruttore di silenziamento viene rispettato.

Ho scritto la routine qui sotto per passare all’ambiente, leggere l’interruttore e quindi tornare alle impostazioni che ho bisogno nella mia app.

 -(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; } 

Olie,

Credo che tu possa trovare la risposta alla tua domanda qui:

https://devforums.apple.com/message/1135#1135

Suppongo che tu abbia accesso ai forum degli sviluppatori su Apple.com 🙂

Per scoprire lo stato dell’interruttore mute e il controllo del volume ho scritto queste due funzioni. Sono ideali se si desidera avvisare l’utente prima di provare a creare l’uscita 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; } 
 -(BOOL)isDeviceMuted { CFStringRef state; UInt32 propertySize = sizeof(CFStringRef); AudioSessionInitialize(NULL, NULL, NULL, NULL); AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state); return (CFStringGetLength(state) > 0 ? NO : YES); } 

Ho seguito la teoria generale qui e ho fatto in modo che funzionasse http://inforceapps.wordpress.com/2009/07/08/detect-mute-switch-state-on-iphone/

Ecco un riassunto: riproduce un breve suono silenzioso. Tempo quanto tempo ci vuole per giocare. Se l’interruttore di silenziamento è attivo, la riproduzione del suono tornerà molto più breve del suono stesso. Ho usato un suono da 500ms e se il suono è stato riprodotto in meno di questo momento, l’interruttore di silenziamento era attivo. Uso i servizi audio per riprodurre il suono silenzioso (che onora sempre l’interruttore di silenziamento). Questo articolo dice che puoi usare AVAudioPlayer per riprodurre questo suono. Se si utilizza AVAudioPlayer, presumo che sarà necessario configurare la categoria di AVAudioSession per onorare l’interruttore di silenziamento, ma non l’ho provato.

L’uso della modalità Ambient per la riproduzione di un video e la modalità PlayAndRecord per la registrazione di un video sullo schermo della fotocamera risolve il problema nel nostro caso.

Il codice nell’applicazione: didFinishLaunchingWithOptions:

 NSError *error = nil; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&error]; [[AVAudioSession sharedInstance] setMode:AVAudioSessionModeVideoRecording error:&error]; [[AVAudioSession sharedInstance] setActive:YES error:&error]; 

Il codice in viewWillAppear su cameraController, se devi utilizzare la fotocamera o la registrazione nella tua app

 [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]; 

Il codice in viewWillDisplay su cameraController

 [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil]; 

Usando queste linee la nostra applicazione registra e riproduce uno switch video e mute funziona perfettamente sia con iOS8 che con iOS7 !!!

Ecco due esempi su come utilizzare AudioSessionInitialize: http://www.restoroot.com/Blog/2008/12/25/audiosessioninitialize-workarounds/

Per Swift

Sotto il quadro funziona perfettamente nel dispositivo

https://github.com/akramhussein/Mute

Basta installare usando pod o scaricare da Git

 pod 'Mute' 

e usare come sotto il codice

 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 } } }