web-dev-qa-db-fra.com

Comment détecter par programmation le commutateur de sourdine de l'iPhone?

Je n'arrive pas à trouver dans le SDK comment détecter par programmation le bouton/commutateur de sourdine sur l'iPhone. Lorsque mon application lit de la musique de fond, elle répond correctement au bouton de volume sans que j'aie de code pour suivre cela, mais lorsque j'utilise le bouton de sourdine, elle continue de jouer.

Comment tester la position de la sourdine?

(REMARQUE: mon programme a son propre commutateur de mise en sourdine, mais j'aimerais que le commutateur physique le remplace.)

45
Olie

Merci, JPM. En effet, le lien que vous fournissez mène à la bonne réponse (éventuellement.;) Pour être complet (car S.O. devrait être une source de réponses RAPIDES!) ...

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

J'ai répondu à une question similaire ici (lien) . Le code correspondant:

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

    }
11
Chris Ladd

Une partie du code dans d'autres réponses (y compris la réponse acceptée) peut ne pas fonctionner si vous n'êtes pas en mode ambiant, où le commutateur muet est respecté.

J'ai écrit la routine ci-dessous pour passer à l'ambiante, lire le commutateur, puis revenir aux paramètres dont j'ai besoin dans mon application.

-(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;
}
7
Jane Sales
-(BOOL)isDeviceMuted
{
 CFStringRef state;
 UInt32 propertySize = sizeof(CFStringRef);
 AudioSessionInitialize(NULL, NULL, NULL, NULL);
 AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
 return (CFStringGetLength(state) > 0 ? NO : YES);
}
5
Haemish Graham

Pour connaître l'état de l'interrupteur muet et le contrôle du volume, j'ai écrit ces deux fonctions. Ils sont idéaux si vous souhaitez avertir l'utilisateur avant d'essayer de créer une sortie 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;
}
5
Martin Cowie

J'ai suivi la théorie générale ici et je l'ai fait fonctionner http://inforceapps.wordpress.com/2009/07/08/detect-mute-switch-state-on-iphone/

Voici un récapitulatif: jouez un court son silencieux. Temps combien de temps il faut pour jouer. Si le commutateur de sourdine est activé, la lecture du son reviendra beaucoup plus courte que le son lui-même. J'ai utilisé un son de 500 ms et si le son était joué moins que cette fois, le commutateur de sourdine était activé. J'utilise les services audio pour jouer le son silencieux (qui honore toujours le commutateur muet). Cet article dit que vous pouvez utiliser AVAudioPlayer pour lire ce son. Si vous utilisez AVAudioPlayer, je suppose que vous devrez configurer la catégorie de votre AVAudioSession pour honorer le commutateur de sourdine, mais je ne l'ai pas essayé.

4
Mark24x7

Pour Swift

Le cadre ci-dessous fonctionne parfaitement dans l'appareil

https://github.com/akramhussein/Mute

Installez simplement en utilisant le pod ou téléchargez depuis Git

pod 'Mute'

et utiliser comme ci-dessous le code

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

}
3
Govind Prajapati

Olie,

Je pense que vous pouvez trouver la réponse à votre question ici:

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

Je suppose que vous avez accès aux forums des développeurs sur Apple.com :)

3
jpm

L'utilisation du mode Ambient pour lire une vidéo et du mode PlayAndRecord pour enregistrer une vidéo sur l'écran de la caméra, résout le problème dans notre cas.

Le code en application: didFinishLaunchingWithOptions:

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

Le code affiché apparaîtra sur cameraController, si vous devez utiliser la caméra ou l'enregistrement dans votre application

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

Le code en vue disparaîtra sur cameraController

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

En utilisant ces lignes, notre application enregistre et lit une vidéo et un interrupteur muet fonctionne parfaitement sous iOS8 et iOS7 !!!

3
slamor

Voici deux exemples d'utilisation de AudioSessionInitialize: http://www.restoroot.com/Blog/2008/12/25/audiosessioninitialize-workarounds/

1
catlan