iOS SDK: Music Library Access

iOS SDK: Music Library Access

Tutorial Details
  • Technology: iOS SDK
  • Difficulty: Intermediate
  • Completion Time: 60 - 90 Minutes

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”.

New Project

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.

Figure

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.

Adding Files

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.

Interface

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 .

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.”

Connection

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!

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://punjabipoetry.co.nr Manvir

    Will it work in the background too ? I am planning on using this tutorial of yours along with background image tutorial where you showed how to animate pictures. is it possible.
    sorry but i am totally new to programming. first week on macs , have some experience on windows but want to learn more about ios developlemt.
    thanks

    • Jeroen van Rijn
      Author

      Hey, thanks for reading the tutorial!

      The music will continue playing on the background of you set the music player to an iPodMusicPlayer. Of you do this your app will shares it’s iPod state with the build-in iPod app.

      Good luck with learning ios development!

  • Suhail Larik

    Thanks Jeroen van Rijn!
    Very Helpful tutorial.
    Rijn i have downloaded source code and build and run that code but when i click on show media picker button application crashes:-(
    what should i do? am i doing any thing wrong?
    i m using Xcode Version 3.2.5. ios 4.2. i m running this app on simulator not on real device.

    • Jeroen van Rijn
      Author

      Hey, I’m glad you like the tutorial.

      The problem is that you are running the app in the simulator. The simulator hasn’t got an iPod library so if you want to show the media picker the app will crash. To use this app you should run it on a real device.

    • Gavin Creber

      Because there is no ipod framework on the simulator, check the console it tells you that…. Just in case your not sure, console is under where you write your code

  • Andrew

    AWESOME TUTORIAL!!!

    I have a question. I have put this into a TabBarController. But, when I switch between tabs, the music stops. Is the a way I can fix that?

    -Andrew

  • fdubrez

    Well, this is nice!

    Thanks for sharing it.

    Regards

  • Jeffrey Kranenburg

    Hi Awesome Tutorial, got it working in my app just fine:-)

    I was wondering could you add an update to show a time scrub??

    Cheers

    • Jeroen van Rijn
      Author

      Thanks! what is the name of your app?

      It isn’t that difficult to create that. First you set the maximum value of a slider of progress view to the playback duration of the current song like this:

          slider.maximumValue = [[musicPlayer.nowPlayingItem valueForProperty:MPMediaItemPropertyPlaybackDuration] longValue];
      

      You also create a timer to update the sider or progress view. Update that timer at least once a second. In that timer you update the slider of progress view like this:

          slider1.value = musicPlayer.currentPlaybackTime;
      

      I hope this van help you.

      • Stanislao

        i insert

        scrubslider.maximumValue = [[musicPlayer.nowPlayingItem valueForProperty:MPMediaItemPropertyPlaybackDuration] longValue];
        in
        musicviewcontroller.m

        declare
        IBOutlet UILabel *scrubslider;
        - (IBAction)volumeChanged:(id)sender;

        but the app crash.. and all the button is bloked :(

        thanks for help

      • Blue Echo

        could you please explain this with a bit more detail because i keep trying this but it wont work, so if you could show like everything you have to do to make the uiprogressview work would be much appreciated, thanks

  • stephen

    thanks for the tutorial,I m creating an iphone app that pulls rss feed that contains .mp3 files from server and i want to create a custom media player just like the one above.is it possible to integerate with the above example or should i go with any other media player framework like(AVplayer)

  • Juan Celemín

    Hey.. great tutorial.. i was wondering if it’s possible to implement an audio level metering to this app… Thanks !!

  • Nealle

    Great article, thanks for sharing.

    I was wondering if there are any security risks or issues in adding these features to apps? I have seen this type of feature added to apps that it just does not makes sense to add it too, like a foreign exchange information app.

  • edward

    Great tutorial. I’m having trouble with the media picker, in Landscape mode it is still in Portrait Orientation. I updated the code in my implementation file but it is not working for me, any suggestions?

    Best,

    Edward Gonzalez

  • Codger

    Great tutorial as a developer myself I was just starting a new application and one of the features I needed was to add a media player. Your article is very well written and consise.

    Thanks Agin keep up the good work

    Codger

  • ItsMe

    Awesome!
    Thanks a lot!!!

  • bensge

    Hey!
    I really like your tutorial, but sadly the source code isn’t downloadable. Can you fix that?
    Thanks,

    bensge

  • stanislao

    hi! thanks for tutorial!! nice!!
    i have a questions for you?
    is simple insert a BPM CHANGER?

    thank you!

  • Rob

    Thanks for the tutorial very well done and easy to follow. I was wondering how would you go about adding lyrics could you point me towards a good starting point???

  • Chris

    Thank you for the tutorial. I have one issue. I am trying to use this in a Storyboard application and the media player button does not work, it will not launch the view. If I write the application in nib format (pre-storyboard) it works just fine. How can I make this same tutorial work but when using storyboard?

  • Alec

    Hi, just wondering, I have to build an app for something like one of those guided tours in a museum where the user enters a four digit number that corresponds to what is on display in the exhibit, anyways, two questions, one is it ok with you if I took your project and copied everything into the app but changed the UI around a little bit, and if so, do you have any idea how I could set the app up to play a certain song from the user entering a number? Thanks.

  • Roarke

    Thanks for the tutorial!

    I’ve been having some problems with the images. Xcode cannot bind the buttons to the images. I noticed your image folder is orange, mine is blue. Does this signify anything?

    Also, in Xcode 4.2+, what type of application do we choose? I don’t see a view based option anymore

  • raj

    Very nice tutorial >>>>>>>>>>>>>>>>

  • Shankar Iyer

    I want to access current track being played on the ipod/ music player of the iphone to be shown on my app i.e. the app running should show the track (played on the ipod/music player of the Iphone) played in the background

  • Brandon

    The real question is how do you do this while using a Tab Based Application?!?!?! I don’t understand how to link, unless it is View Based.

  • rishabh goyal

    hey man it was awesome.
    can you please tell me how to import the song in our application.
    thanks.

  • Beau Hankins

    Hey, great tutorial!

    How would I go about importing the entire music library into my app?
    I’ve seen it integrated into apps on the appstore such as: “AlbumWall” (http://itunes.apple.com/au/app/albumwall/id389381427?mt=8)]

    Thanks in advance,
    Beau

    • Ajay

      Hey,

      Did you got any success with it ?

  • rashid

    very much useful tutorial

  • vineela

    Thanks!

    Very Helpful tutorial.

  • Anum

    Hi Jeroen!

    Thanks for such a nice and clear tutorial. I want to ask you that how can I play songs from iPod library using AVAudioPlayer? After searching, I came to know that I need to copy songs to my app bundle – Can you tell me how to copy songs to bundle from iPod or provide any link… or there is any other possible way to do this?

    Thanks.

  • Josh

    Like the tutorial its very well written and easy to follow… However, was wondering if you could possible enlighten a person on how to setup a label to show the remaining track time? Its giving me some trouble.

    Thanks in advance.

  • kuldeep

    Thanku for sharing a great tutorial …

    when i run this code on simulator than it crash my app so how i fix it. Reply

  • iPhone Developer

    Hi Jeroen,
    I was thinking that if we integrate the music in our app, how will i be able to stop the music when the user stops the app??

  • Super

    Very good. Thanks a lot.

    Any idea on how to receive musicplayer notification when the app is in the background (for instance when i skip song from the headset?

    See also

    http://stackoverflow.com/questions/13483908/ios-receive-media-player-notifications-when-app-is-in-background/

    and

    http://stackoverflow.com/questions/4928207/receiving-notifications-with-app-in-background-mode/

    thanks

  • Gavin Creber

    Hi great work, just tried the tutorial on a iPhone 5 and it mostly works except dismissModalViewController has been depreciated, but still works, the only issue I have is that album art dosenot display and neither dose Title,Artist and album info,

    Any input would be great to get it fully working

  • gavla

    orry the Album Art and Title, Album, Artist do work it’s just dismissModalViewController has been depreciated, is the only issue

  • Thilina Hewagama

    for deprecated issue, use these

    [self presentViewController:mediaPicker animated:YES completion:nil];

    [self dismissViewControllerAnimated:YES completion:nil];

    no issues.

    • gavla

      Thanks for those they work great

  • romarcis

    Good tutorial! I have a question.. How can I control if “there is no next song in list” so I can can hide or alpha the next button? thanks

  • taylornrolyat

    Great tutorial! I do have a question though. Every time the user clicks the button to choose media to add to play, and reclicks on the button later to add more songs, the original chosen songs disappear. How can we make it so that the songs added stay added and the user can view the songs in the queue?

    Thanks!

  • Mohd Rahib

    thanks Jeroen for this wonderful tutorial..i have an issue, want to pick the sound from gallery for UILocalNotification sound, is it possible??

  • http://twitter.com/whit2450 Joel White

    Great tutorial really helpful! found one little issue in your code that I spent awhile on. It turns out that MPMediaItemPropertyArtwork always returns an object. So even if there is no album artwork for the current item it you still get an object and the If statement is executed setting artwork to null instead of leaving it set to noArtworkImage.png