iOS AudioSessionSetActive () bloquant le thread principal?

dans mon application iOS, j'essaie d'implémenter "ducking": alors que mon application joue un son "court", toute musique de fond devrait être abaissée en volume. Une fois le son terminé, le volume de la musique doit revenir à sa valeur d'origine.

Tel que mis en œuvre, l'esquive fonctionne essentiellement comme prévu. Toutefois, lorsque j'appelle AudioSessionSetActive (NO) dans audioPlayerDidFinishPlaying: pour mettre un terme à l'esquive, il y a une petite pause dans les mises à jour de l'interface user qui se produisent à ce moment. Cela implique un dessin personnalisé, ainsi que par ex. défilement automatique du text et ainsi de suite.

Maintenant, voici la question:

Est-ce un problème connu dans iOS6? Je cours le même code sur un iPod / iOS5, où je ne vois pas ce comportement. Ou est-ce que je manque quelque chose du code? Peut-être que l'un d'entre vous a déjà rencontré le même problème et trouvé une solution viable.

Merci beaucoup pour votre soutien,

Goetz

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //... NSError *err = nil; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&err]; //... } - (void) playSound { // Enable ducking of music playing in the background (code taken from the Breadcrumb iOS Sample) UInt32 value = kAudioSessionCategory_MediaPlayback; AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(value), &value); // Required if using kAudioSessionCategory_MediaPlayback value = YES; AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(value), &value); UInt32 isOtherAudioPlaying = 0; UInt32 size = sizeof(isOtherAudioPlaying); AudioSessionGetProperty(kAudioSessionProperty_OtherAudioIsPlaying, &size, &isOtherAudioPlaying); if (isOtherAudioPlaying) {  AudioSessionSetProperty(kAudioSessionProperty_OtherMixableAudioShouldDuck, sizeof(value), &value); } AudioSessionSetActive(YES); // Initialization of the AVAudioPlayer NSSsortingng *soundFileName = [[NSBundle mainBundle] pathForResource:@"Beep" ofType:@"caf"]; NSURL    *soundFileURL = [[NSURL alloc] initFileURLWithPath:soundFileURL]; self.soundPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil]; [self.soundPlayer setDelegate:self]; [self.soundPlayer setVolume:[80.0/100.0]; [self.soundPlayer play]; } - (void) audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { // Callback coming from the AVAudioPlayer // This will block the main thread; however, it is necessary to disable ducking again AudioSessionSetActive(NO);    } 

Après quelques égratignures et debuggings, j'ai trouvé la réponse à cette question. Comme l'indique la question d'origine, afin de rétablir le niveau audio après avoir esquivé, vous devez désactiver la session audio.

Le problème est que la désactivation de la session entraîne un retard de 0,5 seconde lors de la lecture de l'audio, ce qui bloque le thread UI et empêche l'application de répondre (dans mon cas, une timer perd 0,5 seconde et bégaie).

Pour résoudre le problème, je fais mon appel pour désactiver la timer sur un fil séparé. Cela résout le problème de blocage de l'interface user et permet à l'audio de se faufiler comme prévu. Le code ci-dessous montre la solution. Notez qu'il s'agit d'un code C # car j'utilise Xamarin, mais il pourrait facilement être traduit en Objective-C ou Swift pour le même résultat:

  private void ActivateAudioSession() { var session = AVAudioSession.SharedInstance(); session.SetCategory(AVAudioSessionCategory.Playback, AVAudioSessionCategoryOptions.DuckOthers); session.SetActive(true); } private void DeactivateAudioSession() { new System.Threading.Thread(new System.Threading.ThreadStart(() => { var session = AVAudioSession.SharedInstance(); session.SetActive(false); })).Start(); } 

J'appelle ActivateAudioSession avant de câbler mon AVAudioPlayer et une fois que mon lecteur a fini de jouer, j'appelle DeactivateAudioSession (ce qui est nécessaire pour rétablir le niveau audio). Commencer la désactivation sur un nouveau thread évite le niveau audio, mais ne bloque pas l'interface user.