This three-part tutorial series will teach you how to build a custom music player with the iOS SDK. Read on!
Series Format:
Welcome to the first of three tutorials in a step-by-step series on building a custom music player with the MediaPlayer framework. In a previous tutorial on Mobiletuts+, I demonstrated how to access an iOS device music library within your own application. This Tuts+ Premium series will focus on building a much more complex player with a custom interface. In this first series installment, we will create the project and display a list of the user's songs and albums.
NOTE: In order to test this app you will need a physical iOS device. You will also need to be a member of the paid iOS developer program in order to deploy the demo app onto your device for testing.
Step 1: Creating the Project
Open Xcode and select "Create a new Xcode project". Select "Empty Application" and click "Next". Enter a name for your project (I called mine "Music") and make sure you select iPhone for device family and select all the checkboxes, except the "Use Core Data" checkbox. After that, click "Next" and choose a place to save your project and then click "Create".
Step 2: Setting Supported Orientations
We only want to use our application in portrait mode, so go to the Supported Interface Orientations section and deselect the landscape orientations.
Step 3: Import the MediaPlayer Framework
Go to the "Build Phases" tab and expend the "Link Binary With Libraries" option. 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.
Step 4: Create a Storyboard
Go to "File" > "New" > "File..." or press ⌘N to create a new file. Go to the "Use Interface" section, select "Storyboard and click "Next". Make sure that the Device Family is set to iPhone and click "Next" again. Name your storyboard MainStoryboard and click "Create".
Now we have to link the storyboard to our project. Select the project name in the navigator menu of Xcode and select the current target (in our case "Music"). Next select the "Summery" tab and go to the "iPhone / iPad Deployment Info" section. Once there select our storyboard called "MainStoryboard" for the Main Storyboard.
Step 5: Creating the App Interface
Open the storyboard and drag a UITabBarController
from the Object Library to the canvas. As you can see, the screens are already in the iPhone 5 resolution. Of course, the app will also work on older iPhones because it will automatically scale down. Now delete the two connected View Controllers and drag two Navigation Controllers from the Object Library to the canvas. CTRL drag from the UITabBarController
to one of the Navigation Controllers and select "view controllers" from the pop-up menu. Do the same for the other Navigation Controller.
Select the UITabBarItem
from one of the Navigation Controllers and change its title to "Songs". Also change the title of the navigation bar of that Navigation Controller to "Songs". Again, do the same for the other Navigation Controller, but this time change the titles to "Albums".
The last thing we need to do, to make our interface work, is to change the application:didFinishLaunchWithOptions:
method, so open AppDelegate.m and modify the method as follows:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { return YES; }
Now we have created our interface, let’s test the app. Click Build and Run or press ⌘R to test the application. The app should show a UITabBarController
with two tabs, called Songs and Albums.
Step 6: Showing a Song List
Go to "File" > "New" > "File..." to create a new file. This time go to the Cocoa Touch section and select "Objective-C class". Click "Next", enter "SongsViewController" for the class and make sure that it’s a subclass of UITableViewController
and that both the checkboxes are not selected. Click "Next" again and than click "Create".
Open SongsViewController.h and add the following line under #import <UIKit/UIKit.h>
to add the MediaPlayer framework:
#import <MediaPlayer/MediaPlayer.h>
Now open SongsViewController.m and modify the numberOfSectionsInTableView:
and the tableView: numberOfRowsInSection:
method as follows:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { MPMediaQuery *songsQuery = [MPMediaQuery songsQuery]; NSArray *songs = [songsQuery items]; return [songs count]; }
In the first method, we tell the UITableView
that we want one section. In the second method, we tell the tableview that we want that the number of rows is the same as the number of songs in the users iPod library. We accomplish that with a MPMediaQuery. A media query specifies a set of media items from the users iPod library. A media query includes a number of constructors that each have a grouping type. We used the songsQuery method to create or query. The grouping type of that query is automatically set to MPMediaGroupingTitle, which of course groups the tracks by their title. The following constructors are available in the MPMediaQuery class:
- albumsQuery
- artistsQuery
- audiobooksQuery
- compilationsQuery
- composersQuery
- genresQuery
- playlistsQuery
- songsQuery
And you can group them with the following grouping types:
- MPMediaGroupingAlbum
- MPMediaGroupingArtist
- MPMediaGroupingTitle
- MPMediaGroupingComposer
- MPMediaGroupingGenre
- MPMediaGroupingPlaylist
- MPMediaGroupingPodcastTitle
After we created our query we get the media items from that query and store them in an array called "songs".
Now go to the tableView:cellForRowAtIndexPath:
and modify the code to read as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; // Configure the cell... MPMediaQuery *songsQuery = [MPMediaQuery songsQuery]; NSArray *songs = [songsQuery items]; MPMediaItem *rowItem = [songs objectAtIndex:indexPath.row]; cell.textLabel.text = [rowItem valueForProperty:MPMediaItemPropertyTitle]; cell.detailTextLabel.text = [rowItem valueForProperty:MPMediaItemPropertyArtist]; return cell; }
Here we insert the songs titles and artist into the cells. First we create a sonsQuery and we get it’s items, just like in the tableView:numberOfRowsInSection:
method. After that we create a MPMediaItem from the sonsQuery it’s items. At last we set the text of the cells textLabel and detailTextLabel to the media items title and artist.
Now we have finished our code for the SongsViewController, open the storyboard, go to the Songs Navigation Controller and select the table view cell. Open the Attributes Inspector, set the Identifier to Cell and change the Style from "Custom" to "Subtitle".
At last select the TableView controller, open the Identity Inspector and set the Class to the SongsViewController, we just created.
Now we have finished the SongsViewController and can see the users songs in our app, I think it’s a good time to test our app again. Click Build and Run and you should see your songs in the tableview.
Step 7: Fill the Albums Tab
For the albums tab we can start the same as we did with the songs tab, so go to "File" > "New" > "File..." to create a new file. Select "Objective-C class" and click "Next". This time enter "AlbumsViewController" for the class and make sure that it’s a subclass of UITableViewController and that both the checkboxes are not selected. Click "Next" again and than click "Create".
Open AlbumsViewController.h and add the following line under #import <UIKit/UIKit.h>
to add the MediaPlayer framework:
#import <MediaPlayer/MediaPlayer.h>
Now open SongsViewController.m and modify the numberOfSectionsInTableView:
and the tableView:numberOfRowsInSection:
methods as follows:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { MPMediaQuery *albumsQuery = [MPMediaQuery albumsQuery]; NSArray *albums = [albumsQuery collections]; return [albums count]; }
The first method is the same as we used for the songs tab, but the second method is slightly different. Here we created a albums query and we used the count of the collections from that query.
In the albums tab we are also going to show the artwork of the albums. The problem is that there isn’t always artwork available, so we have to provide a default artwork for that situation. Download the sample code attached to this project and drag the No-artwork-albums.png and [email protected] images into your project. Make sure "Copy items into destination group’s folder (if needed)" is checked and click "Finish".
Now go to the tableView:cellForRowAtIndexPath:
and modify the code to read as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; // Configure the cell... MPMediaQuery *albumsQuery = [MPMediaQuery albumsQuery]; NSArray *albums = [albumsQuery collections]; MPMediaItem *rowItem = [[albums objectAtIndex:indexPath.row] representativeItem]; cell.textLabel.text = [rowItem valueForProperty:MPMediaItemPropertyAlbumTitle]; cell.detailTextLabel.text = [rowItem valueForProperty:MPMediaItemPropertyAlbumArtist]; MPMediaItemArtwork *artwork = [rowItem valueForProperty:MPMediaItemPropertyArtwork]; UIImage *artworkImage = [artwork imageWithSize: CGSizeMake (44, 44)]; if (artworkImage) { cell.imageView.image = artworkImage; } else { cell.imageView.image = [UIImage imageNamed:@"No-artwork-albums.png"]; } return cell; }
The beginning of this method is almost the same as in the SongsViewController. First we create a albumsQuery and we get its collections, just like in the tableView:numberOfRowsInSection:
method. After that we create a MPMediaItem from the sonsQuery it’s collections. As you can see we have to use representiveItem property to receive the media item. That’s because the albums array contains a list of MPMediaItemCollections instead of MPMediaItems. A MPMediaItemCollection is a sorted set of media items (MPMediaItems) from the users iPod library. Then we set the text of the cells textLabel and detailTextLabel to the media items album name and album artist. At last we get the albums artwork. It there is artwork available we use it and else we show the image we just added to the project.
Now we have also finished our code for the AlbumsViewController, open the storyboard, go to the Albums Navigation Controller and select the table view cell. Open the Attributes Inspector, set the Identifier to Cell and change the Style from "Custom" to "Subtitle".
At last select the TableView controller, open the Identity Inspector and set the Class to the AlbumsViewController, we just created.
Now our app also shows the users albums in the albums tab of the app, click Build & Run to test the app.
Conclusion
In this first part of the tutorial we have covered how to create a new app from scratch with a storyboard and how to load the songs and albums from a users iPod library into a custom user interface. In the next part we are going to continue with the albums section and we will learn how to play the tracks.
Comments