valbu17
valbu17

Reputation: 4124

Detect currently playing song information in native iOS Music App

I'm having a some issues to get the current playing song information like (title, artist...) in the native iOS Music App.

This is the exact problem, my app is using a MPMusicPlayerController with iPodMusicPlayer this property is call myPlayer. When the user is controlling the music within my app I'm able to display the current song playing information in this way...

- (void)getTrackDescription {

    // getting whats currently playing
    self.nowPlayingItem = [myPlayer nowPlayingItem];

    // song title currently playing
    self.title = [self.nowPlayingItem valueForProperty:MPMediaItemPropertyTitle];

    // if title is not fund Unknown will be displayed
    if (title == (id)[NSNull null] || title.length == 0) {
        title = @"Unknown";
    }

    // artist currently playing
    self.artist = [self.nowPlayingItem valueForProperty:MPMediaItemPropertyArtist];

    // if artist is not fund Unknown will be displayed
    if (artist == (id)[NSNull null] || artist.length == 0) {
        artist = @"Unknown";
    }

    //[self.currentlyPlaying setLineBreakMode:NSLineBreakByWordWrapping];

    // displaying current artist and title song playing
    [self.currentlyPlaying setText:[NSString stringWithFormat:@"%@ - %@", artist, title]];
}

But, the problem comes when the user leave the app in the background or just use the Control Center to change the song.. My app still displays the previous song information and nothing gets update if the user continues using Control Center or the Music app itself.

I tried to solve the problem in this way...

- (void)viewDidLoad {
    [super viewDidLoad];

    if (self.myPlayer.playbackState == MPMusicPlaybackStatePlaying || self.myPlayer.playbackState == MPMusicPlaybackStateSeekingForward || self.myPlayer.playbackState == MPMusicPlaybackStateSeekingBackward){
        // updating track name regardless the user uses app controllers or not
        [self getTrackDescription];
    } 
}

I even tried commenting the if condition to see if I get the song information in that way but it was the same problem.

Well, I hope someone can help me out and explain what I'm doing wrong..

Thanks in advance...!

UPDATE

This what I have at the moment... My getTrackDescription logic is the same but the signature changed to this - (void)getTrackDescription:(id)notification

- (void)viewWillAppear:(BOOL)animated{

    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];

    [notificationCenter addObserver:self
                           selector:@selector(getTrackDescription:)
                               name:MPMusicPlayerControllerPlaybackStateDidChangeNotification
                             object:self.myPlayer];
    [self.myPlayer beginGeneratingPlaybackNotifications];

}

-(void)viewWillDisappear:(BOOL)animated{

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                               name:MPMusicPlayerControllerPlaybackStateDidChangeNotification
                                               object:self.myPlayer];
    [self.myPlayer endGeneratingPlaybackNotifications];
}

Upvotes: 1

Views: 2834

Answers (2)

valbu17
valbu17

Reputation: 4124

This is my complete answer to the problem..

1) I set these two methods.. and set an Observer MPMusicPlayerControllerNowPlayingItemDidChangeNotification which will take care of updating my song information regardless.. with getTrackDescription which still the same as my previous post..

- (void)viewWillAppear:(BOOL)animated{

    // creating simple audio player
    self.myPlayer = [MPMusicPlayerController iPodMusicPlayer];

    // assing a playback queue containing all media items on the device
    [self.myPlayer setQueueWithQuery:[MPMediaQuery songsQuery]];

    self.notificationCenter = [NSNotificationCenter defaultCenter];

    [self.notificationCenter addObserver:self
                                selector:@selector(getTrackDescription:)
                                    name:MPMusicPlayerControllerNowPlayingItemDidChangeNotification
                                    object:self.myPlayer];

    [self.notificationCenter addObserver:self
                                selector:@selector(handle_PlayBackNotification:)
                                    name:MPMusicPlayerControllerPlaybackStateDidChangeNotification
                                    object:self.myPlayer];


    [self.myPlayer beginGeneratingPlaybackNotifications];

}

-(void)viewWillDisappear:(BOOL)animated {

    [self.notificationCenter removeObserver:self
                                name:MPMusicPlayerControllerNowPlayingItemDidChangeNotification
                                object:self.myPlayer];

    [self.notificationCenter removeObserver:self
                                    name:MPMusicPlayerControllerPlaybackStateDidChangeNotification
                                    object:self.myPlayer];

    [self.myPlayer endGeneratingPlaybackNotifications];

}

Then the magic will happen by itself.. it just basically what @0x7fffffff recommended me to do but I had to do some digging because I wasn't familiar with notifications at all..

So, just in case if you want to see how I toggle my play/pause button for the Observer MPMusicPlayerControllerPlaybackStateDidChangeNotification this is how I did it..

- (void)handle_PlayBackNotification:(id)notification{

    if(myPlayer.playbackState == 1){

        // sets the pause image in play button
        [self.pauseBtn setBackgroundImage:[UIImage imageNamed:@"pauseBtn2.png"] forState:(UIControlStateNormal)];

    } else {

        // resets the image to normal play image
        [self.pauseBtn setBackgroundImage: nil forState:(UIControlStateNormal)];


    }

}

just in case this my getTrackDescription ...

- (void)getTrackDescription:(id)notification {

    // getting whats currently playing
    self.nowPlayingItem = self.myPlayer.nowPlayingItem;

    // song title currently playing
    self.title = [self.nowPlayingItem valueForProperty:MPMediaItemPropertyTitle];

    // if title is not fund Unknown will be displayed
    if (title == (id)[NSNull null] || title.length == 0) {
        title = @"Unknown";
    }

    // artist currently playing
    self.artist = [self.nowPlayingItem valueForProperty:MPMediaItemPropertyArtist];

    // if artist is not fund Unknown will be displayed
    if (artist == (id)[NSNull null] || artist.length == 0) {
        artist = @"Unknown";
    }

    // displaying current artist and title song playing
    [self.currentlyPlaying setText:[NSString stringWithFormat:@"%@ - %@", artist, title]];

}

Upvotes: 0

Mick MacCallum
Mick MacCallum

Reputation: 130222

What you're going to want to do is add your view controller as an observer to the MPMusicPlayerControllerNowPlayingItemDidChangeNotification notification, which as it sounds, gets called every time the track changes in the music player. Don't forget to specify when the player should begin/end generating these notifications with the following methods.

[[MPMusicPlayerController iPodMusicPlayer] beginGeneratingPlaybackNotifications];
[[MPMusicPlayerController iPodMusicPlayer] endGeneratingPlaybackNotifications];

Upvotes: 3

Related Questions