How to update MPMusicPlayerController when song changes

2.7k views Asked by At

I was wondering you would update the UI when the song changes in MPMusicPlayerController. For example, if you have an image view with the album cover, but a user presses the skip button, how would you update the image view's image with the new album cover?

2

There are 2 answers

0
Uma_Shanker_Tiwari On

To control music playback, we use an instance of MPMusicPlayerController. There are two types of music players. The iPodMusicPlayer is a reference to the music player instance used by the iPod app. Any settings you change, such as the shuffle or repeat modes, will be changed in the iPod app, too. If the iPod is playing when your application starts, the music will continue playing and you can access the current song and skip back and forward through the currently active playlist. When your app quits, the music will continue playing. I imagine this mode is very handy for most utility apps that try to improve your music listening experience by interacting with the iPod. In contrast, applicationMusicPlayer gives you a music player whose settings you can change independently of the iPod app. This is probably the way to go if your app is a game and you want to give the user the ability to choose the background music from their library. In Songtext, we’ll use iPodMusicPlayer because we want to know which song is playing when our app launches:

@property (nonatomic, strong) MPMusicPlayerController *musicPlayer;
self.musicPlayer = [MPMusicPlayerController iPodMusicPlayer];

The music player uses notifications to inform you about changes of: - The current song (MPMusicPlayerControllerNowPlayingItemDidChangeNotification), - The play/paused/stopped state (MPMusicPlayerControllerPlaybackStateDidChangeNotification), or - The volume (MPMusicPlayerControllerVolumeDidChangeNotification). So the next thing you typically do is to register yourself as an observer for the notifications you are interested in, e.g. in viewDidLoad. We want to receive all 3 notifications:

// Register for music player notifications
NSNotificationCenter *notificationCenter = [NSNotificationCenter   defaultCenter];
[notificationCenter addObserver:self 
                   selector:@selector(handleNowPlayingItemChanged:)
                        name:MPMusicPlayerControllerNowPlayingItemDidChangeNotification 
                     object:self.musicPlayer];
[notificationCenter addObserver:self 
                   selector:@selector(handlePlaybackStateChanged:)
                       name:MPMusicPlayerControllerPlaybackStateDidChangeNotification 
                     object:self.musicPlayer];
[notificationCenter addObserver:self 
                   selector:@selector(handleExternalVolumeChanged:)
                        name:MPMusicPlayerControllerVolumeDidChangeNotification 
                     object:self.musicPlayer];
[self.musicPlayer beginGeneratingPlaybackNotifications];

There is one other related notification that is sent by the iPod media library when the contents of the library change, e.g. when you sync your device with iTunes. You must listen to this notification if your app creates its playlists that need to be updated after library changes. To do so, register yourself as an observer for MPMediaLibraryDidChangeNotification notifications and call:

[[MPMediaLibrary defaultMediaLibrary] beginGeneratingLibraryChangeNotifications]

The notification handlers are where you update your UI in response to changes in the player’s state:

// When the now playing item changes, update song info labels and artwork display. - (void)handleNowPlayingItemChanged:(id)notification { // Ask the music player for the current song. MPMediaItem *currentItem = self.musicPlayer.nowPlayingItem;

// Display the artist, album, and song name for the now-playing media item.
// These are all UILabels.
self.songLabel.text   = [currentItem valueForProperty:MPMediaItemPropertyTitle];
self.artistLabel.text = [currentItem valueForProperty:MPMediaItemPropertyArtist];
self.albumLabel.text  = [currentItem valueForProperty:MPMediaItemPropertyAlbumTitle];    

// Display album artwork. self.artworkImageView is a UIImageView.
CGSize artworkImageViewSize = self.artworkImageView.bounds.size;
MPMediaItemArtwork *artwork = [currentItem valueForProperty:MPMediaItemPropertyArtwork];
if (artwork != nil) {
    self.artworkImageView.image = [artwork imageWithSize:artworkImageViewSize];
} else {
    self.artworkImageView.image = nil;
}

}

// When the playback state changes, set the play/pause button appropriately.
- (void)handlePlaybackStateChanged:(id)notification {
MPMusicPlaybackState playbackState = self.musicPlayer.playbackState;
if (playbackState == MPMusicPlaybackStatePaused || playbackState == MPMusicPlaybackStateStopped) {
    [self.playPauseButton setTitle:@"Play" forState:UIControlStateNormal];
} else if (playbackState == MPMusicPlaybackStatePlaying) {
    [self.playPauseButton setTitle:@"Pause" forState:UIControlStateNormal];
}

}

// When the volume changes, sync the volume slider
- (void)handleExternalVolumeChanged:(id)notification {
// self.volumeSlider is a UISlider used to display music volume.
// self.musicPlayer.volume ranges from 0.0 to 1.0.
[self.volumeSlider setValue:self.musicPlayer.volume animated:YES];

}

0
Jasper On

In the case you are looking for the lock screen playing info:

Have a look at MPNowPlayingInfoCenter

You need to pass a NSDictionary, here's an example:

-(void)updateNowPlayingInfo
{
    //Set Values for MPNowPlayingInfoCenter
    NSArray *keys = [NSArray arrayWithObjects:
                     MPMediaItemPropertyTitle,
                     MPMediaItemPropertyPlaybackDuration,
                     MPNowPlayingInfoPropertyPlaybackRate,
                     MPNowPlayingInfoPropertyElapsedPlaybackTime,
                     nil];

    NSArray *values = [NSArray arrayWithObjects:
                       self.currentPlayingVideo.title,
                       [NSNumber numberWithFloat:self.currentPlayingVideo.duration],
                       [NSNumber numberWithInt:1],
                       [NSNumber numberWithDouble:self.currentVideoPlayView.videoPlayerViewController.moviePlayer.currentPlaybackTime],
                       nil];

    NSDictionary *mediaInfo = [NSDictionary dictionaryWithObjects:values forKeys:keys];
    [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:mediaInfo];
}