I'm developing a music player that plays music in the background.
The app has integration with both Spotify and Apple music, the user will only be authenticated in one of the services.
At the moment, I'm able to play the musics in the app and in the background with both services. I also was able to set the MPNowPlayingInfoCenter
and it is displaying the correct info, but the play/pause, next track and previous tracks are working only when the user is authenticated with Spotify.
MPNowPlayingInfoCenter show music information
When the user is synced with the Apple Music service and tries to use any off the commands the app is not able to receive the notifications, instead it seems that the Apple Music app is handling it, thus playing the next song on the Apple Music playlist instead of my app playlist.
I'm using an AVPlayer
to play the musics when synced with Apple Music and SPTAudioStreamingController
when synced with Spotify.
I also verified the requirements suggested by matt on this question: xcode - MPNowPlayingInfoCenter info is not displayed on iOS 8
Here is the code of the Media center setup:
- (void)setMediaCenterinfoForPlayer:(id)player {
SPTAudioStreamingController *spotifyPlayer;
AVPlayer *localPlayer;
NSMutableDictionary *trackInfo = [[NSMutableDictionary alloc] initWithDictionary: @{ MPMediaItemPropertyTitle: self.currentTrack.name,
MPMediaItemPropertyArtist: ((SPTArtist *)self.currentTrack.artists[0]).name,
MPMediaItemPropertyAlbumTitle : self.currentTrack.album.name,
MPNowPlayingInfoPropertyPlaybackRate: @(1.0)
}];
if ([player isKindOfClass:[SPTAudioStreamingController class]]) {
spotifyPlayer = (SPTAudioStreamingController *)player;
[trackInfo setObject:[NSNumber numberWithFloat:spotifyPlayer.currentPlaybackPosition] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
[trackInfo setObject:[NSNumber numberWithFloat:spotifyPlayer.currentTrackDuration] forKey:MPMediaItemPropertyPlaybackDuration];
} else {
localPlayer = (AVPlayer *)player;
NSTimeInterval playbackTime = [self currentPlaybackTimeForPlayer:player];
[trackInfo setObject:@(playbackTime) forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
[trackInfo setObject:@(CMTimeGetSeconds(localPlayer.currentItem.asset.duration)) forKey:MPMediaItemPropertyPlaybackDuration];
}
[MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = trackInfo;
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
Class playingInfoCenter = NSClassFromString(@"MPNowPlayingInfoCenter");
if (playingInfoCenter) {
[self albumURLCoverForCurrentTrackWithBlock:^(UIImage *albumImage) {
MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage:albumImage];
[trackInfo setObject:albumArt forKey:MPMediaItemPropertyArtwork];
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:trackInfo];
}];
}
}
Here is the code for the event handling:
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
if (event.type == UIEventTypeRemoteControl) {
MPNowPlayingInfoCenter *center = [MPNowPlayingInfoCenter defaultCenter];
NSMutableDictionary *playingInfo = [NSMutableDictionary dictionaryWithDictionary:center.nowPlayingInfo];
[playingInfo setObject:[NSNumber numberWithFloat:[AudioPlayerManager sharedInstance].spotifyPlayer.currentPlaybackPosition] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
center.nowPlayingInfo = playingInfo;
if (event.subtype == UIEventSubtypeRemoteControlPlay) {
[[AudioPlayerManager sharedInstance] playTrack];
} else if (event.subtype == UIEventSubtypeRemoteControlPause) {
[[AudioPlayerManager sharedInstance] pauseTrack];
} else if (event.subtype == UIEventSubtypeRemoteControlPreviousTrack) {
[[AudioPlayerManager sharedInstance] previousTrack];
} else if (event.subtype == UIEventSubtypeRemoteControlNextTrack) {
[[AudioPlayerManager sharedInstance] nextTrack];
}
[[NSNotificationCenter defaultCenter] postNotificationName:kEventTypeRemoteControlUpdateState object:self];
}
}
Hope anyone can point me a way to tackle this situation. Thanks!