Implement Apple Music in an iOS app

    Today, our partners - the developers of Music Paradise - have prepared new material for readers of our blog. This time, the guys will talk in detail about the integration of Apple Music in their own application. A similar experience has already been described on Habré , however, the article by the Music Paradise developers is designed not only to acquaint readers with this process, but to talk in detail about it and about some important, but not obvious points when working with Apple Music.

    “With the release of iOS 9.3, the apple corporation has made it possible to use its Apple Music service to play music. We decided to try out this opportunity in working on our Music Paradise Player application.. The experience was very instructive - some pitfalls and weaknesses were discovered in the system, which are useful to know in advance. In this article we will try to briefly outline the main points of working with Apple Music, as well as some features of this system.


    Check access to Apple Music


    Apple Music support for developers is available in the SDK starting from version 9.3, so if your application was developed for earlier versions of iOS, you should handle this exception.

    The next step on how to find out whether Apple Music can be played is an authorization request to SKCloudServiceController:

    [SKCloudServiceController requestAuthorization:^(SKCloudServiceAuthorizationStatus status) {
        //Обрабатываем полученный статус
    }];

    Several values ​​can come as a status:

    • SKCloudServiceAuthorizationStatusAuthorized - everything is fine. This is our target status; in any other case, playing music in full will not work;
    • SKCloudServiceAuthorizationStatusDenied - the user has denied the application access to the device’s library, we will not be able to advance further. A good way out in this situation is to offer the user to go to the settings and provide access manually;
    • SKCloudServiceAuthorizationStatusRestricted is the same disappointing result, with the only difference being that access is not possible due to circumstances beyond the control of the user.

    Note that in this case, we cannot receive the status of SKCloudServiceAuthorizationStatusNotDetermined, since the user will have to select an answer in the pop-up window to continue working. Accordingly, processing this option does not make sense.

    Now that we’ve figured out access to the user's library, you need to check if he has a subscription to Apple Music:

    SKCloudServiceController *controller = [[SKCloudServiceController alloc] init];
    [controller requestCapabilitiesWithCompletionHandler:^(SKCloudServiceCapability capabilities, NSError * _Nullable error) {
        //Обрабатываем полученный ответ
    }]; 

    There are also many options for statuses, however, only two will be acceptable for us:

    • SKCloudServiceCapabilityMusicCatalogPlayback - the user can play music from Apple Music, iCloud music library is turned off.
    • SKCloudServiceCapabilityAddToCloudMusicLibrary - the user can play music from Apple Music, iCloud Library is turned on.

    If desired, you can also process the unsuccessful SKCloudServiceCapabilityNone (the user does not have a subscription to Apple Music) - that is, invite the user to subscribe.



    Track List Request


    Search and output of the top tracks is a very mixed process for those who have never encountered the iTunes Search API. For clarity, we break it into several points:

    Keyword Search


    The general view of the request is as follows:

    itunes.apple.com/search?term=%@&limit=%ld&s=%@&entity=song&explicit=No

    Let's analyze each parameter:

    Term - our search query. Keep in mind: if it consists of several words, you need to replace the spaces with + (perhaps this will be obvious to many, but worth specifying).

    Limit - the maximum number of results. Everything is intuitive here. The default value is 50, but in some cases this may not be enough.

    S(Apple’s good work, everything is immediately clear by name) - this search argument is required, it indicates the country of the App Store to which the user account is linked. The fact is that for different countries in Apple Music presents various compositions. In addition, the same track may have different identifiers in different countries.

    To get this identifier for a specific user, we use:

    SKCloudServiceController *controller = [[SKCloudServiceController alloc] init];
    [controller requestStorefrontIdentifierWithCompletionHandler:^(NSString * _Nullable storefrontIdentifier, NSError * _Nullable error) {
        if(!error)
        {
            storeID = storefrontIdentifier; //Идентификатор
        }
    }];

    Entity is a necessary entity, in our case it is a song.

    Explicit - Determines whether to include content with profanity in the search results. First of all, it is worth starting from age restrictions in your application.

    More information on using search can be found here .

    Getting Top Charts


    To get top charts, use the RSS feed generator from Apple . At the exit from the generator we get a url of this type:

    itunes.apple.com/ru/rss/topsongs/limit=100/xml

    where the top tracks for Russia are displayed in the amount of 100 pieces in xml format. In my opinion, this result does not suit us for several reasons.

    Firstly, it is necessary to change the country, as our offer is available on the market and for foreign consumers. So, we need to substitute the identifier of the current country of the user instead of ru.

    To get the identifier, we used a little trick. Since IAPs are provided in the application, we take any SKProduct and do the following:

    SKProduct *product = //Любой IAP из приложения
    NSLocale* storeLocale = product.priceLocale;
    NSString *storeCountry = (NSString*)CFLocaleGetValue((CFLocaleRef)storeLocale, kCFLocaleCountryCode);

    Accordingly, we substitute storeCountry instead of ru in our URL.

    And there is another point that does not suit us - this is the format of the data received. But here everything is simple: we change xml to json at the end of the line, as a result we get a URL of this type for the correct upload of top charts:

    itunes.apple.com/%@/rss/topsongs/limit=100/json



    How to get great covers from iTunes search api


    Another problem that we encountered when adding iTunes search to our application was that the API returns us the cover art of tracks no larger than 100x100. However, there are tricks. Although the link to the image in high quality is not provided in the resulting json, we can take it using the following algorithm:

    1. We take the link to the image from json, which is located by the key "artworkUrl100";
    2. Replace in the resulting line 100x100 with 600x600;
    3. We get a link to a large image.


    Play tracks from Apple Music


    No matter how strange it may sound after all the preparations, this step is the easiest in the whole process of adding Apple Music to the application. All we need is to initialize the player and give it a list of playback tracks. The list of playback tracks is set in the format of an array containing strings with track identifiers. As a code, it looks like this:

    -(void)playQuery:(NSArray*)query
    {
        self.player = [MPMusicPlayerController applicationQueuePlayer];
        [self.player setQueueWithStoreIDs:query];
        [self.player play];
    }

    It is worth recalling once again that the function we are interested in working with Apple Music:
    setQueueWithStoreIDs: appeared in the SDK starting with iOS 9.3, until that moment we could only use MPMusicPlayerController to play the existing iTunes library user.

    If we talk about the difficulties that we encountered in studying the functionality, the memory comes from the fact that after processing the jsones that came from the search api, the dictionaries contained digital values, not string values. This must be monitored.

    It is also worth mentioning that in the example we use applicationQueuePlayer. It appeared only in iOS 10.3, but now it seems to us to be a better solution compared to applicationMusicPlayer, which crashes when working with multiple tracks and when remotely controlled (for example, on a locked screen or from headphones), as well as systemMusicPlayer, which the fact is in no way connected with the application and can continue to play even after the user has logged out. "

    Also popular now: