I am in the midst of creating an iOS mobile app for a client that will play a variety of audio tracks.
One of the features that I wanted to implement was to display information about a currently-playing audio track on the lock screen and banner . This is one of those simple convenience to a mobile user and a must-have if your app has background audio playing. Personally, I use this feature all the time!
You should first observe the AVPlayerItem
of AVAudioPlayer
like so:
[playerItem addObserver:self forKeyPath:@"timedMetadata" options:NSKeyValueObservingOptionNew context:nil];
Then create some global variables:
NSString *title;
NSString *artist;
UIImage *artwork;
You would then probably need a function like the one below, so you observe the key path timedMetadata
and update the InfoCenter through updateInfoCenterWithTitle:andArtist:andCover:
.
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"timedMetadata"])
{
for (int i = 0; i < [audioPlayer.currentItem.timedMetadata count]; i++)
{
AVMetadataItem *metaData = [audioPlayer.currentItem.timedMetadata objectAtIndex:i];
if ([[metaData commonKey] isEqualToString:AVMetadataCommonKeyArtist]) {
artist = (NSString *)metaData.value;
}
else if ([[metaData commonKey] isEqualToString:AVMetadataCommonKeyTitle])
{
title = (NSString *)metaData.value;
[self updateInfoCenterWithTitle:title andArtist:artist andCover:artwork];
}
else if ([[metaData commonKey] isEqualToString:AVMetadataCommonKeyArtwork])
{
if ([metaData.keySpace isEqualToString:AVMetadataKeySpaceID3])
{
NSDictionary *dictionary = [metaData.value copyWithZone:nil];
artwork = [UIImage imageWithData:[dictionary objectForKey:@"data"]]];
} else if ([metaData.keySpace isEqualToString:AVMetadataKeySpaceiTunes]) {
artwork = [UIImage imageWithData:[metaData.value copyWithZone:nil]];
}
}
else {
NSLog(@"%@ --> %@", [metaData commonKey], metaData.value);
}
}
}
}
This is where the magic happens:
- (void)updateInfoCenterWithTitle:(NSString *)title andArtist:(NSString *)artist andCover:(UIImage *)cover
{
if (cover == nil) {
cover = [UIImage imageNamed:@"defaultCover"];
}
MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];
[infoCenter setNowPlayingInfo:@{MPMediaItemPropertyTitle:title,
MPMediaItemPropertyArtist:artist,
MPMediaItemPropertyArtwork:[[MPMediaItemArtwork alloc] initWithImage:cover]}];
}