Reputation: 4406
I am trying to receive information about the currently played track in a iOS app. This works pretty fine while the iPhone is not connected to an accessory. If I connect it to my car (Opel Astra, iPhone jack), the following code stops to work as described in the documentation:
If you create an iPod music player and the user plays an item from another library using Home Sharing, the value of this property is
nil
.
Code:
// nil while connected to an accessory
MPMediaItem *nowPlayingMediaItem =
[[MPMusicPlayerController iPodMusicPlayer] nowPlayingItem];
// Works while not connected to an accessory
NSString *title = [nowPlayingMediaItem valueForProperty:MPMediaItemPropertyTitle];
I even tried "hacky" stuff like to access "private" properties (original code):
MPMediaQuery *query=nil;
MPMediaItemCollection *collection=nil;
id internalPlayer=nil;
Ivar internalPlayeriVar = object_getInstanceVariable(iPod, "_internal", NULL);
internalPlayer = object_getIvar(iPod, internalPlayeriVar);
NSLog(@"internalPlayer: %@", internalPlayer);
Ivar queryIvar = object_getInstanceVariable(internalPlayer, "_query", NULL);
query = object_getIvar(internalPlayer, queryIvar); // nil everytime
Ivar collectionIvar = object_getInstanceVariable(internalPlayer,
"_itemCollection", NULL);
collection = object_getIvar(internalPlayer, collectionIvar); // nil everytime
or to call private methods:
// Same behaviour like [iPod nowPlayingItem], works
// only while no accessory is connected
MPMediaItem *nowPlayingMediaItem =
[iPod nowPlayingItemAtIndex:[iPod indexOfNowPlayingItem]];
// Works while not connected to an accessory
NSString *title = [nowPlayingMediaItem valueForProperty:MPMediaItemPropertyTitle];
Its also no solution to access the new MPNowPlayingInfoCenter
, its nil
all the time.
[MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo
My car plays my music directly without using a iPhone app and it seems my iPhone knows what the car is currently playing because it displays the title, artist and cover icon on the lock screen (and only there). Also the internal play count gets increased.
If I check the playback state, it returns also YES
if the car plays music:
[[MPMusicPlayerController iPodMusicPlayer] playbackState] == MPMusicPlaybackStatePlaying
So, is there any way (may be through calling private methods) to access the song, the car is currently playing?
Upvotes: 22
Views: 6554
Reputation: 4406
Apple just "fixed that" in iOS 6.1 after I reported it as a bug. The following code now works while my iPhone is connected to my car:
MPMediaItem *nowPlayingMediaItem = [iPod nowPlayingItem];
NSString *title = [nowPlayingMediaItem valueForProperty:MPMediaItemPropertyTitle];
NSLog(@"Playing title: %@", title);
And, what I really like: It is also possible to change the playing track using the iPod app - the app appears as you expect it, instead of the big white "connected to an accessory" screen. So this may also work programatically.
Upvotes: 2
Reputation: 1
Actually you won't get any MPMediaItem because your iPhone isn't playing the songs but your car's accessory connected to the iPhone is accessing the media library. In doing so, it is responsible to update all the metadata of the accessed objects (songs), especially incrementing the playcount and updating the last accessed date of the song. It also stores some information of where in the song it is (position) in the iTunes library.
This information is read by the lock screen to update the cover. This is also what helps the iPod app to continue where your car's accessory left.
So tap into the library and get the latest information from there. Have a look at the TopSongs example project to get started.
Upvotes: 0
Reputation: 11865
Are you using threads? If so run the code on the main thread. If not then register for the MPMusicPlayerController notifications for item change. That way when the song changes your app will know what the new song is. Also be sure this runs on the main thread as well.
If your playback state is updating while connected but your nowPlayingItem isn't, this would confirm it is a bug. I would submit a bug report for this issue.
EDIT: Visit https://developer.apple.com/support/resources/bug-reporting.html and scroll to the bottom. The last question says you can contact TSI for bug work arounds. You get 2 TSI requests for being a developer for free so you can use one of those to ask them if they have a work around using a private library until the bug is fixed.
Upvotes: 2
Reputation: 4503
I am pretty sure the answer is no, you can't with any public api's at least but you should file a bug with apple for two reasons:
The reason MPNowPlayingInfoCenter does not give you the info is because it has to be specifically implemented by the app playing the music, if apple's app playing then it should have been implemented so file a bug.
Now if you say [[MPMusicPlayerController iPodMusicPlayer] playbackState] reflects playback changes then that would mean iPodMusicPlayer is still the app in charge of playback so giving you nil for MPMediaItemPropertyTitle should also be reported to apple as a bug.
Additionally non public information on the topic is likely covered by the MFi NDA and nobody is going to risk his ass.
Upvotes: 0