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.
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).
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.
" 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.
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.
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é.
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
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.
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