Introducing MusicKit

Session 502 WWDC 2017

Get introduced to the new API for the Apple Music subscription service. Learn how to add Apple Music playback in your own app, and discover how to search the catalogue, manage playback queues, and engage with playlists and recommendations.

Hi.

[ Applause ]

We love music at Apple.

As Tim said yesterday in the keynote, it's a fundamental part of our DNA.

My name is Tim, and I'm here today to introduce you to MusicKit, a way for you to integrate streaming music with Apple Music content.

With MusicKit, you're going to get access to artists, albums and songs, playlists, activities and curators.

We also provide operations for discovery, like search, and charts, and if the user authorizes your app, personalized recommendations that are tailored to the user's taste or their activity.

MusicKit is two things; it's a collection of client APIs in the iOS SDK and a set of web services that provide personalized and cataloged content.

I'll be talking about the web services part, which we call Apple Music API.

These are some of the topics I'll be discussing.

I'll go a little into how to format a request, how we represent the content with resources and relationships, some detail about limits and pagination.

My colleague Joel will give a brief demo.

I'll touch on personalized services; and finally, talk about how to get access to the Apple Music API.

No talk about a Web services API would be complete without talking about the URL structure.

Apple Music API only supports the secure HTTPS scheme, and it's hosted at api.music.apple.com.

The first element in the URL path is the version.

Current version is V1, and if we make significant improvements or backwards incompatible changes, we'll bump the version.

The next part of the path is cataloged, and this just indicates that this is the Apple Music streaming content catalog.

A note that not all content is available in every area or region of the world, and so we introduced the concept of Storefront in the path.

Storefront scopes the catalog to the area region where content is available so that you can provide relevant and playable music to your users.

The next part is the API.

This just indicates the resource you'd like to request or the operations you'd like to perform.

And finally, we have a set of parameters that you can use to filter or expand the request.

Our API is localized.

We support many localizations, but not all localizations are supported in every Storefront.

We provide a mechanism for you to get which Storefront supports which localizations.

The API supports limits in pagination, and I'll go into some detail later in my presentation about exactly how that works.

And finally, every request to Apple Music API requires a developer token.

Representing data is an important consideration for any API.

We've taken our experience building the Apple Music app to give you an API that takes into consideration ease of use, flexibility, and performance.

Here, I have the first representation of a resource, which we call the identity form.

It includes an ID, a type of thing that this is, and an href, which indicates the location in the catalog where you can find this content.

This isn't very useful for display.

That's why we have this type, which is the attributes form.

This includes the identity and a list of attributes that you can use to display relevant information about the content.

This includes things like artwork and name and description, and if the content is playable, it will have an attribute called play parameters.

Finally, we have the default form.

If you ask the Apple Music API for a collection of things, this is the default form that you'll get.

It's the attributes and relationship form.

This is all of the attributes required for display plus collections of content that are related to this particular resource.

It's a little bit about relationships.

Here I have an album resource.

It has three relationships.

The first is a relationship to tracks.

This is the songs or music videos that are attached to this album.

The second is artists, which, of course, is the artist that created the song or the album; and genres.

Genres are just the category of music that this album belongs in.

Now, each of these relationships is of a different type.

The first app for tracks is an attributes included relation.

It means if you ask for this album, it's going to return all of its tracks with their attributes included.

This means that if you ask for an album, you could get all of the data about the songs and its attributes.

The second type, artist, is identifiers only.

It means we only return the identifier form, the location, and the kind of thing, and where you can find it in the catalog.

And finally, we have the omitted by default.

This is not returned in the default representation, although the relationship still exists.

So, let's look at this in practice.

Here, I have a URL to an album, and you can see that in the adjacent response tracks have attributes omitted, and artists are the identifier form.

So, what if I wanted to make a single call and get the attributes for an artist.

I'd simply add the career parameter, include and specify the name of the relationship, which I would like to omit the attributes for.

And you can see that here we have omitted the attributes for the artist, along with the attribute form for the tracks.

You'll notice in this response that we don't include genres.

So, how would you include the attribute form of genres?

You'd simply add genres to the include career parameter, and you can see that genres will be omitted in the attribute form.

So, that's a little bit about resources and relationships.

I'm now going to talk about some limits and pagination.

So, here are the requests for the tracks resource for an album.

This will give me the collection of songs for this album.

This album happens to have 9.

If I wanted to limit the number of tracks that I would get back, I would simply add the limit career parameter, and let's say I wanted a page size of 2.

This would give me the first two songs in this album, and then it would give me a Next key that indicates where the rest of these tracks live.

If I follow this next link, I will get the rest of the tracks for this album, songs 3 through 9.

If I wanted to implement a page size of 2, I would simply add, again, limit equals 2.

It would give me songs 3 and 4.

Again, a Next reference, with a URL to where the rest of the data for this album lives.

So, what does this look like in practice?

Here it is.

You can see that the Next reference is a sibling of the collection of data that comes back for these tracks.

So, I've talked a little bit about resources, the relationships, and pagination.

Let's talk about an operation.

Most of our operations come back as collections of resources grouped by the type of thing that they are.

For example, a search for Khalid would bring back albums, artists, songs, and playlists.

If I wanted to limit the type of things that came back from a search, I would simply add the "types" career parameter and specify the kind of thing that I would like to come back.

Here, I'm asking for albums, and when I call it, I'll just get a collection of albums.

And now, I'd like to welcome my colleague Joel onto the stage to do a quick Playground demo of a Search request.

[ Applause ]

Thank you, Tim.

Hi, my name is Joel, and I'd like to show you just how easy it is to fetch content from Apple Music to enrich your apps in Swift.

To do that, I'd like to show you how to fetch some content from this catalog search endpoint, and here we'll be searching for albums from Khalid.

To do so, we'll simply start building the URL for this search request, using URL components, and one important part of this URL in the path is the inclusion of the Storefront county code corresponding to the user.

Then, you need to add a few query parameters to this request, and we'll do so by using query items, and we'll simply set the term to "Kahalid" and type 2 albums.

Once you have that, you can construct a fully formed URL, and then a URL request with that.

And then, you need to include an HTTP header to this URL request, which is the authorization header, and this is useful to authenticate your app with Apple Music API.

Here, we'll be using the developer token as a part of the value of this HTTP header with the "Bearer" prefix.

Next stop, we can load the data, using URL session, and with this raw JSON data, we'll simply use the new JSON Decoder in Swift 4.0 to parse this data, and it really makes it easy to convert JSON data into strongly typed Swift structures.

You can simply define a few Swift structures that conform to the codable protocol, and then you can feed such structures to the JSON decoder.

In this case, I'll be passing the Catalog Search Results struct to the JSON Decoder, along with the Search data, and then I can take a peek into the results.

So, here, I'll be looking for the first album in these results, and let's take a look at the attributes we get.

Sure enough, we get the American Teen Album by Khalid, including the other related attributes.

And as you can see, we also have some information about the artwork, and this comes with a URL.

But if you really take a look at this URL, it's more of a URL format string because it allows you to replace a width and height token at the end of the URL with the desired width and height to match the user end face in your app.

So, to fetch the artwork for this album, I just created the Helper method on this artwork structure, and it's really simple.

We'll just replace the width token, w with the desired width here, and then we'll do the same for the height.

And because most artwork for music content is perfectly square, we'll simply use the same width in height.

And with that, you have a fully formed URL.

So, here, I just constructed a URL for this album that has a width of 1200 pixels, and let's just take a look at what we get.

Here it is.

This is the album artwork for this American Teen album by Khalid.

So, this is how easy it is to fetch content from Apple Music.

Now, I'd like to head it back to Tim, and he'll tell you all about personalized requests.

Thank you.

[ Applause ]

Thanks, Joel.

So, I'm going to talk a little bit about personalized requests with the Apple Music API.

The URL structure is just a little bit different.

After the Version, you'll see that every personalized call starts with me.

Here, I have a URL that will give me the recently played items for a user's account.

So, you'll also notice that the Storefront part of the path is missing.

That's because a user's account is bound to the Storefront, so they can only play content that is available in the Storefront, which their account is legitimately available for.

So, what do you need to play?

What do you need to get personalized data?

The user must have an Apple Music subscription, and every call to a personalized request requires two things, the developer token, and a Music User token, which Joel will show you how to get in the latter half of the presentation.

Now, how do I get access to the API?

One, you have to be a member of the Apple Developer Program.

Second thing you need is a MusicKit private key.

You can find a MusicKit private key in the Accounts section of the Apple Developer Portal in the Certificates and Identities area.

Once you have the Music private key, you can use that to sign the Developer token.

The Developer token is in JSON Web Token format, much like the APNS token, and it's required, as I mentioned previously, in the authorization header for every Apple Music API request.

Just one note about security, keep you MusicKit private key secure.

Don't embed it in the binaries of your application.

What we recommend is that you dynamically generate your developer tokens, preferably on a server that's within your control and that you have authorization access for.

Some notes about the format of a Developer token.

Developer token has two parts, required headers, which are the encryption algorithm.

We only support, ES256 is ou encryption algorithm, and the key identifier.

When you download your MusicKit private key, you can find this as part of that download.

The second half is the required claims.

We have three required claims, an Issuer ID, which is the Team ID, and you can find this in the Membership section of the Apple Developer portal.

We have an issue at time for this Developer token, which is in UNIX format; and finally, you have an expiration.

Tokens can only be generated that expire 6 months from now.

So, with that, I'm going to turn over the rest of the presentation to my colleague, Joel, and he'll tell you a little bit about using MusicKit on iOS.

[ Aapplause ]

Thank you.

Thank you, Tim.

Hi again. So, I'd like to tell you all about how you can take full advantage of MusicKit for your iOS apps.

And to do that, first, I will tell you some more about how you can get full access to Apple Music API.

Then, I'll tell you what you're supposed to do if you're faced with a user who doesn't currently have an Apple Music subscription.

And finally, I'll tell you how you can use the iOS SDK to initiate and control playback of subscription and library content.

So, let's talk about getting full access to Apple Music API.

The first thing you might wonder about is authentication, but as it turns out most users are already signed in with an iTune Store account on their iOS device, and for this reason, you really don't need to worry about Prompt User for Credentials.

However, because privacy is such an important concern on iOS, you really need to get the user's informed consent before we grant your app access to Apple Music.

This user consent is very similar to what ou would request before getting access to the user's location or the user's contact information.

This is also something you need to request per application and per iOS device.

So, if your apps, app works on both iPhone and iPad for the same user, make sure to request this user consent separately.

This is what the user consent dialogue looks like in the Nike Plus Run Club app, and it's the standard user consent dialogue for privacy.

And one important part of it is the subtitle where the third party app developer is required to inform the user as to why it requires access to the Apple Music data of the user.

Requesting the user consent is needed to get access to both the device library as well as the music user token.

You can read the current authorization status for your app to see if you've already been granted this user consent, and this will not prompt the user with the dialogue I just showed you.

However, you can more simply request authorization, and this will prompt the user unless your app has already received this authorization.

To do so, you can use a class and distorted framework.

It's called SKCloudServiceController, and you can call a method on it, a class method named Request Authorization.

We'll call your completion handler with a status code, and you know you can proceed to call Apple Music API if you get the authorized status code.

Additionally, you will have to set the NS Apple Music Usage description field in your Info P list to populate the subtitle of the user consent dialogue.

The next important step is to fetch the subscription status.

To determine if the user is actually subscribed to Apple Music, and this is important for issuing personalized requests to get at data such as recently played or heavy rotation, for example.

However, this is not necessarily a simple yes and no type of question.

The subscription status may be complex because while a user may be an Apple Music subscriber because that user may simply pay the monthly fee, it's also possible a user is a subscriber through their carrier.

Additionally, some users can play subscription content for Apple Music, and yet your apps won't be able to add content to those user's music libraries.

And this is because the iCloud Music Library feature has to be enabled separately.

Finally, it's possible you won't be able to suggest to all of your users to become Apple Music subscribers because we don't offer Apple Music in every single country, and even in countries where we do offer Apple Music, there are settings such as education settings or enterprise settings where becoming an Apple Music subscriber is actually restricted.

So, for this reason, we expose three independent capabilities you can query.

The music catalog playback capability, the add to iCloud Music Library capability, and you can also tell if the user can become a subscriber.

So, it's important that you check these individual capabilities in your app before you take an action related to Apple Music.

So, for example, if you want to have a Play button in your app to preview a piece of content from Apple Music, make sure to check the music catalog playback capability.

Conversely, if you want to have an Add button to add a certain song to a playlist from the user's library, make sure that the Add to iCloud Music Library capability is enabled.

Fetching the subscription status information requires the user's consent, and you can do it in code using, again, SKCloudServiceController.

Here, we'll be calling an instance method called Request Capabilities, and we'll call your completion handler with an Option set of capabilities.

You can check inside of that Option set for the presence of the Music Catalog Playback capability to check if the user can play subscription content or for the presence of Add to Cloud Music Library to see if your app can add songs to the Cloud Library of this user.

Next stop, you might need to know the Storefront Country Code.

This is particularly important for requesting content from the catalog end points of the Apple Music API because, as you know, the Storefront Country Code is an important part of the past of those URLs.

To fetch this Storefront Country Code, you'll be able to use another instance method of SKCloudServiceController.

This time it's called Request Storefront Country Code, and we'll invoke your Completion Handler with a two-letter country code, which you can then use to build out the URL for your catalog end point request.

In this case, we're trying to build the top songs URL, and this is the particular line that is relevant where we use the Storefront Country Code in the middle of the path of this URL.

Finally, to unlock the full power of Apple Music API, you will need to get the music user token, which is very important to issue requests for personalized content, such as recently played or heavy rotation.

This is derived from your developer token, and because fetching the music user token is a somewhat expensive operation, we recommend you cache the music user token once you've fetched it.

You can do so using user defaults, for example, but make sure not to transfer the music user token across devices because you might be violating user consent if you do so.

Since you'll be caching this music user token, you should also be aware of when you should invalidate this cache and fetch the music user token again, and this is typically whenever you get a forbidden status code from any of the Apple Music API endpoints; that is the (403) HTTP status code.

This could happen in a number of scenarios, For example, the user might change the password associated with the iTunes store account, or the user might actually decide to revoke the user token associated with your app, or, finally, the user token could expire naturally.

In all of these cases, make sure to refetch the music user token after checking the capabilities again, just in case the active iTunes store account has changed, meanwhile.

So, to fetch the music user token, we'll be using store kits, SKCloudServiceController, once more.

Here, we have another method.

Request user token for developer token.

You'll pass the developer token as a parameter, and then we'll invoke our completion handler and hand you the music user token.

You can then use that to properly populate the relevant HTTP headers in your URL request and specifically the music token HTTP header.

Once you've gotten the User Token and User Consent, you have full access to Apple Music API, so you can proceed to build amazing user experiences for your apps that keep your users engaged.

However, sometimes, you'll be faced with another edge case when a user is not already an Apple Music subscriber.

When that's the case, you might want to show a subscription view to suggest to the user to join Apple Music so they can take part in our trial period, get access to over 40 million songs, and also unlock the full potential of your apps.

Additionally, it's particularly relevant for you as developers because you can get rewarded for bringing in Apple Music subscribers by taking part in our Affiliate Program.

So, when exactly are you supposed to show the Subscription View?

You should do so whenever you detect that the user cannot currently playback subscription content.

But the user can become an Apple Music subscriber.

In terms of the capabilities we discussed previously, that means you need to make sure the music catalog playback capability is currently disabled while the music catalog subscription eligible capability is enabled.

As a side note, in the very rare occurrence that the user doesn't have an active iTunes Store account on this device, you will see that status reported the exact same way, and we will make sure to include a Sign In button as part of the Subscription View.

A subscription view is quite configurable and, namely, you can choose the main message we convey to the user.

By default, we'll tell the user Join Apple Music.

But by passing an optional message identifier, you can choose a more tailored message based on the next action you want to take in your app.

So, we have other values you can choose from for the message identifier, such as Connect, and we'll tell the user connect to Apple Music.

We also have Add Music, and well tell the user add all the music you want.

And we finally have Play Music.

So, make sure to pick the best message identifier that corresponds to the next action you want to take in your app, so we can choose the right message that will make the most sense to the user.

You can also make the subscription view contextual by highlighting a certain piece of content, such as a song, album, playlist, or radio station.

You can do so by passing an iTunes item identifier option which requires a value of tight string, and that corresponds to the ID field of the JSON representation of an Apple Music API resource.

There are a few more options you need to be aware of for this subscription view.

You will have to set the action to subscribe, and you can also pass optional affiliate tokens and campaign tokens if you are taking part in our Affiliate Program.

Putting it all together, this is how you can show the Subscription view.

We'll instantiating a view controller from Store Kits SK CloudServiceSetupViewController, and you can set yourself up as a delegate for this ViewController.

Then, you need to build the list of options we just discussed.

In this case, we will be setting the action to subscribe and the message identifier to play music, and you need to call the load with options method to load all the content of the subscription view.

And this is because it's a server driven view that requires us to load a certain amount of content.

Because this process is asynchronous, we recommend you show a spinner in your app while we're loading this content, and you can do so using UIActivityIndicatorView.

Once we're done loading all the content, we'll invoke the completion handler, and you can proceed to show the subscription view.

If it did succeed Boolean, it's set to true by simply calling the PresentViewController method from UIKit.

And that's how you show the subscription view.

Additionally, if the user decides to become a subscriber as a result of this, you can detect that by observing the capabilities did change notification from SKCloudServiceController, and you can also detect that the subscription view was dismissed using the belated delegate method.

So, with that, you have all the tokens you need to have Apple Music API, fetch Apple Music content, and you made sure the user is a subscriber.

So, we can have some more fun and actually do some playback of subscription or library content.

And to do so, we'll switch gears a little bit and take a look at another framework in the iOS SDK, the MediaPlayer framework.

You'll find the MediaPlayer framework a class named MP MusicPlayer Controller, which offers two distinct players that allow you to control music playback for two different types of use cases.

To highlight that, let's start with an example.

Let's say you're building a social networking app.

You want to make it easy for your users to share music content with their friends, and so it's important that the friend receiving such a piece of content is able to preview that song or album from your app.

However, you should make sure that the friend receiving this piece of content can then benefit from the full feature set of the music app, allowing the friend to go back to the music app and maybe share the song further, using Connect or AirDrop.

For such applications, the system user player might be the right fit.

However, if you need more control over the playback experience, you might want to take a look at the application queue player, and a good example here might be a fitness app.

It's possible you want to have some music playing in the background while your user is running outside, and so you might want to make sure that the music matches the pace of the runner.

You might also want to insert a power song in the middle of the playback queue and have your own customized playback controls.

The application queue player will allow you to do all of those things.

Both of these players will do a lot for you automatically.

They will make sure to populate the control center in lock screen.

However, things will be recorded a bit differently, depending on the player you pick because the music app will be recoded as a Now Playing app with the system music player, whereas it's going to be your app recorded as the Now Playing app if you choose the application queue player.

And this is because with the System Music Player, your app is acting as a simple remote control of the music app.

Whereas if you use the application queue player, your app fully owns the playback queue completely independent from the music app.

Both of these players allow you to control the playback queue with simple operations such as completely replacing the playback queue with a Set Queue command, and you can also use the Up Next functionality by setting content to Play Next or Play Later.

But with the application queue player, you can go one step further by inserting items in the middle of the playback queue over moving items that are already in the playback queue.

To achieve some of those playback queue manipulation tasks, you'll be using a concept we call queue descriptors.

We offer three different types of queue descriptors based on the type of content you're dealing with.

The first one is the media item queue descriptor, and this is useful if you have an instance of MPMediaItem or MPMediaItemCollection, which you would like to start playback with.

And typically, you get a hold of such instances by making device library queries using MPMediaQuery, or by presenting the media picker to allow the user to select a piece of content from his library.

For catalog playback, we also have the store queue descriptor, and here the data you need to use the store queue descriptor is a store ID, and that's a string that corresponds to the ID field of the JSON representation of an Apple Music API resource.

And this is typically useful for catalog content such as from catalog search.

We also have a new queue descriptor, the playback, the play parameter's queue descriptor, and this does everything the store queue descriptor does, in addition to handling personalized content, such as content from recently played or heavy rotation, and it also supports playback of radio stations.

Here, the data you'll need to use for the play parameters queue descriptor is the value associated with the play params field in the JSON representation of an Apple Music API resource.

So, let's take a look at how you can use those queue descriptors to control playback in your apps.

Here, we'll do some simple playback queue manipulation tasks, and we'll choose to use the SystemMusicPlayer.

Both players support simple playback tweaks you can apply to them such as setting the repeat mode to all.

But you can also change the shuffle mode if you like.

The first thing we'll do is change the playback queue, replace it completely with a local album represented with an MPMediaItemCollection.

Because that's the type of data we have, we'll be using the MPMediaItem, I'm sorry, the MediaItemQueueDescriptor.

You can also decide to start playback with the fourth song of the album by setting the start item with the fourth item of the album.

And you can use that to call the setQueue method on the player.

You can also use Up Next to add a song to Play Next using the prepend method on the player.

And here, we're trying to add a catalog song to Play Next.

It's represented with a Store ID, and for this reason, we have to use the store queue descriptor.

But you can also add songs from recently played, for example, to the queue, and they'll typically be represented with play parameters you can find in the JSON representation of Apple Music API resources.

And because that's the data we have, we'll be using the play parameters queue descriptor.

Then, in this case, we'll choose to use it with the append method of the player to add this song to Play Later.

If your app requires more control over the playback queue, however, you can switch to the ApplicationQueuePlayer to unlock some more features.

Mainly, you can call the perform queue transaction method on the ApplicationQueuePlayer.

It requires two closures as parameters.

The first one is the queue transaction.

We'll be passing a mutable queue object, which represents the current state of the playback queue.

You can call a few methods on this mutable queue, such as the remove method to remove the third item currently in the playback queue.

You can also call the insert after method, which we're calling here to insert an item after the fifth item of the playback queue.

Once we're done applying all of those modifications to the playback queue, we'll call your completion handler to let you know.

And that's an overview of everything you can do in terms of playback with Apple Music, and we can't wait to see the experiences you'll build in your apps.

So, let's talk about timeframe.

When can you adopt these APIs in your apps?

As it turns out, a lot of these APIs trickled in throughout several releases, and many of them are available on iOS 10.3 with a few caveats.

We will begin generating music user tokens for iOS 10.3 devices later this fall.

You'll also have to use an alternate method to get to the storefront country code, and you can use, for example, the current locale's region code as an approximation.

However, you'll be able to initiate playback with catalog content using the store queue descriptor right on iOS 10.3.

On iOS 11, with beta you have available to you today, you can do everything we just discussed with the exception of play parameters, queue descriptors, which will come in a later beta.

And because play parameters queue descriptors support everything the store queue descriptor supports, in addition to radio stations and personalized content, if you're targeting iOS 11 and later, you should really use that primarily instead of the store queue descriptor.

So, to summarize, Apple Music offers a breadth of content, over 40 million songs and personalized recommendations for your users, and you can use that, leverage this content to create immersive experiences in your apps to keep your users engaged.

To do that, you'll have to use StoreKit framework to get the user's consent and the Music user token to unlock the full capabilities of Apple Music API.

And you can call Apple Music API, fetch the relevant data, parse it from JSON, and use MediaPlayer framework to control playback of this piece of content.

For more information on MusicKit, feel free to check out our developer portal with this URL.

You also have a few related sessions.

We just had the What's New in Audio session in this room.

We'll also have tomorrow morning, What's New in Foundation, where you can learn all about using the new JSON decoder in Swift 4.0 and on Thursday, you can learn about AirPlay 2 as well.

Thank you very much, and enjoy the rest of the conference.

[ Applause ]

Apple, Inc. AAPL
1 Infinite Loop Cupertino CA 95014 US