I need some help with an issue when my music player app is playing on background.
I'm able to play the musics in the app and in the background with both services. I'm also able to set the MPNowPlayingInfoCenter and it displays the correct info, but the play/pause, next track and previous tracks are working only when the user is authenticated with Spotify:
notifications are received correctly by the app when the user authenticates with Spotify
but it doesn't work when user authenticates with Apple Music. In this case it seems that Apple Music is the one receiving the notifications.
I'm using an AVPlayer to play the musics when synced with Apple Music and SPTAudioStreamingController when synced with Spotify.
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];
}
}
Could anyone please point me a way to tackle this situation?
Related
I am using AVPlayerLayer to play video and playing the audio of video when app goes in background. Is there any way I can manage controls when screen is locked. User wants to stop play the audio.
My app is working in background but controls are not visible so user have to open the app and stop the video.
I got the solution simply used MPRemoteCommandCenter and added details about video see code in Objetive C
// to setup the playing info
- (void) setupNowPlayingInfoCenter{
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
[commandCenter.togglePlayPauseCommand setEnabled:YES];
[commandCenter.playCommand setEnabled:YES];
[commandCenter.pauseCommand setEnabled:YES];
[commandCenter.nextTrackCommand setEnabled:NO];
[commandCenter.previousTrackCommand setEnabled:NO];
[commandCenter.playCommand addTargetWithHandler: ^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
[self->_player play];
return MPRemoteCommandHandlerStatusSuccess;
}];
[commandCenter.pauseCommand addTargetWithHandler: ^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
[self->_player pause];
return MPRemoteCommandHandlerStatusSuccess;
}];
}
// to update the playing info when enter in background
- (void) updateNowPlayingInfoCenter {
NSDictionary *metadata = [self.media metaData];
MPNowPlayingInfoCenter *playingInfoCenter = [MPNowPlayingInfoCenter defaultCenter];
NSMutableDictionary *songInfo = [[NSMutableDictionary alloc] init];
[songInfo setObject:metadata[MIBMediaMetaDataTrackNameKey] forKey:MPMediaItemPropertyTitle];
[songInfo setObject:metadata[MIBMediaMetaDataTrackNameKey] forKey:MPMediaItemPropertyArtist];
[songInfo setObject:metadata[MIBMediaMetaDataTrackDurationKey] forKey:MPMediaItemPropertyPlaybackDuration];
[songInfo setObject:[NSNumber numberWithDouble:(!self.playing ? 0.0f : 1.0f)] forKey:MPNowPlayingInfoPropertyPlaybackRate];
[playingInfoCenter setNowPlayingInfo:songInfo];
}
// add this line of code in init or viewdidload
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:#selector(applicationDidEnterBackgroundNotification:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
Called these 2 methods when enter in background
- (void)applicationDidEnterBackgroundNotification:(NSNotification *)notification {
[self setupNowPlayingInfoCenter];
[self updateNowPlayingInfoCenter];
}
If the app is playing the audio and phone screen is locked then control screen is shown as below. I am not able to take any action on avplayer
In my appdelegate I implemented:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
MPRemoteCommandCenter *rcc = [MPRemoteCommandCenter sharedCommandCenter];
[[rcc skipForwardCommand] setEnabled:NO];
[[rcc skipBackwardCommand] setEnabled:NO];
[[rcc nextTrackCommand] setEnabled:NO];
[[rcc previousTrackCommand] setEnabled:NO];
[[rcc skipForwardCommand] setEnabled:NO];
[[rcc skipBackwardCommand] setEnabled:NO];
rcc.playCommand.enabled = YES;
rcc.pauseCommand.enabled = YES;
[[MPRemoteCommandCenter sharedCommandCenter].playCommand addTarget:self action:#selector(play)];
[[MPRemoteCommandCenter sharedCommandCenter].pauseCommand addTarget:self action:#selector(pause)];
}
- (void) play {
[[MyVideoController instance] play];
}
- (void) pause {
[[MyVideoController instance] pause];
}
class MyVideoController consists of:
- (void) pause {
[self.avPlayer pause];
}
- (void) play {
[self.avPlayer play];
}
Even though these methods are triggered (added breakpoints to check), no action on avplayer is taken. No matter what, avplayer doesn't pause.
Is there any way to pause the avplayer?
EDIT 1:
Adding the complete code
In my AppDelegate:
- (void) remoteControlReceivedWithEvent: (UIEvent *) event {
[[ZVideoPlayerController instance] eventReceived:event];
if (event.type == UIEventTypeRemoteControl) {
switch (event.subtype) {
case UIEventSubtypeRemoteControlTogglePlayPause: {
break;
}
case UIEventSubtypeRemoteControlPlay: {
[[ZVideoPlayerController instance] play];
break;
}
case UIEventSubtypeRemoteControlPause: {
[[ZVideoPlayerController instance] pause];
break;
}
default:
break;
}
}
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
}
I AM RECEIVING EVENTS BUT THE AUDIO DOESN'T PAUSE UPON CALLING PAUSE METHOD ON AVPLAYER.
EDIT 2:
instance declaration in PlayerController class
+ (instancetype)instance {
static id instance = nil;
if (instance == nil)
{
static dispatch_once_t onceToken = 0;
dispatch_once(&onceToken, ^(void) {
NSAssert(instance == nil, #"Singleton instance is already allocated.");
instance = [[super allocWithZone:NULL] init];
});
}
return instance;
}
initialising AVPlayer
AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:avAsset];
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
NSError *activationError = nil;
BOOL success = [[AVAudioSession sharedInstance] setActive: YES error: &activationError];
NSMutableDictionary *songInfo = [[NSMutableDictionary alloc] init];
MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage: [UIImage imageNamed:#"Audio_Thumbnail_Play"]];
[songInfo setObject:title forKey:MPMediaItemPropertyTitle];
[songInfo setObject:#"100" forKey:MPMediaItemPropertyPlaybackDuration];
[songInfo setObject:albumArt forKey:MPMediaItemPropertyArtwork];
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songInfo];
self.avPlayer = [AVPlayer playerWithPlayerItem:playerItem];
self.avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer];
I found a solution to the problem. As I was getting nil value of avPlayer, I used my PageViewController class to get the instance of PlayerController. Then I used the instance of this playerController to play and pause my avplayer because this instance holds the reference to avPlayer.
- (PlayerController *)getVideoController {
NSArray *controllers = [UtiliyClass getNavigationController].viewControllers;
PageViewController *pageController = nil;
for (UIViewController *cont in controllers) {
if ([cont isKindOfClass:[PageViewController class]]) {
pageController = (PageViewController *)cont;
break;
}
}
if (pageController == nil) {
return nil;
}
NSArray *objectsController =pageController.pageController.viewControllers;
PlayerController *videoPlayerController = nil;
for (UIViewController *item in objectsController) {
if ([item isKindOfClass:[PlayerController class]]) {
videoPlayerController = (PlayerController *)item;
break;
}
}
return videoPlayerController;
}
- (void) pause {
PlayerController *controller = [self getVideoController];
[controller.avPlayer pause];
}
- (void) play {
PlayerController *controller = [self getVideoController];
[controller.avPlayer play];
}
You need to register for remote notification to update player state when application is locked.For that follow following:
Add this in your AppDelegate , Ideally in applicationDidEnterBackground:
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
And this in applicationDidBecomeActive:
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
Recieve remote notifcations by adding this in AppDelagate. This will listen all actions when phone is locked.
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
if (event.type == UIEventTypeRemoteControl){
// Call method of your player where you want to make change (Pause , Paly),
// I am calling a shared view for example, Its up to your logic how you want to deal it
[[AudioPlayerView sharedPlayerView] remoteControlReceivedWithEvent:event];
}
}
And in that get your desired event and update state accordingly
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
if (event.type == UIEventTypeRemoteControl){
switch (event.subtype){
case UIEventSubtypeRemoteControlPlay:
[[MyVideoController instance] play];
break;
case UIEventSubtypeRemoteControlPause:
[[MyVideoController instance] pause];
break;
case UIEventSubtypeRemoteControlTogglePlayPause:
// Check if state is playing , call pause else call play
break;
}
default:
break;
}
}
}
In iOS 7.1 and later, use the shared MPRemoteCommandCenter object to register for remote control events. You do not need to call this method when using the shared command center object.
This method starts the delivery of remote control events using the responder chain. Remote-control events originate as commands issued by headsets and external accessories that are intended to control multimedia presented by an app. To stop the reception of remote-control events, you must call endReceivingRemoteControlEvents().
Add this following code for in didfinishlunching for init audio season and get remote control event :
// 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];
}
for reciving commadn use this code :
- (void)remoteControlReceivedWithEvent:(UIEvent *)receivedEvent {
if (receivedEvent.type == UIEventTypeRemoteControl) {
switch (receivedEvent.subtype) {
case UIEventSubtypeRemoteControlPreviousTrack:
break;
case UIEventSubtypeRemoteControlNextTrack:
break;
case UIEventSubtypeRemoteControlPlay:
[[MyVideoController instance] play];
break;
case UIEventSubtypeRemoteControlPause:
[[MyVideoController instance] pause];
break;
default:
break;
}
}
}
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!
I am playing an MP3 by using AVPlayer. The mp3 is playing in background mode also. I want to access the music from the pull up notification panel like any other media player app does.
It's really easy to use MPNowPlayingInfoCenter, Firstly read here
If you are using backgroundMode you are initiazing a AVAudioSessionso you can just add it to info center.
You can follow this blog
And this is how I did it
MPNowPlayingInfoCenter* mpic = [MPNowPlayingInfoCenter defaultCenter];
NSMutableDictionary *songDictionary = [[NSMutableDictionary alloc] init];
if (songInfo.detail.songTitle) {
[songDictionary setObject:songInfo.detail.songTitle forKey:MPMediaItemPropertyTitle];
} else {
[songDictionary setObject:songInfo.visibleName forKey:MPMediaItemPropertyTitle];
}
if (songInfo.detail.artist) {
[songDictionary setObject:songInfo.detail.artist forKey:MPMediaItemPropertyArtist];
}
if (songInfo.detail.album) {
[songDictionary setObject:songInfo.detail.album forKey:MPMediaItemPropertyAlbumTitle];
}
if (songInfo.detail.duration) {
double durationDouble = CMTimeGetSeconds([APPDELEGATE.session.playerItem duration]);
[songDictionary setObject:[NSNumber numberWithDouble:durationDouble] forKey:MPMediaItemPropertyPlaybackDuration];
double playbackDouble = CMTimeGetSeconds([APPDELEGATE.session.playerItem currentTime]);
[songDictionary setObject:[NSNumber numberWithDouble:playbackDouble] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
}
if(mpic) {
[mpic setNowPlayingInfo:songDictionary];
}
I know i am too late to answer on this post but i did not found any solution about this problem when i was searching on it. Check this and just add in your code, your song will be show in notification panel .
//Add these lines where you are initializing your player and creating items for it.
_appdel.player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[_appdel.player currentItem]];
- (void)remoteControlReceivedWithEvent:(UIEvent *)event
{
//if it is a remote control event handle it correctly
if (event.type == UIEventTypeRemoteControl) {
if (event.subtype == UIEventSubtypeRemoteControlPlay)
{
NSLog(#"UIEventSubtypeRemoteControlPlay");
//[[AppMusicPlayer sharedService]playAudio];
[_appdel.player play];
}
else if (event.subtype == UIEventSubtypeRemoteControlPause)
{
NSLog(#"UIEventSubtypeRemoteControlPause");
//[[AppMusicPlayer sharedService]pauseAudio];
[_appdel.player pause];
}
else if (event.subtype == UIEventSubtypeRemoteControlTogglePlayPause)
{
NSLog(#"UIEventSubtypeRemoteControlTogglePlayPause");
}
else if (event.subtype == UIEventSubtypeRemoteControlNextTrack)
{
NSLog(#"UIEventSubtypeRemoteControlToggleNext");
}
else if (event.subtype == UIEventSubtypeRemoteControlPreviousTrack)
{
NSLog(#"UIEventSubtypeRemoteControlPrevious");
}
}
}
its working on my side and Hopefully it will work for you thanks..
How do i pass the song info such as song name and track duration to control center.
Player plays music fine and the play and pause control works fine though.
Playing with apple's music app
Playing with my app with the code below, how to pass song information in order to display it ?
//AppDelegate
-(void)setupAudio
{
// Set AVAudioSession
NSError *sessionError = nil;
[[AVAudioSession sharedInstance] setDelegate:self];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&sessionError];
// Change the default output audio route
UInt32 doChangeDefaultRoute = 1;
AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,
sizeof(doChangeDefaultRoute), &doChangeDefaultRoute);
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
}
//Make sure we can recieve remote control events
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (void)remoteControlReceivedWithEvent:(UIEvent *)event
{
//if it is a remote control event handle it correctly
if (event.type == UIEventTypeRemoteControl) {
if (event.subtype == UIEventSubtypeRemoteControlPlay)
{
NSLog(#"UIEventSubtypeRemoteControlPlay");
[[AppMusicPlayer sharedService]playAudio];
}
else if (event.subtype == UIEventSubtypeRemoteControlPause)
{
NSLog(#"UIEventSubtypeRemoteControlPause");
[[AppMusicPlayer sharedService]pauseAudio];
}
else if (event.subtype == UIEventSubtypeRemoteControlTogglePlayPause)
{
NSLog(#"UIEventSubtypeRemoteControlTogglePlayPause");
}
}
}
AppMusicPlayer.m
+ (id) sharedService
{
static dispatch_once_t _singletonPredicate;
static AppMusicPlayer *_sharedObject = nil;
dispatch_once(&_singletonPredicate, ^{
_sharedObject = [[AppMusicPlayer alloc]init];
});
return _sharedObject;
}
- (id)init
{
self = [super init];
if (self) {
// Work your initialising here as you normally would
}
return self;
}
- (void)playAudio
{
[self.audioPlayer play];
}
- (void)pauseAudio
{
NSLog(#"pause");
[self.audioPlayer pause];
}
- (void)playAudioFromURL:(NSURL *)songURL
{
[self.audioPlayer stop];
//Declare the audio file location and settup the player
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:songURL error:&error];
[self.audioPlayer setNumberOfLoops:-1];
if (error)
{
NSLog(#"%#", [error localizedDescription]);
}
else
{
//Load the audio into memory
[self.audioPlayer prepareToPlay];
[self.audioPlayer play];
}
}
-(void)setUpRemoteControl
{
NSDictionary *nowPlaying = #{MPMediaItemPropertyArtist: songItem.artistName,
MPMediaItemPropertyAlbumTitle: songItem.albumTitle,
MPMediaItemPropertyPlaybackDuration:songItem.playbackDuration,
MPNowPlayingInfoPropertyPlaybackRate:#1.0f,
MPMediaItemPropertyArtwork:[songMedia valueForProperty:MPMediaItemPropertyArtwork]
};
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:nowPlaying];
}
Are you playing songs from iPods music library ?
If yes than You should you MPMusicPlayerViewController, it provides in-build functionality for seek bar properties as well as Info center.
I can see here in your code you have used AVAudioPlayer,
We can set only below details using AVAudioPlayer class, but can't access seekbar change event in our app.
NSMutableDictionary *albumInfo = [[NSMutableDictionary alloc] init];
UIImage *artWork = [UIImage imageNamed:album.imageUrl];
[albumInfo setObject:album.title forKey:MPMediaItemPropertyTitle];
[albumInfo setObject:album.auther forKey:MPMediaItemPropertyArtist];
[albumInfo setObject:album.title forKey:MPMediaItemPropertyAlbumTitle];
[albumInfo setObject:artworkP forKey:MPMediaItemPropertyArtwork];
[albumInfo setObject:album.playrDur forKey:MPMediaItemPropertyPlaybackDuration]
[albumInfo setObject:album.elapsedTime forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime]
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:albumInfo]
Here we need to count album.playrDur and album.elapsedTime as per required format.
You are looking for this:
- (IBAction)playButtonTouched:(id)sender {
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];
}
}
I happen to be working on the same thing today and don't know the answer, but in my app the Control Center does show the app name. I want to be able to show the title of the thing I'm playing. I even have a picture I'd like to show, like an album cover. I don't think I'm doing anything different than you, I didn't code anything to send it the app name, for example.
Wait a second... I see there's something called MPNowPlayingInfoCenter that we should look into..
Not sure but may be this code help you little bit..
- (void) handle_NowPlayingItemChanged: (id) notification
{
MPMediaItem *currentItem = [musicPlayer nowPlayingItem];
NSString *titleString = [currentItem valueForProperty:MPMediaItemPropertyTitle];
if (titleString)
{
titleLabel.text = [NSString stringWithFormat:#"Title: %#",titleString];
}
else
{
titleLabel.text = #"Title: Unknown title";
}
}