With music library access your applications can incorporate the songs, audio books, and podcast collections of your users. This functionality can be used to enhance gameplay by allowing users to play their own soundtrack, build custom media-player applications, and more!
NOTE: In order to test this functionality you will need a physical iOS device and will need to be a member of the paid iOS developer program.
Step 1: Creating the Project
Open Xcode and select “Create a new Xcode project”. Select “view-based application” and click “next”. Enter a name for your project (I called mine “Music”), enter your company identifier, make sure you select iPhone for device family, and then click “next”. Choose a place to save your project and click “create”.
Step 2: Import the MediaPlayer Framework
In the navigator area of Xcode 4, select the project name (in our case “Music”). Next, select the current target (“Music” here again), and then select the “Build Phases” tab. Expand the “Link Binary With Libraries” option, and then click the “+” button to add a new framework. Type “MediaPlayer″ into the search box, and select the MediaPlayer.framework option that appears in the list. Click “Add” to include this framework in the linking phase of your project.
Now that you have added the media player framework into your project, you need to import that framework into the view controller that will use the iPod
library. Go to the MusicViewController.h file and insert the following line of code below the UIKit #import
line:
#import <UIKit/UIKit.h> #import <MediaPlayer/MediaPlayer.h>
Step 3: Importing the Project Images
Download the source code and drag the images map to your project. Make sure that the checkbox by Copy item into destination group’s folder (if needed) is checked. This map contains the images we will use in this app.
Step 4: Designing the Interface
In the “Music” folder in the “Project Navigator” click on MusicViewController.xib.
Drag a UIImageView from the library to the view. Make sure the utilities window is shown and go to the Size Inspector. Set both the width and height to 200, the x-coordinate to 60 and the y-coordinate to 20. This image view will show the songs artwork.
Now drag a UISlider to the view and arrange it with the blue guide lines to the bottom of the view. Also make it a bit wider, so it uses the entire width of the view between the two blue guidelines. We will use this slider to adjust the volume.
Now drag 4 UIButtons to the view. Drag the first one under the image view and set its title to “Show Media Picker”. This one will do just what the text says. The other three buttons will be the control buttons. Select the other three buttons and go to the Attributes Inspector. Set the type to Custom and set the image of the buttons respectively to PreviousButton.png, PlayButton.png and NextButton.png. Arrange the buttons like below.
At last, drag three UILabels to the view. Delete the text of all the labels and arrange them like below (I added some text, so you can see where the labels are. You won’t need to add this text). These labels will show some information about the currently playing song.
Step 5: Making the IB Connections
Now that we have designed out interface, we can make the connections. Click the middle button of the editor to show the assistant editor .
Click the image view and CTRL-drag to the interface. A pop-up will show. Enter the text “artworkImageView” for name and then click “connect.”
Now Click the slider and connect it the same way, but name it “volumeSlider”. CTRL-drag again from the slider to the interface, but this time under the curly braces. Set the connection to Action instead of Outlet. Enter “volumeChanged” for the name and make sure the event is Value Changed and click “connect”.
These 4 buttons also need actions. Connect them the same way the slider action was connected. Name the actions as follows:
- Show Media Picker button: showMediaPicker
- Previous button: previousSong
- Play button: playPause
- Next button: nextSong
The play button also needs an outlet. Connect it the same way we connected the outlet for the image view, but name it “playPauseButton”.
At last we need to create the outlets for the labels. Connect them again the same way we connected the image view outlet. Name the first label “titleLabel”, the second label “artistLabel” and the last label “albumLabel”.
Now the code for the MusicViewController.h file should read as follows:
#import <UIKit/UIKit.h> #import <MediaPlayer/MediaPlayer.h> @interface MusicTestViewController : UIViewController { IBOutlet UIImageView *artworkImageView; IBOutlet UISlider *volumeSlider; IBOutlet UIButton *playPauseButton; IBOutlet UILabel *titleLabel; IBOutlet UILabel *artistLabel; IBOutlet UILabel *albumLabel; } - (IBAction)volumeChanged:(id)sender; - (IBAction)showMediaPicker:(id)sender; - (IBAction)previousSong:(id)sender; - (IBAction)playPause:(id)sender; - (IBAction)nextSong:(id)sender; @end
Build and Run the code to make sure that the app runs well. The app only shows the interface we just created, but the buttons won’t work.
Step 6: Creating a Music Player Controller
Go to the MusicViewController.h file and modify the code to read as follows:
#import <UIKit/UIKit.h> #import <MediaPlayer/MediaPlayer.h> @interface MusicTestViewController : UIViewController <MPMediaPickerControllerDelegate> { IBOutlet UIImageView *artworkImageView; IBOutlet UISlider *volumeSlider; IBOutlet UIButton *playPauseButton; IBOutlet UILabel *titleLabel; IBOutlet UILabel *artistLabel; IBOutlet UILabel *albumLabel; MPMusicPlayerController *musicPlayer; } @property (nonatomic, retain) MPMusicPlayerController *musicPlayer; - (IBAction)volumeChanged:(id)sender; - (IBAction)showMediaPicker:(id)sender; - (IBAction)previousSong:(id)sender; - (IBAction)playPause:(id)sender; - (IBAction)nextSong:(id)sender; - (void) registerMediaPlayerNotifications; @end
As you can see we added the MPMediaPickerControllerDelegate and created a MPMusicPickerController. We also added the method registerMediaPlayerNotifications for registering notifications from the media player.
Now go to the MusicViewController.m file and synthesize the musicPlayer by adding the following code under the @implementation :
@synthesize musicPlayer;
We also need to release it in the dealloc
and viewDidUnload
method with the following code:
[musicPlayer release];
Now go to the viewDidLoad
method. Uncomment it and add the following code under [super viewDidLoad];
musicPlayer = [MPMusicPlayerController iPodMusicPlayer];
Here we set our music player controller to an iPodMusicPlayer. This means that our app shares the iPod state and if we quit our app the music will continue playing. The applicationMusicPlayer is the other type. This music player plays the music locally within your app. Your music player can have a different now playing item than the built-in iPod app. When you quit the app, the music stops playing.
Step 7: Updating the UI Upon Load
Add the following code to the viewDidLoad
method:
[volumeSlider setValue:[musicPlayer volume]]; if ([musicPlayer playbackState] == MPMusicPlaybackStatePlaying) { [playPauseButton setImage:[UIImage imageNamed:@"pauseButton.png"] forState:UIControlStateNormal]; } else { [playPauseButton setImage:[UIImage imageNamed:@"playButton.png"] forState:UIControlStateNormal]; }
First, we set the current value of the slider to the music player’s current volume. Volume is a value between 0 and 1. If the volume is 0 there is no sound and when the volume is 1, the volume is on his maximum. After that we check it the music player is playing something. If it’s playing, we set the image of the playPauseButton to the pauseButton image and when it isn’t playing we set the image of the playPauseButton to the playButton image.
Step 8: Register the MediaPlayer Notifications
Add the following code to the viewDidLoad
method:
[self registerMediaPlayerNotifications];
This line will call the registerMediaPlayerNotifications
method where we will register three observers for the media player notifications. Add the following code under the viewDidLoad
method:
- (void) registerMediaPlayerNotifications { NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter addObserver: self selector: @selector (handle_NowPlayingItemChanged:) name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification object: musicPlayer]; [notificationCenter addObserver: self selector: @selector (handle_PlaybackStateChanged:) name: MPMusicPlayerControllerPlaybackStateDidChangeNotification object: musicPlayer]; [notificationCenter addObserver: self selector: @selector (handle_VolumeChanged:) name: MPMusicPlayerControllerVolumeDidChangeNotification object: musicPlayer]; [musicPlayer beginGeneratingPlaybackNotifications]; }
Here we register three observers for the media player notifications. The first one is for the MPMusicPlayerControllerNowPlayingItemDidChangeNotification
. We will use this to update the current media item information. The second one is for the MPMusicPlayerControllerPlaybackStateDidChangeNotification
, we also use this one to update our UI. The third and last one is for the MPMusicPlayerControllerVolumeDidChangeNotification
, we will use this one to update the current value of our slider.
Whenever you register an observer, you should also be sure to remove it in the viewDidUnload
and the dealloc
methods. So add the following code to both these methods:
[[NSNotificationCenter defaultCenter] removeObserver: self name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification object: musicPlayer]; [[NSNotificationCenter defaultCenter] removeObserver: self name: MPMusicPlayerControllerPlaybackStateDidChangeNotification object: musicPlayer]; [[NSNotificationCenter defaultCenter] removeObserver: self name: MPMusicPlayerControllerVolumeDidChangeNotification object: musicPlayer]; [musicPlayer endGeneratingPlaybackNotifications];
Add the following code under the registerMediaPlayerNotifications
method:
- (void) handle_NowPlayingItemChanged: (id) notification { MPMediaItem *currentItem = [musicPlayer nowPlayingItem]; UIImage *artworkImage = [UIImage imageNamed:@"noArtworkImage.png"]; MPMediaItemArtwork *artwork = [currentItem valueForProperty: MPMediaItemPropertyArtwork]; if (artwork) { artworkImage = [artwork imageWithSize: CGSizeMake (200, 200)]; } [artworkImageView setImage:artworkImage]; NSString *titleString = [currentItem valueForProperty:MPMediaItemPropertyTitle]; if (titleString) { titleLabel.text = [NSString stringWithFormat:@"Title: %@",titleString]; } else { titleLabel.text = @"Title: Unknown title"; } NSString *artistString = [currentItem valueForProperty:MPMediaItemPropertyArtist]; if (artistString) { artistLabel.text = [NSString stringWithFormat:@"Artist: %@",artistString]; } else { artistLabel.text = @"Artist: Unknown artist"; } NSString *albumString = [currentItem valueForProperty:MPMediaItemPropertyAlbumTitle]; if (albumString) { albumLabel.text = [NSString stringWithFormat:@"Album: %@",albumString]; } else { albumLabel.text = @"Album: Unknown album"; } }
This method will respond to the MPMusicPlayerControllerNowPlayingItemDidChangeNotification:
notification. First we create a MPMediaItem and set it to the nowPlayingItem. Then we create a UIImage called artworkImage. For default we set the image to the noArtworkImage. Then we create an MPMediaItemArtwork object which stores the artwork of the current item. If there is artwork, we set the artworkImage to the artwork. Finally, we set the artworkImageView image to the artworkImage.
Then we create an NSString with stores the title of the currentItem. Again, we check if the currentItem has a title. If it has a title we set the tittleLabel to that title. If the currentItem doesn’t have a title, we set the title to “unknown”. We do the same with the artist and album.
We only used the artwork, title, artist, and album properties here, but there are many more properties like lyrics, rating and composer.
Add the following code under the handle_NowPlayingItemChanged:
method:
- (void) handle_PlaybackStateChanged: (id) notification { MPMusicPlaybackState playbackState = [musicPlayer playbackState]; if (playbackState == MPMusicPlaybackStatePaused) { [playPauseButton setImage:[UIImage imageNamed:@"playButton.png"] forState:UIControlStateNormal]; } else if (playbackState == MPMusicPlaybackStatePlaying) { [playPauseButton setImage:[UIImage imageNamed:@"pauseButton.png"] forState:UIControlStateNormal]; } else if (playbackState == MPMusicPlaybackStateStopped) { [playPauseButton setImage:[UIImage imageNamed:@"playButton.png"] forState:UIControlStateNormal]; [musicPlayer stop]; } }
This method will respond to the MPMusicPlayerControllerPlaybackStateDidChangeNotification:
notification. Here we check the state of the music player and update the image of the playPauseButton. As you can see we stop the music player if its state is MPMusicPlaybackStateStopped. We do this to ensure that the music player will play its queue from the start.
At last, add the following code under the handle_PlaybackStateChanged:
method:
- (void) handle_VolumeChanged: (id) notification { [volumeSlider setValue:[musicPlayer volume]]; }
This method will respond to the MPMusicPlayerControllerVolumeDidChangeNotification:
notification. Here we update the volume sliders value to the music player’s volume. We do this because we can also adjust the volume with the hardware buttons.
Step 9: Making the controls work
Go to the volumeChanged:
action and modify the code to read as follows:
- (IBAction)volumeChanged:(id)sender { [musicPlayer setVolume:[volumeSlider value]]; }
Here we set the volume of the music player to the value of the slider.
Now go to the playPause:
action and modify the code to read as follows:
- (IBAction)playPause:(id)sender { if ([musicPlayer playbackState] == MPMusicPlaybackStatePlaying) { [musicPlayer pause]; } else { [musicPlayer play]; } }
First we check if the music player is playing. If it’s playing we will pause the music player. If the music isn’t playing, we start playing the music.
Now go to the previousSong:
action and modify the code to read as follows:
- (IBAction)previousSong:(id)sender { [musicPlayer skipToPreviousItem]; }
Here we let the music player skip to the previous item.
At last, go to the nextSong:
action and modify the code to read as follows:
- (IBAction)nextSong:(id)sender { [musicPlayer skipToNextItem]; }
Here we let the music player skip to the next item.
Step 10: Showing the Media Picker
The last thing we need to do is to show the media picker and play a song if the user picked one or more songs. Go to the showMediaPicker:
action and modify the code to read as follows:
- (IBAction)showMediaPicker:(id)sender { MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeAny]; mediaPicker.delegate = self; mediaPicker.allowsPickingMultipleItems = YES; mediaPicker.prompt = @"Select songs to play"; [self presentModalViewController:mediaPicker animated:YES]; [mediaPicker release]; }
First we create a media picker controller and set its delegate to self. We also allow the user to pick multiple items. The prompt is the text that will be displayed when the media picker shows. I set the prompt to “select songs to play”. Then we show the media picker and release it.
Add the following code under the showMediaPicker
: action:
- (void) mediaPicker: (MPMediaPickerController *) mediaPicker didPickMediaItems: (MPMediaItemCollection *) mediaItemCollection { if (mediaItemCollection) { [musicPlayer setQueueWithItemCollection: mediaItemCollection]; [musicPlayer play]; } [self dismissModalViewControllerAnimated: YES]; } - (void) mediaPickerDidCancel: (MPMediaPickerController *) mediaPicker { [self dismissModalViewControllerAnimated: YES]; }
The first method is called when the user picks a song. In this method we check if there is media item collection and if there is a media item collection we set the music player’s queue to that media item collection and start playing. We always dismiss the media picker controller. The second method only dismisses the media player controller.
Click Build and Run to test the application. You can pick a song if you press the Show Media Picker button. You see the title, artist, album and artwork of the current song. If you adjust the volume with the hardware buttons you can see the slider changing.
Wrap Up
Thanks for reading this tutorial about iPod library access! If you have questions or comments on this tutorial, leave them in the comments section below!
Comments