30

I have an app that uses the iPod Library API to access the song database in iOS. With the release of iTunes Match, any song which is not on the device will fail to load. Is there a way I an request that the song be downloaded? Perhaps using the new iCloud API?

Edit: To be clear I am not asking how to download songs with iTunes Match using the iPhone. The iOS SDK allows access to the iPod Library via the MPMediaQuery/MPMediaItems. On a iOS device with iTunes Match enabled songs which are in your iTunes Match library but not local on the device are returned via a MPMediaQuery however the MPMediaItems have their 'exportable' flag set to false. When I access these songs in the Music app they are automatically downloaded. I would like to trigger the same automatic download via the MPMediaItem.

I have seen items in iTunes Match refereed to as part of iCloud and there is a new iCloud section of the iOS 5 SDK. However as I understand it I can only get data my app as uploaded. I was hoping there was a way via the MPMediaItem or using the URL via iCloud to trigger an iTunes Match download.

TurqMage
  • 3,321
  • 2
  • 31
  • 52
  • This question might be better suited for Apple.SE – JW8 Nov 16 '11 at 07:09
  • 1
    Isn't the Apple.SE more for using the device and not for coding on on the device? – TurqMage Nov 16 '11 at 17:37
  • could you clarify what you mean by "their 'exportable' flag"? I'm not aware of an exportable property. Are you referring to MPMediaItemPropertyAssetURL? – prendio2 Nov 28 '11 at 09:29
  • 1
    Yes that was rather unclear... Using MPMediaItemPropertyAssestURL, getting an AVAsset then the AVAsset's .exportable property. – TurqMage Nov 28 '11 at 17:33
  • 2
    Querying MPMediaItemPropertyAssetURL returns a nil NSURL when the song is not in your library yet, so [AVAsset assetWithURL:url] returns nil, instead of an AVAsset. – carlos May 26 '12 at 23:19

4 Answers4

15

I have found something, but it isn't great. If you select the song to be played through the iPod player then that will trigger a download. You can access the iPod player with an MPMusicPlayerController.

MPMusicPlayerController *mDRMAudioPlayer;
mDRMAudioPlayer = [MPMusicPlayerController iPodMusicPlayer];

MPMediaQuery *assetQuery = [[MPMediaQuery alloc] init];
NSNumber *persistentID = [mediaItem valueForProperty: MPMediaItemPropertyPersistentID];
MPMediaPropertyPredicate *predicate = [MPMediaPropertyPredicate predicateWithValue: persistentID 
                                                                       forProperty: MPMediaItemPropertyPersistentID];
[assetQuery addFilterPredicate: predicate];

[mDRMAudioPlayer setQueueWithQuery: assetQuery];
[mDRMAudioPlayer play];

No feedback on if this really started a download or not, or progress on the download but the item will start downloading and if your connection is good it will play the first time (otherwise you can spam play and it will get around to starting).

Akhrameev
  • 325
  • 4
  • 12
TurqMage
  • 3,321
  • 2
  • 31
  • 52
  • iPodMusicPlayer is deprecated. Rather we could use systemMusicPlayer. – Abdul Yasin Jul 11 '17 at 07:25
  • As of 2019 this solution doesn't seem to work anmyore. The song is played but now downloaded. You can verify this if you go into the music app. The download icon is still there. The only way to download it is to actually tap the download icon in the music app. This sucks… – Swissdude Jul 28 '19 at 19:39
7

MPMediaItem | iCloud or DRM Protected

The link above shows how you can use a property introduced in iOS 6 to see if an MPMediaItem is in the cloud.

MPMediaItemPropertyIsCloudItem

BOOL isCloud = FALSE;

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")) {
    NSNumber *isCloudNumber = [mediaItem valueForProperty:MPMediaItemPropertyIsCloudItem];
    isCloud = [isCloudNumber boolValue];
}
if (isCloud) {
    DebugLog(@"Cloud Asset URL: %@", assetURL);
}

That is using a macro to ensure only iOS 6 uses that code which was added with iOS 6. Below is that macro.

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

Still you cannot initiate a download as far as I can tell.

Community
  • 1
  • 1
Brennan
  • 11,546
  • 16
  • 64
  • 86
7

I just heard back from Apple regarding this issue (I used one of my Technical Support Incidents).

According to Apple, the iOS SDK does not currently provide any APIs for initiating a download from iCloud. I was instructed to file an enhancement request for this feature via Apple's bug reporter tool. I would encourage others to do the same.

Apple really should provide programmatic support for downloading audio assets from iCloud considering that iCloud is one of the defining features of iOS 5.

  • 2
    I've also posted a bug report for it (#12736293), with the following description: `There is no API in the iOS SDK to determine whether a track is available locally vs. on iCloud (in iTunes Match), nor is there any API to track its download status. There is no way to distinguish between tracks that are available locally vs. those that are only available via iCloud, and if you start to play a media item that requires downloading, there is no way to monitor the download progress (started, failed, in-progress, complete)` – cleverbit Nov 21 '12 at 11:41
  • 1
    Any progress on your report? (Hello from 2015, the problem still seems to be in place) – mojuba Sep 22 '15 at 15:19
  • Hello from 2019, still nothing changed... – Klaas Jun 13 '19 at 14:38
3

Here's something to watch out for. My app does an ordinary [MPMediaQuery albumsQuery] to gather all albums and their songs. This works fine even if the whole music library consists of iTunes Match stuff most of which is still in the cloud. But there's one problem:

If a song is being played at that moment, and if that song was in the cloud, so that now it is being downloaded, that song and the next song in the album are missing from the result of [MPMediaQuery albumsQuery]. This is presumably because those songs are "in transit": they are both partially downloaded. (I presume two songs are always downloaded so that when the first finishes it is possible to segue seamlessly into the next.)

Moreover, playing and therefore downloading a song triggers an MPMediaLibraryDidChangeNotification even though the "table of contents" of the library has not in fact changed.

I don't see any way around this, since there's no other way to query the library. Apple needs to fix the system and the APIs to take account of iTunes Match's existence. Unfortunately I am not getting a sense that they are working on this for iOS 5.1...

matt
  • 515,959
  • 87
  • 875
  • 1,141