Sunday, November 18, 2012

Incorrect MPMusicPlaybackState Bug

iOS 5 introduced a bug with MPMusicPlayerController that results in the MPMusicPlaybackState of the music player to be incorrect.

This will manifest itself in your music playing app as a pause button being presented to the user when the music is paused (it should be a play button so they can start playback again).

Here is the solution I posted to the following stackoverflow post (code is easier to read over there):

I have also reported this bug to Apple. I was able to reproduce it 100% of the time by doing the following:

Launch application that uses MPMusicPlayerController. Launch the "Music" App. Hit Play, Skip, Skip, Pause, Play, Pause Open the original application and the MPMusicPlaybackState of MPMusicPlayerController will be incorrect.

None of the proposed solutions here worked for me. The solution that did work was to keep track of when the bug was occurring and updating the UI specially in these cases. When the UIApplicationDidBecomeActiveNotification notification is received (see matbur post for more details on this), see if audio is actually not playing when the MPMusicPlaybackState said it was:

  -(BOOL) isPlaybackStateBugActive { 
     MPMusicPlaybackState playbackState = self.musicPlayer.playbackState; 
     if (playbackState == MPMusicPlaybackStatePlaying) { 
     AudioSessionInitialize (NULL, NULL, NULL, NULL); UInt32 sessionCategory = kAudioSessionCategory_AmbientSound; 
     AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof (sessionCategory), &sessionCategory); 
     AudioSessionSetActive (true); 
     UInt32 audioIsPlaying; 
     UInt32 size = sizeof(audioIsPlaying);         
          AudioSessionGetProperty(kAudioSessionProperty_OtherAudioIsPlaying, &size, &audioIsPlaying);
       if (!audioIsPlaying){ NSLog(@"PlaybackState bug is active"); 
           return YES; 
    return NO; 

Don't forget to import the AudioToolbox framework.

UPDATE: As mentioned in the comments below I believe I started seeing the opposite scenario as well. MPMusicPlaybackState indicated the player was paused when the music was actually playing. This was far less common and harder to replicate but I decided to use everything inside the outer if statement from the above code to determine playback state in all situations.

Here is the modified code as mentioned in the comments below: