Darren Darren - 6 months ago 18
Objective-C Question

Audio playing while app in background iOS

I have an app mostly based around Core Bluetooth.
When something specific happens, the app is woken up using Core Bluetooth background modes and it fires off an alarm, however I can't get the alarm working when the app is not in the foreground.

I have an Alarm Singleton class which initialises

AVAudioPlayer
like this:

NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:soundName
ofType:@"caf"]];

self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
[self.player prepareToPlay];
self.player.numberOfLoops = -1;
[self.player setVolume:1.0];

NSLog(@"%@", self.player);


This is the method that is called when my alarm code is called:

-(void)startAlert
{
NSLog(@"%s", __FUNCTION__);

playing = YES;
[self.player play];
NSLog(@"%i", self.player.playing);

if (vibrate) {
[self vibratePattern];
}
}


Now when the app is in the foreground,
self.player.playing
returns
1
however when the app is in the background
self.player.playing
returns
0
. Why would this be?
All the code is being called, so the app is awake and functioning.
The vibrate works perfectly which uses
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);


Any idea why this sound won't play?

Thanks

Answer

I have an App than also needs background audio but my App works with the App background mode "Voice over IP" as it needs to record sometimes. I play background audio telling the App singleton I need to play audio in background:

UIBackgroundTaskIdentifier newTaskId = UIBackgroundTaskInvalid;
if([thePlayer play]){
    newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];   
}

EDIT: You must call [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL]; before your app goes to background. In my app, it is at the same time you start playing, in yours, if the player might be started in background, you should do:

- (void)applicationDidEnterBackground:(UIApplication *)application{
  // You should retain newTaskId to check for background tasks and finish them 
  newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];   
}
Comments