Como detectar programaticamente o mudo iPhone?
-
08-07-2019 - |
Pergunta
Eu não consigo encontrar no SDK como sentir programaticamente o botão / interruptor de silêncio sobre o iPhone. Quando meu aplicativo reproduz música de fundo, ele responde corretamente para o botão de volume sem me ter qualquer código a seguir isso, mas, quando eu uso o interruptor mudo, ele simplesmente continua jogando fora.
Como faço para testar a posição do mudo?
(NOTA:. Meu programa tem seu próprio interruptor de silêncio, mas eu gostaria o interruptor físico para substituir essa)
Solução
Obrigado, JPM. Na verdade, o link que você fornecer pistas para a resposta correta (finalmente;). Para completar (porque S. O. deve ser uma fonte de respostas 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.");
}
Outras dicas
Eu respondi uma pergunta semelhante aqui (link) . O 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;
}
Parte do código em outras respostas (incluindo a resposta aceita) pode não funcionar se você não está no modo de ambiente, onde o mudo é respeitado.
Eu escrevi a rotina abaixo para mudar para o ambiente, leia o interruptor, e depois voltar para as definições que preciso em meu aplicativo.
-(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;
}
Para saber o estado do interruptor mute e o controle de volume Escrevi estas duas funções. Estes são ideais se você quiser avisar o usuário antes de tentar criar uma saída de áudio.
-(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);
}
Olie,
Eu acredito que você pode encontrar a resposta para sua pergunta aqui:
https://devforums.apple.com/message/1135#1135
Eu estou supondo que você tenha acesso aos Developer Forum em Apple.com:)
Eu segui a teoria geral aqui e tenho essa para o trabalho http://inforceapps.wordpress.com / 2009/07/08 / detectar-mudo-switch-state-on-iphone /
Aqui está um resumo: Tocar um som silencioso curto. Tempo quanto tempo leva para jogar. Se o mudo está ligado, a reprodução do som vai voltar muito mais curto do que o próprio som. Eu usei um 500ms som e se o som reproduzido em menos de desta vez, em seguida, o mudo começou. Eu uso Serviços de áudio para reproduzir o som silencioso (que sempre honra o interruptor mute). Este artigo diz que você pode usar AVAudioPlayer para jogar este som. Se você usar AVAudioPlayer, eu suponho que você precisa configurar sua categoria de AVAudioSession para honrar o interruptor de silêncio, mas eu não tentei it`.
Usando Ambient modo para reproduzir um vídeo e PlayAndRecord modo para gravar um vídeo na tela da câmera, resolve o problema no nosso caso.
O código na aplicação: didFinishLaunchingWithOptions:
NSError *error = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&error];
[[AVAudioSession sharedInstance] setMode:AVAudioSessionModeVideoRecording error:&error];
[[AVAudioSession sharedInstance] setActive:YES error:&error];
O código na viewWillAppear em cameraController, se você tem que usar a câmera ou gravação em seu aplicativo
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
O código na viewWillDisappear em cameraController
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
Usando essas linhas de nossos registros de aplicação e desempenha um vídeo e mudo funciona perfeitamente sob ambos iOS8 e iOS7 !!!
Para Swift
Abaixo quadro funciona perfeitamente no dispositivo
https://github.com/akramhussein/Mute
Basta instalar usando pod ou transferência a partir Git
pod 'Mute'
e utilização como código abaixo
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
}
}
}
Aqui dois exemplos como usar AudioSessionInitialize: http://www.restoroot.com/Blog/2008/12 / 25 / audiosessioninitialize-soluções alternativas /