Mots introductifs
Peu importe à quel point ils réprimandent Apple pour la nature fermée de la plate-forme et de l'écosystème lui-même, certaines de leurs solutions font exception. Il existe de nombreux services de streaming sur le marché, mais la fourniture d'un SDK à part entière pour le streaming dans des produits tiers est extrêmement petite, pour le marché russe, la liste des SDK officiellement disponibles est limitée à Deezer et Apple Music. Bien sûr, lorsque Spotify arrivera sur notre marché, il y aura plus de SDK disponibles, mais jusqu'à présent, il y a deux joueurs et un seul a une large base d'utilisateurs.
Il se trouve que j'ai eu de l'expérience avec le SDK Deezer pour Android et en ce moment je travaille activement avec le SDK Apple Music ( MusicKit ) pour iOS. Et la principale différence avec l'expérience avec Deezer est que MusicKit est la pointe de l'iceberg, c'est aussi une API accessible au public. Contrairement à Deezer, où répéter la plupart des fonctionnalités de l'application officielle n'est qu'un long processus, il est impossible de répéter même la page Web d'Apple Music en utilisant uniquement l'API publique. Même si Apple utilise MusicKit dans ses solutions, en plus de cela, il utilise beaucoup de demandes d'API non documentées et d'API privées qui ne sont pas autorisées à être utilisées par les mortels.
Dans l'article, je parlerai de travailler avec MusicKit du point de vue du développeur dans le contexte de la mise en œuvre de « tâches assez simples »: recherchez dans le catalogue, montrez des images dans les résultats de la recherche, obtenez des chansons, des recommandations et même jouez une sorte de musique. Pour l'avenir, je dirai qu'une grande partie de ce qui précède sera vraie pour travailler avec Apple Music dans Android et Javascript.
Si nécessaire, je suis prêt à donner des réponses détaillées avec un code de questions dans les commentaires.
Séparez les mouches des côtelettes
Lorsque vous travaillez avec MusicKit sous iOS, vous devrez interagir avec les entités suivantes:
- StoreKit pour autorisation dans Apple Music et offre un abonnement au service ( référence si vous pouvez vous abonner au programme d'affiliation )
- API HTTP pour rechercher et récupérer diverses informations d'un répertoire
- API de recherche iTunes pour rechercher dans le répertoire iTunes (une alternative très utile à l'API HTTP ). Apple indique une limite d'un maximum de 20 requêtes par minute, ce qui est souvent suffisant pour effectuer des requêtes depuis les appareils des utilisateurs
- Lecteur multimédia pour lire et gérer la file d'attente
De plus, lorsque vous vous connectez à un programme d'affiliation, vous pouvez demander l'accès au vidage de métadonnées du flux de partenaires d'entreprise , qu'Apple recommande d'utiliser au lieu de demandes fréquentes à l'API iTunes Search.
Et juste au cas où, Music.app est l'application Music sur les appareils iOS, qui est le lecteur officiel Apple Music.
Sources d'information, par ordre décroissant de leur utilité:
- Documentation officielle
- Rechercher dans toute la documentation Apple
- Méthode d'expérimentation scientifique 1 avec API HTTP
- Developer Console dans votre navigateur préféré, épinglé sur la page Web de l'entité d'intérêt dans Apple Music
- Forums des développeurs Apple
- Stackoverflow
Cherchez. Les photos
Le moyen le plus évident de vérifier si quelque chose peut être fait dans votre application est le fait que quelque chose comme ça est disponible dans l'application officielle. Ici, nous prenons, par exemple, une recherche. Nous recherchons le groupe "The Police" et dans Music.app
nous avons une photo du groupe avec un Sting souriant:

Très bien, nous utiliserons l'API de recherche . En cours d'émission, nous avons la clé de l' artwork
avec un lien url
intégré pour tout sauf les artistes. C’est étrange. Vérifiez à nouveau, dans Music.app, tout est là. De plus, l'interface Web possède également une photographie et un lien vers la page Web est disponible dans l'API du moteur de recherche json.
L'API de recherche iTunes ne artistLinkUrl
pas non plus artistLinkUrl
image, mais elle inclut également l'adresse de la page Web avec la clé artistLinkUrl
dans la artistLinkUrl
.
Eh bien, que faire, vous devez télécharger la page Web et en obtenir l'adresse de l'image, heureusement, les développeurs ont pris soin et enregistré l'adresse de l'image dans les méta-informations:
<meta property="og:image" content="https://is5-ssl.mzstatic.com/image/thumb/Features113/v4/bb/a2/66/bba266dd-570b-bff7-d7c6-777982582964/mzl.tdrwskof.jpg/1200x630cw.png" id="ember52310559" class="ember-view">
Formellement, nous avons déjà violé les règles d'Apple qui interdisent de «gratter» leurs pages Web. En fait, toutes les applications tierces le font, sauf celles qui recherchent des images à l'aide de services tiers.
Il y a un autre inconvénient: nous demandons une page de plusieurs centaines de kilo-octets. Pour une application qui gère déjà de grandes quantités de données ( lecture de musique ), c'est tolérable ( surtout si l'on considère que les données sont transmises sous forme compressée ), mais dans le cas général ce n'est pas très.
La taille des images peut être ajustée à vos besoins: dans l' url
il y a des modèles à remplacer ( {w}
, {h}
), et sur la page Web le lien vers l'image a le même format, donc il n'y a aucune difficulté à obtenir l'image de la bonne taille. Si vous voulez obtenir une image arrondie, vous devez ajouter cw
avant l'extension.
Bonus sur les images à afficher dans le lecteur
Pendant la lecture, le lecteur de Media Player
fonctionne sur la construction MPMediaItem
, qui, en particulier, fournit un objet Artwork
. Il est très pratique pour afficher une image d'une piste dans le lecteur. Le seul problème est que dans la pratique, cet objet, quoi qu'on puisse dire, ne donne pas d'images pour la musique en streaming ( qui est n'importe quelle musique d'Apple Music ), donc vous devez "lire" le MPMediaItem
lecture avec des chansons qui ont été ajoutées à la file d'attente et téléchargées l'image est similaire aux albums.
Recherche par genre
ITunes et l'application Apple Music contiennent des listes de genres et de meilleures chansons. Trouver un genre ne devrait pas être difficile, car on peut chercher n'importe quoi?
C'est loin d'être le cas. L'API ne recherche pas par genre et ne fournit pas de liste de genres. Il est possible de demander des informations ( de l'utile - nom ) d'un genre par son identifiant,
mais la plupart des informations de l'API ne contiennent que le nom du genre, pas l'identifiant.
L'avantage pour iTunes est le déchargement de tous les genres ( tous, y compris les "genres" des applications mobiles ). Les identifiants de genres ( comme les autres identifiants d'iTunes ) correspondent entièrement aux identifiants d'Apple Music. Le déchargement est disponible pour toutes les régions (la région est indiquée dans la clé cc
, pas la storefront
comme dans l'API Apple Music ), mais en fait seuls les noms diffèrent ( ils sont traduits ). La structure des genres est hiérarchique et il y a des répétitions des noms de genres.
En général, une recherche par genre doit être effectuée localement, et gardez à l'esprit que le funk jazz, le jazz funk et le jazz funk sont une seule et même chose. Pas difficile, mais pas aussi simple que de demander à l'API de recherche de rechercher par genre.
Après avoir trouvé un genre, vous pouvez demander un tableau (une liste des chansons les plus populaires ) pour ce genre. Pour les genres rares, il est tout à fait possible d'obtenir dans la sortie de seulement 3 chansons.
Fait amusant: pour certains albums et artistes ( Ed Sheeran du célèbre ), un seul des genres indique simplement le genre de haut niveau de "Music". Si vous souhaitez faire des recommandations basées sur les genres, ce genre doit être ignoré.
Chansons d'artistes
Lorsqu'une application doit jouer des chansons d'un artiste ( groupe musical ) le plus souvent, cela signifie qu'il est nécessaire de jouer des chansons populaires de ce groupe. Apple Music permet de demander des chansons en tant que lien "chansons" 2 pour l'artiste. La sortie a un maximum de 20 chansons 3 , clairement triées par popularité.
Parfois, vous voulez toujours obtenir un peu plus de chansons. Avec les groupes très populaires, il existe une option pour obtenir des listes de lecture comme " [Nom de l'artiste]: Essentials " et " [Nom de l'artiste]: Détails " (" [Nom de l'artiste]: Étapes suivantes "), mais en général, cette option ne convient pas. Autre option: prendre 20 chansons populaires et terminer le reste des albums, l'avantage d'Apple Music permet d'obtenir immédiatement tous les albums d'artistes ( liens comme des albums
) et toutes les chansons qu'ils include="tracks"
( include="tracks"
) en une seule demande.
Mais si vous obtenez toutes les chansons de l'artiste, un autre problème se pose: vous devez sélectionner les chansons populaires parmi toutes ces chansons. Malheureusement, l'API d'informations de popularité ne fournit pas 4 . Vous pouvez prendre des chansons au hasard dans toute la liste, mais dans la pratique, cette approche conduit à jouer fréquemment des enregistrements complètement inintéressants ( transcriptions en direct, enregistrements de répétition, ermitages, etc. ), ce qui est particulièrement visible dans les groupes très populaires 5 .
Essayons d'obtenir des chansons populaires d'une manière différente. Même avant l'avènement de MusicKit, Apple a commencé à fournir des API de recherche dans l'iTunes Store. Comme déjà mentionné, le catalogue de l'Apple Music et de l'iTunes Store sont les mêmes 6 et, en conséquence, les identifiants des chansons sont également les mêmes. Cette API renvoie 50 chansons par défaut, mais vous pouvez demander jusqu'à 200 chansons. Les résultats sont également triés par popularité.
Fait intéressant, Apple lui-même n'utilise aucune de ces options dans sa propre interface Web. Ils utilisent l'API 7 non documentée (en lecture, privée ), dans laquelle il y a tout ce qui manque, y compris l'identifiant ( et pas seulement le nom ) du genre et l'indice de popularité. Je n'ai pas osé utiliser cette API dans la pratique 8 , car les identifiants de genre peuvent être obtenus par recherche inversée par noms de genre 9 , et l'indice de popularité numérique n'est pas si important lorsque vous obtenez une liste de chansons triées par popularité.
Le fait amusant que j'appelle le « problème de Hugh Laurie » est que le catalogue Apple Music contient des tonnes de contenu non musical. En particulier, diverses compilations d'émissions de comédie et de stand-up. C'est bien d'une part ( nous avons payé pour la musique, mais nous avons également eu des dialogues amusants avec Stephen Fry que vous pouvez écouter avant d'aller au lit ), et d'autre part, cela conduit à une sorte de bavardage lorsqu'on lui demande d'activer la musique. En conséquence, lorsque le contexte de fonctionnement de l'application indique directement que l'utilisateur souhaite écouter de la musique, il faut supprimer indépendamment de la liste des « chansons » celles dont les genres sont désignés comme « parole parlée » et « comédie ».
Recommandations
Les recommandations de lecture (ce sont aussi des « chansons similaires », des « stations de radio », « vous l'aimerez », etc.) sont devenues la fonctionnalité de base des lecteurs de streaming. Classiquement, les recommandations peuvent être divisées en deux types 10 : pour l'utilisateur ( basé sur l'historique d'écoute, les achats et les likes ) et pour l'objet musical ( artiste, titre, moins souvent album et playlist ).
Avec les préférences de l'utilisateur dans Apple Music, officiellement, tout va bien: vous pouvez demander une liste de recommandations personnelles, qui comprend des « mixages personnels » ( listes de lecture ) et des albums recommandés. À partir d'albums, une liste de chansons peut être obtenue en utilisant les API ( tracks
) , pour les listes de lecture de la même manière. Gardez à l'esprit que les pistes peuvent inclure non seulement des chansons ( type = "songs"
), mais aussi des clips vidéo, de sorte qu'un filtrage supplémentaire des données reçues ne nuira pas.
Avec d'autres recommandations, tout est un peu plus compliqué. Si vous regardez Music.app, les " artistes similaires " y sont affichés et vous pouvez activer la " station de radio " pour cet artiste. Ce dernier perd le mix de l'artiste et les recommandations à lui.

Il semble que tout soit simple: pour les artistes, il y a probablement un lien entre " artistes similaires ". Je m'empresse de bouleverser, il n'y a pas une telle connexion. Il n'y a pas non plus d'informations de similitude dans le schéma de données du flux de partenaire d'entreprise.
D'accord, nous pouvons donc demander une " station de radio " pour l'artiste et obtenir une liste de chansons? Et encore une fois, non, on peut vraiment demander une station de radio, son identifiant est dans l'émission des connexions de l'artiste. Mais dans les informations de la station, il n'y a aucune information sur les chansons, les albums ou les artistes en cours de lecture, il n'y a qu'un objet de service avec des informations pour jouer à playParams
. L'idée avec playParams
simple: nous introduisons ce dictionnaire 12 dans la file d'attente de lecture et l'écoutons.
Tout cela est bien si vous ne voulez écouter qu'une station de radio ( comme le fait Music.app ), mais que faire si vous voulez mélanger des chansons de la station de radio 13 avec autre chose? De toute évidence, nous devons en quelque sorte obtenir une liste d'artistes similaires.
Dans Media Player
, les files d'attente de lecture jouent un rôle important, en particulier MPMusicPlayerControllerMutableQueue . La file d'attente vous permet de: insérer des descripteurs après un certain objet jouable, supprimer des objets spécifiés et également obtenir une liste de tous les objets dans la file d'attente. Lorsque vous interrogez des objets pour la sortie, nous devons obtenir un tableau de MPMediaItem
. Et MPMediaItem
, en particulier, comprend l' identifiant de la chanson . Il n'y a qu'un seul problème: les constructeurs de files d'attente ne sont pas une API publique, je traduirai: Media Player
peut donner une file d'attente prête à l'emploi (parfois modifiable ), mais il est impossible de la créer vous-même 14 .
Eh bien, creuser un peu vers des béquilles peut être utile. Si Media Player
peut me donner une file d'attente variable, je dois la prendre. Pour ce faire, vous devrez travailler avec le lecteur actuel ( singleton ), vous devez donc agir rapidement, sinon l'utilisateur risque de perdre quelque chose de mal, et le lecteur aura toujours le temps de précharger les chansons inutiles jusqu'à présent. Nous changeons la file d'attente de lecture actuelle ( ajoutez le descripteur de station ), regardons ce qui s'est passé, annulons les modifications dans la file d'attente avec une nouvelle transaction ( supprimez ce qui a été réellement ajouté à la file d'attente ).
Malheureusement, nous constatons que seuls deux objets MPMediaItem
sont MPMediaItem
à la file d'attente. Les deux ressemblent à des chansons ( il y a le nom de l'artiste, le nom de la piste, la longueur de la piste ), mais n'incluent pas l'identifiant de la chanson. Si vous regardez Music.app, nous constatons que tout y converge: allumer la station de radio jouera la chanson, et dans la file d'attente il n'y aura qu'une seule chanson à jouer. Lorsque vous passez à la chanson suivante, la file d'attente est mise à jour.
Cela n'a aucun sens d'essayer de construire des béquilles avec des stations de radio plus loin; vous devez utiliser d'autres options.
Rappelez-vous que dans Music.app et l'interface Web, des artistes similaires sont affichés. Des artistes similaires ne sont disponibles que pour les groupes les plus populaires 15 . Encore une fois, vous devez recourir à la méthode interdite d'analyse d'une page Web. Des pros: nous téléchargeons déjà une page Web pour obtenir une photo, afin que nous puissions en obtenir immédiatement des artistes similaires.
Dans le code de la page html, nous voyons un grand objet json, à partir duquel nous prenons d'abord les identifiants d'artistes similaires ( ["data"]["relationships"]["artistContemporaries"]
):

puis en utilisant ces identifiants, nous obtenons les données de l'artiste du même json ( ["included"]
avec le type lockup/artist
):

Ayant les identifiants des artistes, nous pouvons demander leurs morceaux. L'API vous permet de demander plusieurs artistes par leurs identifiants en une seule demande avec les liens activés. Hélas, en pratique, l'API renvoie une erreur indiquant l'impossibilité d'ajouter une liste de pistes au résultat. Cela ne peut se faire qu'en demandant des artistes un par un ou en demandant directement des chansons pour un seul artiste. Dans ce cas, vous pouvez utiliser l'API iTunes Search déjà mentionnée, qui vous donnera des informations un peu plus utiles.
Les listes "d' artistes similaires " dans Apple Music sont assez bonnes, mais en pratique, elles s'avèrent souvent vides. Dans le cas d'une liste de recommandations vide, vous devez utiliser des services tiers. Classiques - Last.fm, un peu plus sophistiqué - Spotify. Les résultats des deux doivent correspondre aux objets du catalogue Apple Music. La solution "au front" consiste à rechercher chaque artiste par son nom avec exactement un résultat, puis à recevoir les chansons comme décrit ci-dessus. Les solutions sont un peu plus intéressantes, mais il est plus coûteux d'utiliser musicbrainz pour l'appariement. Musicbrainz fournit des informations sur les identifiants 16 dans d'autres services, c'est-à-dire Vous pouvez associer un identifiant dans Spotify à un identifiant dans Apple Music. La situation avec Last.fm est encore meilleure: Last.fm renvoie les identifiants de musicbrainz dans la liste des recommandations. Le surcoût réside dans les limites de l'utilisation de musicbrainz, avec beaucoup de trafic, vous devez générer votre propre clone de musicbrainz (heureusement, cela est possible ) ou développer votre propre API autour d' une base de données , dont les décharges peuvent être facilement téléchargées.
Pour les nouveaux groupes, même Last.fm ne donnera pas de recommandations, les options alternatives seront des recommandations de «genre». Nous prenons les genres de l'artiste ( sur la base du nom, nous obtenons des identifiants de la liste déjà chargée de tous les genres ), nous obtenons le tableau de chaque genre, nous mixons les chansons reçues. C'est mieux que rien.
Deux choses sont inséparables: le joueur et la file d'attente
Media Player est responsable de la lecture dans iOS depuis Apple Music; il vous permet de travailler avec la musique d'Apple Music et le répertoire personnel de l'utilisateur 17 . Le cadre est de haut niveau et dans la situation de travailler avec du contenu en streaming pour descendre à un niveau inférieur à 18 ne fonctionnera pas.
Le cadre fournit à deux joueurs une interface logicielle commune: l' un joue de la musique directement dans l'application Music.app, et l' autre fonctionne plus ou moins indépendamment. Utiliser le premier pour quelque chose de sérieux est inutile 19 . Et la documentation ment effrontément 20 que le deuxième joueur ne fonctionne pas en arrière-plan
Du point de vue architectural, travailler avec cette question est simple: nous disons au joueur quoi jouer ( par exemple, en remplissant la file d'attente, sur la base d'un tableau d'identifiants de chansons ) et nous contrôlons la lecture ( lecture, pause, suivante, précédente ).
Il n'y a pas de contrôle direct de la file d'attente de lecture, vous devez effectuer une modification transactionnelle , ce qui prend du temps. Dans le même temps, le gestionnaire de completionHandler
est souvent appelé avec une erreur de temporisation, qui se traduit par " Je ne sais pas si j'ai pu faire quelque chose ou si je fais autre chose, mais je suis fatigué de m'attendre ." Le plus souvent, la transaction se passe bien et les erreurs qui arrivent au gestionnaire doivent être ignorées. Certaines des modifications peuvent être apportées à un niveau légèrement supérieur , cependant, si vous avez déjà dû utiliser des modifications transactionnelles, il est préférable de les utiliser pour tout.
En général, les files d'attente sont assez flexibles, et s'il est peu probable que votre application fonctionne une fois avec d'autres services de streaming 21 , vous pouvez faire beaucoup de choses intéressantes avec les files d'attente, en particulier, indiquer à quelle heure l'élément commence à jouer et pendant combien de temps.
Parmi les autres « inconvénients » d'une telle approche de haut niveau, il convient de noter l'incapacité à traiter les actions des utilisateurs. En appuyant sur l'utilisateur sur le casque du bouton " piste suivante " ne conduira pas à une demande pour le programme " que dois-je faire ", le joueur sait mieux quoi faire et changera de chanson lui-même. Vous ne pouvez donc attraper que les modifications réellement terminées de l'état du joueur et prendre certaines décisions après coup.
En revanche, vous n'avez pas à faire grand-chose: les informations sur la lecture sur l'écran de verrouillage sont simplement là et tous les boutons y fonctionnent, Apple Watch et Siri peuvent contrôler la lecture, et la diffusion via AirPlay sur Apple TV fonctionne à partir de la boîte 22 .
Il est possible de répéter la fonctionnalité et l'interface de la file d'attente Music.app dans votre application, mais la simplicité apparente des éléments drag'n'drop de la file d'attente s'avère en fait jongler avec les transactions pour changer la file d'attente et synchroniser la file d'attente souhaitée et la file d'attente réelle de 23 joueurs.
En fait, travailler avec l'API n'est pas différent sur d'autres plates-formes, mais les SDK ne sont pas complètement copiés avec iOS et, à certains endroits, sont plus pratiques 24 , bien que l'idée générale d'une file d'attente et d'un lecteur en tandem demeure.
Ainsi, sous Android, vous pouvez obtenir la file d'attente actuelle et déplacer les éléments de la file d'attente sans astuces avec un changement transactionnel (en supprimant de la file d'attente et en ajoutant au bon endroit avec les doigts croisés ).
MusicKit JS fournit également des méthodes d'emballage spéciales pour travailler avec l'API Apple Music,
mais lorsque vous utilisez des wrappers, vous ne pouvez pas vous passer de lire la documentation de l'API elle-même. Travailler avec la file d'attente et le lecteur n'est pas plus pratique que le SDK iOS , mais avec de petits modules complémentaires, il peut devenir supportable .
Quelques mots sur le simulateur
Vous ne pouvez travailler dans le simulateur avec MusicKit que dans le contexte de la communication avec l'API HTTP, mais même dans ce cas, vous devrez stabiliser le jeton de l'utilisateur pour effectuer les demandes, et ne pas l'obtenir via StoreKit . Il est complètement impossible de lire de la musique d'Apple Music dans le simulateur, car l'application Music.app est manquante.
En fait, vous devez développer vos propres modules complémentaires sur le SDK et, lors de l'exécution dans le simulateur, utiliser des implémentations alternatives ( fictives ). En fait, lors du développement, le simulateur n'est utile que pour travailler sur l'interface utilisateur. Sa propre abstraction sera également utile dans les captures d'écran automatisées de l'application ( et en effet lors de la création de captures d'écran à l'aide d'un simulateur ), car avoir les deux générations de «grands» iPad Pro dans l'arsenal juste pour prendre des captures d'écran de votre lecteur sur les deux est extrêmement peu rentable et stupide .
En tant qu'expérience intéressante mais pas très utile, vous pouvez créer une implémentation alternative de votre propre lecteur de haut niveau basé sur MusicKit JS.
À propos du flux de partenaires d'entreprise
D'une part, Apple fournit un vidage de métadonnées sur demande et dit de l'utiliser pour réduire la charge sur l'API et obtenir des informations que l'API ne possède pas. D'autre part, nous avons un problème clair avec le poulet et les œufs: l'accès au programme d'affiliation est fourni en spécifiant un lien vers l'application. Il est assez difficile de développer une application en utilisant les données qui ne peuvent être obtenues qu'avec l'application publiée sur l'App Store.
Et, bien sûr, les données ne donnent pas le premier venu. Chaque demande est vérifiée dans les cinq jours ouvrables. Au moment d'écrire ces lignes, je n'ai pas réussi à obtenir un cliché de métadonnées entre mes mains. Apple a encapsulé ma demande sans préciser les raisons exactes. , - " Apple Music " , Apple . - , -, . , Apple , , .
, , . Apple Music ( , ), . , , Apple Music . , , .
Enterprise Partner Feed :
- Apple Music API iTunes Search API
- (" "), -
, - :
- . , , .
, . , - - - , , . , - , -.
- , SDK , . Apple 25 SDK 26 , , , API , SDK .
- , " code level " . " Q&A " " Tech Notes ", , - .
- . , , . API ( Last.fm, musicbrainz, iTunes Search API ) IP . Apple Music . " " , 27 .
- , Apple Music API, , . - App Store , ( ) , , ( ). 28 , , , 29 . Apple 30 .
- , - Apple Music — Ember. , , html DOM Javascript.
- -, , . , .
SDK, batch API, , « » Apple Music. , , SDK . SDK, .
, .
1 ( )
2 ,
3 , Music.app - ( ), API ( "" )
4 limit
: Specified limit for relationship 'songs' exceeds maximum of 20
5 The Beatles
6 , Apple Music iTunes Store. API iTunes Store `isStreamablez, Apple Music .
7 : https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewArtistSeeAll?cc=ru&ids=424279384§ion=0
8 , , , iTunes ( ) iTunes Store
9
10 , !
11 , Apple Music : , ,
12 , MPMusicPlayerPlayParametersQueueDescriptor
13 Apple Music , ( ) . .
14 , , App Store
15 ( ) ( ) ( ) ( ) . .
16 -,
17 , iTunes Store iTunes Match
18 API URL
19 — -, . , .
20 : ( When your app moves to the background, the music player stops playing the current media. ). AVPlayer
, , Info.plist
.
21 .
22 , MPMediaItem
23
24 , SDK , , . iOS Media Player
, API .
25 , — , .
26 SDK , Apple Music. Apple , .
27 , — . , Enterprise Partner Feed, musicbrainz, API. , ( ) . , .
28 RIP
29 API Bing
30