Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Paused audio starts playing automatically on applicationWillEnterForeground:

When applicationDidEnterBackground: triggers, I pause the audio which is playing using AVAudioPlayer:

[self.avPlayer pause];

Now, when applicationWillEnterForeground: triggers, the audio starts to play automatically! Since I didn't start the audio, the user interface is not updated and it shows that the audio is still in the paused state.

What's going on? This is happening in iOS 6.x, on iPad 2. This issue is not reproducing on the older iPad running iOS 5.x.

This is how I setup the AVAudioSession:

// Setup the audio session
BOOL succeeded = NO;
NSError *sessionError = nil;
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setDelegate:self];

if ([session respondsToSelector:@selector(setPreferredSampleRate:error:)]) {
    succeeded = [session setPreferredSampleRate:128000.0f error:&sessionError];

} else {
    succeeded = [session setPreferredHardwareSampleRate:128000.0f error:&sessionError];
}

succeeded = [session setCategory:AVAudioSessionCategorySoloAmbient error:&sessionError];
succeeded = [session setActive:YES error:&sessionError];
like image 226
Mustafa Avatar asked Jul 08 '13 12:07

Mustafa


2 Answers

In one of my recent app, I found a similar issue where audio playback pauses automatically and resumes after you are interrupted by a call and GUI is not refreshing in my app. I have fixed the issue by using the following method:

Register this in the class where you handle player code

[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

And use AVAudioSession's audioPlayerEndInterruption delegate method to get control after the application was resumed. In this function you can resume the playback and update UI accordingly.

- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player withOptions:(NSUInteger)flags

Hope this helps.

like image 135
HRM Avatar answered Sep 20 '22 21:09

HRM


I found some weird UX and when going back and forth from the background and based on a bunch of posts, I'd plan for a little jiggling of the handle. I did something fairly simple - check if other music is playing when the app enters the foreground:

    func applicationWillEnterForeground(application: UIApplication) {
         if AVAudioSession.sharedInstance().otherAudioPlaying{                 
NSNotificationCenter.defaultCenter().postNotificationName(Notifications.ForegroundEnteredWithOtherAudioPlaying, object: nil)
         }
    }

If so, you can pause the player when that notification is received. You mentioned that did not work but without seeing the rest of your code, it's tough to know why.

One other thing I had to do is to remove the observer to the status flag from the player item because I listen to that for the ReadyToPlay value where I tell AvPlayer to actually play. That gets fired when the app enters the foreground and there is an active audio session. So by removing that observer on pause and setting it every time on play, (which isn't crazy because I'd argue it's an OK constraint to say I only care to observe after I hit play), I'm able to control of lot of the weirdness.

I also wrote up a bunch of test cases which I'll share here to make sure your experience is in pretty good shape. It's not comprehensive but it's also fairly thorough.

    // 1. Play, leave app, don't open anything else, come back
    // 2. Play, leave app, open an app that plays music, come back
    // 3. Play, leave app, open an app that plays music, play music, come back
    // 4. Play, let audio go for 5 seconds, pause, open an app that plays music, come back
    // 5. Play, let audio go for 5 seconds, pause, open an app that plays music, play music, come back
    // 6. Press play, leave app before playback starts, open an app that plays music, come back
    // 7. Crazy s$*t like play, leave app, open an app that plays music, play music, come back, tap a different song 
like image 45
Tony Avatar answered Sep 21 '22 21:09

Tony