これまでは、楽曲を検索するにはApple Music APIを使用する必要がありました。新たに発表されたiOSのMusicKitフレームワークによって、楽曲を検索したり、アルバム内の曲をすべてリストアップしたり、楽曲を再生したりするためのリクエストをより簡単に行えるようになりました。
このフレームワークは、Androidシステムでも利用可能です。この記事では、これについては触れません。
MusicKitの新たなフレームワークには、新しくなったSwiftの並行処理も採用されています。データのリクエストに対するレスポンスを待つには、await
コマンドを使用することができます。
この記事では、Apple Music
のカタログを検索し、音楽を再生するアプリの構築について説明します。
使用事例
Appleによると、可能となる使用事例にはゲーム内のBGM、トレーニング中の音楽、ソーシャルメディアなどが含まれています(しかしながら、ご使用の際にはライセンスや著作権などに関して、常にご確認をいただくようお願いします)。
最初にEntitlementを追加する
最初に https://developer.apple.com/account/resources/identifiers/list に移動し、アプリケーションを開くことを選択します。クリックしてApp Services
タブを開き、MusicKit
のトグルをオンにします。
リスト内にアプリケーションが表示されない場合は、XcodeのSigning & Capabilities
ビューで任意の機能を追加できます。これによりXcodeが自動的でに署名プロファイルを生成します。
トークンを生成する必要はありません。それはMusicKitによって自動的に生成されます。
Apple Music ライブラリ へのアクセス申請
ユーザーの視聴履歴や個人ライブラリにアクセスしたい場合は、許可を申請する必要があります。
まず、Info.plist
ファイル内に使用説明文字列NSAppleMusicUsageDescription
を追加します。
次に、ユーザーの認可を要求します
Button("Request authorization") {
Task {
await MusicAuthorization.request()
}
}
次のコードで、ユーザーがアクセスを許可しているか確認します。
Button("Reload authorization status") {
self.currentAuthStatus = MusicAuthorization.currentStatus
}
ユーザーのApple Musicサブスク契約状況を確認
画面が表示されたら、ユーザーのApple Musicサブスク契約状況の問い合わせができます。
まず、ユーザーのサブスク契約状況を格納する変数musicSubscription
を作成します。表示開始時には、これはnil
となっています。
@State private var musicSubscription: MusicSubscription?
ビューが表示されたら、forループでawait
を利用して読み込みを続け、ユーザーの登録ステータスにおける変化を待ちます。
.task {
for await subscription in MusicSubscription.subscriptionUpdates {
self.musicSubscription = subscription
}
}
登録に関する更新情報があれば、ユーザーの登録ステータスを読み込むことができます。
ユーザーがApple Musicに登録できるかどうかを確認
musicSubscription.canBecomeSubscriber
を利用して、ユーザーがApple Musicの登録者になれるかどうかを確認します。
この値がtrueの場合、ユーザーはApple Musicにまだ登録しておらず、登録可能であることを意味します。
MusicSubscriptionOffer
オブジェクトを利用すれば、ユーザーにApple Musicへの登録を勧めることができます。SwiftUI内では、musicSubscriptionOffer
ビューモディファイアが使用可能です。
@State private var showAppleMusicSubscriptionOfferView: Bool = false
if musicSubscription.canBecomeSubscriber {
Button("Promopt the user to subscribe to Apple Music") {
self.showAppleMusicSubscriptionOfferView = true
}
.musicSubscriptionOffer(isPresented: $showAppleMusicSubscriptionOfferView)
}
変数musicSubscription.canBecomeSubscriber
がfalse
の場合は以下のいずれかが当てはまります:
- ユーザーのデバイスが制限されているか、もしくはApple Musicにサブスクライブできません。
- ユーザーが既にApple Musicにサブスクライブしています。どちらに当てはまるのか確認したい場合は、別の変数を使ってユーザーがApple Musicカタログにアクセスできるかチェックする必要があります。
ユーザーがApple Musicのカタログにアクセスできるかどうかの確認
変数musicSubscription.canPlayCatalogContent
を使用します。この変数がtrueであれば、ユーザーはApple Music内のコンテンツを再生できることを意味し、ほとんどの場合、ユーザーはApple Musicに加入していることになります。
ユーザーのiCloudミュージックライブラリへのアクセス確認
変数musicSubscription.hasCloudLibraryEnabled
を使って、ユーザーがクラウドミュージックライブラリを有効にしているかどうかを確認することができます。
音楽を検索する
Apple Musicの音楽カタログを検索するにはMusicCatalogSearchRequest
オブジェクトを使用します。
public struct MusicCatalogSearchRequest {
public init(term: String, types: [MusicCatalogSearchable.Type])
}
term
変数には検索語を指定してください。types
変数には検索するデータの種類を指定します(例:曲、アルバム、プレイリストなど)。検索する種類は複数定義することができます。
たとえば、次のコードを使用すると検索語がBGM
の曲を検索することができます。
let request = MusicCatalogSearchRequest(term: "BGM", types: [Song.self])
次に、let response = try await request.response()
を利用して、検索リクエストを実行します。await
を使用しているので、検索結果が返ってくるまでコードはこの行で停止します。
Button("Perform search") {
Task {
do {
let request = MusicCatalogSearchRequest(term: searchTerm, types: [Song.self])
self.isPerformingSearch = true
let response = try await request.response()
self.isPerformingSearch = false
self.searchResultSongs = response.songs
} catch {
fatalError("Error")
}
}
}
この例では、応答をリクエストする直前に、isPerformingSearch
をtrue
に設定しています。応答の準備が整うと、isPerformingSearch
はfalse
に、searchResultSongs
は検索によって取得された曲に設定されます。
特定のアイテムをリクエストする
アイテム(曲またはアルバム)をリクエストするためには、そのIDを使用します。
let request = MusicCatalogResourceRequest<Album>(matching: \.id, equalTo: "1594311281")
let response = try await request.response()
let items: MusicItemCollection<Album> = response.items
オブジェクトのさらなる情報を読み込む
MusicKitは、すべての情報で応答するわけではありません。例えば、アルバムを検索する場合、アルバム内の曲の情報は含まれません。
MusicKitから受け取ったオブジェクトは、with
関数を呼び出すことで更新できます。
例えば、アルバムオブジェクトがあり、曲を含むアルバムを取得したい場合、関数album.with([.artists, .tracks, .relationAlbums])
を呼び出します。
このSwiftUIビューの例では、検索結果からアルバム変数を入力し、曲情報でオブジェクトを更新します。
struct AlbumDetailsView: View {
@State private var updatedAlbumObject: Album?
var album: Album
var body: some View {
AnyView()
.task {
self.updatedAlbumObject = try? await album.with([.tracks])
}
}
}
self.updatedAlbumObject.tracks
変数を使用して、このアルバム内のすべての曲を取得します。
if let tracks = self.updatedAlbumObject?.tracks {
ForEach(tracks) { track in
switch track {
case .song(let songItem):
SongInfoView(songItem: songItem)
case .musicVideo(_):
EmptyView()
@unknown default:
EmptyView()
}
}
} else {
ProgressView("Loading tracks...")
}
音楽アイテムのアートワークを入手
.artwork
プロパティを呼び出すと、音楽アイテム(曲やアルバムなど)のアートワークを取得できます。
if let artwork = songItem.artwork {
ArtworkImage(artwork, height: 100)
}
SwiftUI内では、ArtworkImage
変数を直接使用して、アートワーク画像を表示できます。
音楽を再生
システムプレーヤーまたはアプリプレーヤーを使用して音楽を再生できます。1曲または1枚のアルバムを再生できます。
システムプレーヤーを使用すると、アプリを閉じても音楽が再生され続けます。
システムプレーヤーの使用
Button("Play using iOS system player") {
Task {
SystemMusicPlayer.shared.queue = .init(for: [album])
do {
try await SystemMusicPlayer.shared.play()
} catch {
print(error.localizedDescription)
}
}
}
album
変数は、MusicItem
プロトコルに準拠した他のオブジェクトで変えることができます。
アプリ内プレーヤーの使用
アプリ内プレーヤーを使えば、より多くのカスタマイズを行うことができます。
Button("Play using in-app player") {
Task {
ApplicationMusicPlayer.shared.queue = .init(for: [album])
do {
try await ApplicationMusicPlayer.shared.play()
} catch {
print(error.localizedDescription)
}
}
}
他の種類のAPIリクエストの実行
その他のApple Music用APIの中には、MusicKit内では利用できないものがある場合があります。そのような場合は、MusicDataRequest
を使ってリクエストを行ってください。レスポンスは手動で解析する必要があります。
let url = URL(string: "https://api.music.apple.com/v1/me/recent/played")!
let request = MusicDataRequest(urlRequest: URLRequest(url: url))
let response = try await request.response()
例えば、最近再生した音楽を取得するには、このウェブページを参照してください: MusicKit - Access user’s recently … | Apple Developer Forums
カテゴリー別に整理された、自分の公開記事とニュースレターを表示します。iOSデバイスのカメラアプリを使用して、このコードをスキャンするだけです。