Note: Example project is available here
One of the great additions iOS 5 brought us is the ability to display meta data about currently playing tracks on the lock screen. This is a great convenience to users and a must if your app has background audio playing. I know I use this to great extent, especially when driving. Best of all, it’s actually quite simple to get going.
For the sake of this tutorial, we’re going to be focusing mainly on the MPNowPlayingInfoCenter and not much on how to play streaming audio. If you have questions, as always, please feel free to leave a comment. I, as I’ve stated in the past, am still fairly new to the iOS/Objective-C world so if you see something that makes you say ‘UR DOING IT WRONG!’, please let me know. If you’d like to review the details of MPNowPlayingInfoCenter, you can read the Apple documentation.
To get started, create a new project. I created one using the single view template but feel free to do whatever you’d like. Once you’ve created the project there are a few things we need to do to get the project setup. By default, simply playing audio won’t persist if the application leaves the foreground. We need to tell iOS we’d like to play background audio. To get started doing this, open up your application’s info.plist file and add a new row: “Required background modes” (UIBackgroundModes). This creates an array with Item 0 change the value to “App plays audio” (audio). I’ve got a screen shot of what this should look like:
Next, there are a few frameworks we need to link to our project:
- AVFoundation.framework
- MediaPlayer.framework
playButton and linked it in the nib. I’ve also attached an IBAction, playButtonPress to the button’s touch up inside event.You can see those items in myViewController.h:
@interface ViewController : UIViewController {
IBOutlet UIButton *playButton;
}
@property (nonatomic, retain) IBOutlet UIButton *playButton;
-(IBAction)playButtonPress:(id)sender;
Next I’m going to import the MPMoviePlayerController header to add a player to my view controller class:
#import <MediaPlayer/MPMoviePlayerController.h>
To add the player controller we’ll add these lines to the ViewController.h:
MPMoviePlayerController *audioPlayer;
and
@property (nonatomic, retain) MPMoviePlayerController *audioPlayer;
Swing over to your ViewController.m file and we’re going to add a few more headers:
#import <MediaPlayer/MPNowPlayingInfoCenter.h> #import <MediaPlayer/MPMediaItem.h> #import <AVFoundation/AVFoundation.h>
And we’ll synthesize our playButton and audioPlayer:
@synthesize playButton, audioPlayer;
In viewDidLoad we’ll initialize our audio session and audioPlayer and pre-load it with content from the web. We’re going to use Oliver Drobnik’s Cocoanetics podcast as our audio feed for this tutorial. Oliver has an awesome podcast packed with great info for iOS developers, you can find out more about it at http://cocoanetics.com.
[[AVAudioSession sharedInstance] setDelegate: self];
NSError *myErr;
// Initialize the AVAudioSession here.
if (![[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&myErr]) {
// Handle the error here.
NSLog(@"Audio Session error %@, %@", myErr, [myErr userInfo]);
}
else{
// Since there were no errors initializing the session, we'll allow begin receiving remote control events
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
}
//initialize our audio player
audioPlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:@"http://www.cocoanetics.com/files/Cocoanetics_031.mp3"]];
[audioPlayer setShouldAutoplay:NO];
[audioPlayer setControlStyle: MPMovieControlStyleEmbedded];
audioPlayer.view.hidden = YES;
[audioPlayer prepareToPlay];
It’s important we have line 12 as this is what tells iOS we want to receive any remote control events from the lock screen (i.e. backward, play, pause, forward). I’ve found that without that line your information will never display (here’s a link to my Stack Overflow question chronicling my journey to that discovery).
Moving onward, next we need to create our action that actually plays the audio and posts the information to the lock screen:
- (IBAction)playButtonPress:(id)sender {
[audioPlayer play];
Class playingInfoCenter = NSClassFromString(@"MPNowPlayingInfoCenter");
if (playingInfoCenter) {
NSMutableDictionary *songInfo = [[NSMutableDictionary alloc] init];
MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage: [UIImage imagedNamed:@"AlbumArt"]];
[songInfo setObject:@"Audio Title" forKey:MPMediaItemPropertyTitle];
[songInfo setObject:@"Audio Author" forKey:MPMediaItemPropertyArtist];
[songInfo setObject:@"Audio Album" forKey:MPMediaItemPropertyAlbumTitle];
[songInfo setObject:albumArt forKey:MPMediaItemPropertyArtwork];
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songInfo];
}
}
Let’s go through this line by line starting with line 5. Lines 5 & 7 of our code make sure the class MPNowPlayingInfoCenter exists since this functionality was just added in iOS 5. Next, we create an NSMutableDictionary called songInfo that will contain the information for the lock screen. Next we create an MPMediaItemArtwork item that will store the image. We set our information on lines 13-16. These are the properties that display on the lock screen. Something to keep in mind is there are several 3rd party peripherals that interact with the iPhone/iPod that play music that might pull this information. There are a few additional properties you can assign that may be accessed by other devices and you can read about those in the Apple docs. Last and certainly not least, the magic happens with line 17 as we add the information to the lock screen! Viola!


Pingback: MPNowPlayingInfoCenter defaultCenter will not update or retrieve information