El audio de fondo de iOS no se reproduce

Tengo una aplicación que usa modos de fondo CoreBluetooth . Cuando ocurre un evento determinado, necesito reproducir un sonido de alarma. Todo funciona bien en primer plano y toda la funcionalidad de bluetooth funciona bien en segundo plano. También lo tengo trabajando donde progtwig UILocalNotification ‘s en el fondo para hacer sonar la alarma, sin embargo, no me gusta la falta de control de volumen con estos, así que quiero reproducir el sonido de la alarma con AVAudioPlayer.

.plist audio modo de fondo a mi archivo .plist , pero no puedo hacer que el sonido se reproduzca correctamente.

Estoy usando una clase singleton para la alarma e inicializo el sonido así:

 NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:soundName ofType:@"caf"]]; player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]; player.numberOfLoops = -1; [player setVolume:1.0]; 

Comienzo el sonido así:

 -(void)startAlert { playing = YES; [player play]; if (vibrate) [self vibratePattern]; } 

y usa esto para la vibración:

 -(void)vibratePattern { if (vibrate && playing) { AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); [self performSelector:@selector(vibratePattern) withObject:nil afterDelay:0.75]; } } 

La vibración funciona bien en el fondo, pero no hay sonido. Si utilizo Systemsound para reproducir el sonido de esta manera, se reproduce bien (pero sin control de volumen):

 AudioServicesCreateSystemSoundID((__bridge CFURLRef)url, &_sound); AudioServicesPlaySystemSound(_sound); 

Entonces, ¿cuál podría ser el motivo por el cual AVAudioPlayer no está reproduciendo el archivo de sonido?

Gracias

EDIT ——-

El sonido se reproducirá si ya se está reproduciendo cuando la aplicación está en segundo plano. Sin embargo, hacer que comience a jugar mientras está en segundo plano no está funcionando.

agregue una clave llamada Modos de fondo obligatorios en el archivo de lista de propiedades (.plist).

como la siguiente imagen …

enter image description here puede obtener ayuda …

y agregue el siguiente código en

AppDelegate.h

 #import  #import  

AppDelegate.m

en la aplicación didFinishLaunchingWithOptions

 [[AVAudioSession sharedInstance] setDelegate:self]; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; [[AVAudioSession sharedInstance] setActive:YES error:nil]; [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; UInt32 size = sizeof(CFStringRef); CFStringRef route; AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &size, &route); NSLog(@"route = %@", route); 

Si desea cambios según los eventos, debe agregar el siguiente código en AppDelegate.m

 - (void)remoteControlReceivedWithEvent:(UIEvent *)theEvent { if (theEvent.type == UIEventTypeRemoteControl) { switch(theEvent.subtype) { case UIEventSubtypeRemoteControlPlay: [[NSNotificationCenter defaultCenter] postNotificationName:@"TogglePlayPause" object:nil]; break; case UIEventSubtypeRemoteControlPause: [[NSNotificationCenter defaultCenter] postNotificationName:@"TogglePlayPause" object:nil]; break; case UIEventSubtypeRemoteControlStop: break; case UIEventSubtypeRemoteControlTogglePlayPause: [[NSNotificationCenter defaultCenter] postNotificationName:@"TogglePlayPause" object:nil]; break; default: return; } } } 

basado en la notificación tiene que trabajar en ello ..

code.tutsplus.com proporciona un tutorial .

para HandsetBluetooth tienes que agregar el siguiente código en AppDelegate

 UInt32 size = sizeof(CFStringRef); CFStringRef route; AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &size, &route); NSLog(@"route = %@", route); NSString *routeString=[NSString stringWithFormat:@"%@",route]; if([routeString isEqualToString:@"HeadsetBT"]){ UInt32 allowBluetoothInput = 1; AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryEnableBluetoothInput,sizeof (allowBluetoothInput),&allowBluetoothInput); } 

Además de la configuración de plist , debe modificar el delegado de la aplicación.

 - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restre your application to its current state in case it is terminated later. [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL]; [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; } 

También en su controller escriba el siguiente código.

 [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; [[AVAudioSession sharedInstance] setActive: YES error: nil]; [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; 

Tal vez deberías hacer que la sesión de audio de tu aplicación sea más alta que otras.

Además del proceso para configurar el modo de fondo, debe establecer AudioSession correctamente.

A veces simplemente haciendo esto no es suficiente

 [[AVAudioSession sharedInstance] setActive:YES error:&activationErr]; 

porque en el documento de Ayuda hay una discusión sobre setActive

 Discussion If another active audio session has higher priority than yours (for example, a phone call), and neither audio session allows mixing, attempting to activate your audio session fails. Deactivating your session will fail if any associated audio objects (such as queues, converters, players, or recorders) are currently running. 

Entonces, setActive: withOptions: error: es necesario. Justo como este

 [audioSession setCategory :AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error] 

Es decir, debe hacer que la sesión de audio de su aplicación sea más alta que otras.

De forma predeterminada, AVAudioPlayer utiliza la categoría AVAudioSessionCategorySoloAmbient , que se silencia con el interruptor de timbre. La categoría AVAudioSessionCategoryPlayback es más adecuada para su situación, ya que no está silenciada por el interruptor y continuará reproduciéndose en segundo plano.

 NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:soundName ofType:@"caf"]]; player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]; [player setCategory:AVAudioSessionCategoryPlayback error:nil]; player.numberOfLoops = -1; [player setVolume:1.0]; 

Esto (con suerte) puede ser tan simple como retener el audio. Si pudieras verificar dónde estableciste la propiedad del jugador que es fuerte.

 @property (strong, nonatomic) AVAudioPlayer *player; 

Espero que esto ayude,

Saludos, Jim