comience a reproducir audio desde una tarea de background a través de AVAudioPlayer en XCode

Estoy tratando de comenzar a reproducir un sonido desde una tarea en segundo plano a través de un AVAudioPlayer que se instaló entonces, así que esto es lo que tengo.

Para mayor legibilidad, recorté todos los valores seleccionados por el usuario.

- (void)restartHandler { bg = 0; bg = [[UIApplication shanetworkingApplication] beginBackgroundTaskWithExpirationHandler:^{ [[UIApplication shanetworkingApplication] endBackgroundTask:bg]; }]; tim = [NSTimer timerWithTimeInterval:.1 target:self selector:@selector(upd) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:tim forMode:NSRunLoopCommonModes]; } - (void)upd { if ([[NSDate date] timeIntervalSinceDate:startDate] >= difference) { [self playSoundFile]; [tim invalidate]; [[UIApplication shanetworkingApplication] endBackgroundTask:bg]; } } - (void)playSoundFile { NSError *sessionError = nil; [[AVAudioSession shanetworkingInstance] setCategory:AVAudioSessionCategoryPlayback error:&sessionError]; // new player object _player = [[AVQueuePlayer alloc] init]; [_player insertItem:[AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"Manamana" withExtension:@"m4a"]] afterItem:nil]; [_player setVolume:.7]; [_player play]; NSLog(@"Testing"); } 

Explicación: bg , tim , startDate , difference y _player son variables declaradas globalmente. Llamo - (void)restartHandler desde un método disparado por el usuario y dentro de él comienzo un timer de repetición de 10Hz para - (void)upd . Cuando se alcanza una diferencia preestablecida, - (void)playSoundFile recibe una llamada e inicia e inicia el jugador. Se llama a la testing NSLog al final del método.

Ahora lo extraño es que si llamo - (void)playSoundFile cuando la aplicación está activa, todo funciona bien, pero si lo comienzo desde la tarea de background, simplemente no reproducirá ningún sonido.

Cualquier ayuda, sugerencia, solución o instrucciones es muy apreciada.

Editar

Así que traté de usar diferentes hilos en el time de ejecución y, como parece, si el jugador no está instanciado en el hilo principal, aparecerá el mismo problema. También intenté usar AVPlayer y AVAudioPlayer donde la propiedad .playing devolvió YES y todavía no se reproducía ningún sonido.

Por lo que aprendí después de escribir una aplicación para jugadores, parece que no puedes comenzar a reproducir audio cuando tu aplicación ya está en segundo plano durante más de X segundos, incluso si has configurado todo correctamente.

Para solucionarlo, debes usar sabiamente la tarea de background. Lo más importante es que NO debe llamar a endBackgroundTask inmediatamente después de playSoundFile . Retraso durante unos 5-10 segundos.

Así es como logré hacerlo para iOS6 e iOS7.

1, agregue UIBackgroundModes de audio en plist.

2, Establecer categoría de session de audio:

3, Cree un AVQueuePlayer en el subprocess principal y encoja un recurso de audio antes de que la aplicación entre en segundo plano.

* Para continuar reproduciendo en segundo plano (como reproducir una list de reproducción) *

4, Asegúrese de que la queue de audio en AVQueuePlayer nunca se vacía , de lo contrario su aplicación se suspenderá cuando finalice la reproducción del último activo.

5, si 5 segundos no es suficiente para que pueda get el siguiente activo, puede emplear una tarea de background para retrasar la suspensión. Cuando el activo esté listo, debe llamar a endBackgroundTask después de 10 segundos.

incluya su llamada playSoundFile en el siguiente, esto siempre debería ejecutarse en el hilo principal

 dispatch_async(dispatch_get_main_queue(), ^{ }); 

agregue esto si a su - (void) playSoundFile para comprobar si se creó el reproductor, de lo contrario, luego - (void) playSoundFile

 if(!_player) { _player = [[AVQueuePlayer alloc] init]; } 

¿Me parece que no tiene el modo de background adecuado? Xcode captura de pantalla

Además, parece que otro usuario tuvo el mismo problema y lo solucionó con una publicación de Apple Docs. Enlace a la publicación

Quizás necesite hacer el paso para configurar la session de audio como activa:

 [audioSession setActive:YES error:&activationError]; 

¡Espero eso ayude!

Si necesita comenzar a reproducir un sonido en segundo plano (sin un truco como seguir jugando al volumen cero hasta que necesite el sonido):

  • Establezca el modo de background Audio en su p.list;
  • Establezca la categoría AudioSession en AVAudioSessionCategoryPlayback
  • Establezca AudioSession en activo
  • Cuando su aplicación en segundo plano se está ejecutando, inicie una tarea de background antes de reproducir el sonido (aparentemente cuando el time de background restante es inferior a 10 segundos, el sonido no se reproduce)

Esto ahora funciona para mí.