Start playing sound from background task through AVAudioPlayer in Xcode

I am trying to start playing sound from a background task using the created AVAudioPlayer, so here is what I have.

For readability, I cut out all user-selected values.

- (void)restartHandler { bg = 0; bg = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [[UIApplication sharedApplication] 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 sharedApplication] endBackgroundTask:bg]; } } - (void)playSoundFile { NSError *sessionError = nil; [[AVAudioSession sharedInstance] 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"); } 

Explanation: bg , tim , startDate , difference and _player are globally declared variables. I call - (void)restartHandler from the user method and inside it starts a 10 Hz re-timer for - (void)upd . When a predetermined difference - (void)playSoundFile reached, - (void)playSoundFile is called and initiates and starts the player. NSLog testing will be called at the end of the method.

Now it’s strange if I call - (void)playSoundFile when the application is active, everything works fine, but if I start it with a background task, it just won’t play sound.

Any help, hint, solution or heads-up is welcome.

Edit

So, I tried to use different threads at runtime, and as it seems, if Player is not created in the main thread, the same problem will appear. I also tried using AVPlayer and AVAudioPlayer , where the AVAudioPlayer .playing property returned YES and the sound was still not playing.

+6
source share
4 answers

From what I learned after writing the application for the player, it seems that you can not start playing sound when your application is already in the background for longer than X seconds, even if you configured everything correctly.

To fix this, you should use background tasks wisely. Most importantly, you should NOT call endBackgroundTask immediately after playSoundFile . Delay for 5-10 seconds.

Here's how I managed to do it for iOS6 and iOS7.

1, Add UIBackgroundModes audio to plist.

2, Set the audio session category:

3, create an AVQueuePlayer in the main thread and start the sound resource before the application enters the background.

* To continue playing in the background (for example, playing a playlist) *

4, make sure that the audio queue in AVQueuePlayer never becomes empty , otherwise your application will be suspended when it finishes playing the last asset.

5 If you are not enough 5 seconds to receive the next asset, you can use background tasks to delay the suspension. When the asset is ready, you should call endBackgroundTask in 10 seconds.

+12
source

enable the playSoundFile call in the following, this should always be run in the main thread

 dispatch_async(dispatch_get_main_queue(), ^{ }); 

add this if on your - (void) playSoundFile to check if the player is created, if not, then create it

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

It seems to me that you do not have the corresponding background mode? Xcode screenshot

Also, it looks like the other user had the same problem and fixed his publication in the Apple Docs document. Post Link

Perhaps you just need to take a step to configure the audio session as active:

 [audioSession setActive:YES error:&activationError]; 

Hope this helps!

0
source

If you need to start playing sound in the background (without a trick, for example, when playing with a zero tone until you need sound):

  • Set background audio in your p.list;
  • Set AudioSession category to AVAudioSessionCategoryPlayback
  • Set AudioSession to Active
  • When your background application is running, start the background task before playing the sound (apparently, when the remaining background time is less than 10 seconds, the sound does not play)

Now it works for me.

0
source

Source: https://habr.com/ru/post/959465/


All Articles