Détection du commutateur Ring / Silent / Mute de l'iPhone en utilisant AVAudioPlayer ne fonctionne pas?

j'ai essayé d'utiliser ces méthodes pour essayer de détecter si L'interrupteur est actif ou non:

comment programmer le commutateur pour iPhone mute?

AVAudioSession catégorie ne fonctionne pas que de la documentation dicte

mais sur mon iPhone 4, la valeur" state "est toujours" Speaker " (et la valeur de longueur retournée par CFStringGetLength(state) est toujours 7). Quelqu'un a utilisé cette méthode avec succès? Si oui, sur quel type d'appareil et version SDK?

Je l'appelle comme ça:


- (BOOL)deviceIsSilenced {
    CFStringRef state;
    UInt32 propertySize = sizeof(CFStringRef);
    OSStatus audioStatus = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
    if (audioStatus == kAudioSessionNoError) {
        NSLog(@"audio route: %@", state) // "Speaker" regardless of silent switch setting, but "Headphone" when my headphones are plugged in
        return (CFStringGetLength(state) <= 0);
    }
    return NO;
}

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    audioSession.delegate = self;
    [audioSession setCategory:AVAudioSessionCategoryAmbient error:nil];
    [audioSession setActive:YES error:nil];
    NSLog(@"muted? %i", [self deviceIsSilenced]);
    ...
}

je pensais que peut-être un autre événement (plus précis) kAudioSessionProperty est déclenché lorsque l'interrupteur physique sur le téléphone est ... basculer. N'importe qui ont des idées?

soit dit en passant, j'utilise la catégorie AVAudioSessionCategoryAmbient avec ma [AVAudioSession partagée en instance].

mise à jour: j'ai également essayé d'utiliser différentes catégories audio, et une poignée d'autres propriétés de session audio, aucun ne semble s'allumer lors de la mutation/désactivation de l'interrupteur. : (

Jan. 1, 2014 Mise à jour: c'est un peu d'un piratage, et j'ai rencontré un accident alors multitâche w/ it sur mon iPhone 5S, mais le SoundSwitch bibliothèque liée dans la nouvelle réponse acceptée est la voie à suivre si vous voulez détecter la interrupteur silencieux. Il fonctionne même dans iOS 7.

31
demandé sur Community 2011-08-01 20:18:18

7 réponses

j'ai parcouru cette bibliothèque VSSilentSwitch.

Ne fonctionne pas pour moi (ne fonctionne pas lorsque vous commencez à utiliser réellement l'audio).

Je pensais à comment il l'a fait, et j'ai réalisé que l'appel d'achèvement audio est appelé presque dès que le son commence à jouer quand nous sommes silencieux.

Pour être un peu plus précis:

Les sons du système étant joués en utilisant AudioServicesPlaySystemSound compléteront la lecture dès comme il a commencé.

Bien sûr, cela ne fonctionnera que sur les catégories audio qui respectent l'interrupteur silencieux (la valeur par défaut AVAudioSessionCategoryAmbient la respecte).

Le truc est donc de créer un son système, de préférence un son silencieux, et de continuer à le jouer encore et encore, tout en vérifiant le temps qu'il a fallu entre la lecture et l'achèvement (installer une procédure d'achèvement en utilisant AudioServicesAddSystemSoundCompletion ).

Si le proc d'achèvement est appelé très bientôt (permettre certains seuil) - cela signifie que l'interrupteur silencieux est allumé.

Cette astuce comporte de nombreuses mises en garde, la plus importante étant le fait qu'elle ne fonctionnera pas sur toutes les catégories audio.

Si votre application audio en arrière - plan- assurez-vous d'arrêter ce test alors que dans l'arrière-plan ou votre application s'exécute indéfiniment dans le fond (et sera rejetée par apple, trop).

3
répondu Moshe Gottlieb 2017-08-12 08:12:08

Eh bien j'ai trouvé la réponse grâce à quelqu'un des forums de développeurs, et vous les gars ne vont pas aimer!

J'ai eu une réponse D'Apple à ce sujet.

ils ont dit qu'ils n'ont pas et n'ont jamais fourni de méthode pour détecter le commutateur muet matériel et n'ont pas l'intention de le faire.

: (

IMO il est certainement utile de détecter l'interrupteur silencieux et la notification l'utilisateur au cas où ils ont oublié qu'il était allumé... J'ai eu des gens qui se plaignent qu'ils n'ont pas de son et l'interrupteur silencieux était la raison! Oh bien.

PS: si vous souhaitez Qu'Apple ajoute cette fonctionnalité (et bien sûr que vous le faites!) veuillez déposer un nouveau rapport de bug "Enhancement" pour "iPhone SDK" à http://bugreport.apple.com /

mise à Jour: Alors qu'il n'y a toujours pas de manière officielle pour vérifier l'état du commutateur muet, il y a une solution de contournement/bibliothèque appelée "SoundSwitch" qui semble faire l'affaire. Consultez la nouvelle réponse acceptée pour le lien.

29
répondu taber 2014-01-01 08:26:32

" cependant, si quelqu'un pouvait nous montrer comment utiliser cette AudioSessionProperty_AudioRouteDescription, Le bounty est légitimement le sien."

Eh bien, juste NSLog () le résultat et vous obtenez

routes: {
    "RouteDetailedDescription_Inputs" =     (
    );
    "RouteDetailedDescription_Outputs" =     (
                {
            "RouteDetailedDescription_PortType" = Speaker;
        }
    );
}

malheureusement, j'obtiens ce résultat identique sur un iPad2 / OS 5.0 muté et non muté. Il semble donc être fonctionnellement équivalent à kAudioSessionProperty_AudioRoute, pas de joie là.

à la recherche sur les cartes de développeur trouve qu'il s'agit d'un problème fréquemment rencontré, résumée le mieux avec

"j'ai signalé ce problème avec rdar://9781189 en juillet et le problème est toujours présent dans le GM."

donc oui ... on dirait que vous êtes SOL avec ça en 5.0.

ADDENDUM:

" mais qu'en est-il de ce Cfdiction que vous enregistrez. Comment puis-je accéder à la clé "RouteDetailedDescription_PortType"?"

sans frais l'intégration est votre ami.

  CFDictionaryRef asCFType = nil;
  UInt32 dataSize = sizeof(asCFType);
  AudioSessionGetProperty(kAudioSessionProperty_AudioRouteDescription, &dataSize, &asCFType);
  NSDictionary *easyPeasy = (NSDictionary *)asCFType;
  NSDictionary *firstOutput = (NSDictionary *)[[easyPeasy valueForKey:@"RouteDetailedDescription_Outputs"] objectAtIndex:0];
  NSString *portType = (NSString *)[firstOutput valueForKey:@"RouteDetailedDescription_PortType"];
  NSLog(@"first output port type is: %@!", portType);

produit

le premier type de port de sortie est: haut-parleur!

de nombreux types courants de CFT sont pontés vers des types plus commodes.

http://developer.apple.com/library/ios/#documentation/CoreFoundation/Conceptual/CFDesignConcepts/Articles/tollFreeBridgedTypes.html

Maintenant, il faut un peu de pratique pour deviner correctement ce incantation magique jette obtiendrez quelque chose d'utile d'un dictionnaire comme ci-dessus. Un assistant de vidage de classe selon ces lignes vous aidera à vous mettre à jour avec cela:

  - (void)whatsInThis:(CFDictionaryRef)thingy
  {
     NSDictionary *dict = (NSDictionary *)thingy;
     for (NSString *key in dict.allKeys)
     {
        id value = [dict valueForKey:key];
        NSLog(@"key: %@ value type %@", key, [value class]);
        if ([value isKindOfClass:[NSArray class]])
        {
           NSArray *array = (NSArray *)value;
           for (id item in array)
           {
              NSLog(@" -- object type %@", [item class]);
              if ([item isKindOfClass:[NSDictionary class]])
                 [self whatsInThis:item];
           }
        }
     }
  }

qui, pour notre dictionnaire actuel, produit (en ajoutant des indentations pour plus de clarté)

key: RouteDetailedDescription_Inputs value type __NSCFArray
key: RouteDetailedDescription_Outputs value type __NSCFArray
  -- object type __NSCFDictionary
    key: RouteDetailedDescription_PortType value type __NSCFString

qui vous permet de savoir avec certitude ce que vous auriez pu déduire du journal original, sachant que NSLog affiche des tableaux à l'intérieur de ( ) et des dictionnaires à l'intérieur de { } de sorte que les casts corrects étaient éminemment devinables. Mais certaines structures de type CFT sont plus difficiles à analyser que cela.

11
répondu Alex Curylo 2011-10-21 08:31:31

essayez d'insérer cette ligne au-dessus de votre appel à AudioSessionGetProperty à l'intérieur de deviceissilencé

AudioSessionInitialize(NULL, NULL, NULL, NULL);

devrait alors commencer à retourner la chaîne vide lorsque l'interrupteur est éteint (bien que cela montrera le casque D'écoute et quelques autres états si le casque D'écoute BT ou l'accessoire connecté par exemple).

FWIW, je ne crois pas qu'il existe quelque chose dans les API qui se déclenche lors de la migration proprement dite est déplacé.

0
répondu flake 2011-08-02 18:32:10

je pense que vous avez la mauvaise impression. Un itinéraire où il va. Vous voulez connaître le niveau de volume. Use kAudioSessionProperty_CurrentHardwareOutputVolume

0
répondu slf 2011-10-20 13:52:08

Ok, après avoir suivi kAudioSessionProperty_AudioRoute en utilisant CMD + click, j'ai trouvé ceci: (

/*!
 @enum           AudioSession audio categories states
 @abstract       Deprecated AudioSession properties
 @constant       kAudioSessionProperty_AudioRoute 
 Deprecated in iOS 5.0; Use kAudioSessionProperty_AudioRouteDescription 
 */
enum {
    kAudioSessionProperty_AudioRoute                            = 'rout',   // CFStringRef      (get only)        
};

il s'avère que nous devons utiliser kAudioSessionProperty_AudioRouteDescription , mais ce type renvoie un CFDictionaryRef ou quelque chose, et je n'ai absolument aucune idée de comment le gérer....

j'ai fait cette réponse au cas où personne ne nous montre comment utiliser kAudioSessionProperty_AudioRouteDescription , où je vais essayer d'accepter ma réponse...

Cependant, si quelqu'un pouvait nous montrer comment utiliser ce kAudioSessionProperty_AudioRouteDescription , Le bounty est à juste titre le sien.

edit:

clairement, c'est un problème iOS 5. Je ne l'ai pas dit plus tôt parce que ça avait l'air trop évident, mais j'ai pensé que ce ne serait pas aussi évident pour les moteurs de recherche .. si vous obtenez ce que je veux dire.

donc, iOS 5 ne fonctionne pas avec l'interrupteur silencieux/muet sur l'iPhone en raison de la valeur dépréciée.

0
répondu Mazyod 2011-10-20 20:39:06

trouvé cette bibliothèque http://www.verietassoftware.com/index.php?option=com_content&view=article&id=27&Itemid=115

est-ce que Apple autoriserait ce genre de choses? C'est une bibliothèque de 500Kb faisant de la magie noire avec des paramètres audio et de téléphone

0
répondu Carl D'Halluin 2012-03-18 16:09:40