如何显示流式 Apple Music 的专辑插图?
How to display album artwork of streamed Apple Music?
在我的音乐播放器中使用新的 Apple Music API(2016 年 5 月 12 日发布)在 iOS 9(swift,虽然我目前正在熟悉 Objective-C),我可以显示流媒体歌曲的信息,但不能显示插图。我正在使用 MediaPlayer、UIKit 和 StoreKit 框架。我已成功请求对 AddToCloudMusicLibrary 和 MusicCatalogPlayback 的授权。我成功地显示了我从 Apple Music 应用程序下载的歌曲中的 Apple Music 插图,以及我个人歌曲 collection 中的插图。我见过其他人有这方面的问题,没有运气......
在我求助于显示默认图像(这对 error-handling 来说是必要的)之前,我只是想再问一次,为了人们,或者从替代服务中提取。任何帮助都会很棒!在我的代码中并不是真正的错误,所以我不会显示它,除非被要求帮助解决这个问题。
我第一次尝试发布代码...这是我在名为 Authorization 的 swift 文件中的内容。我需要在任何地方引用此代码还是应该在 AppDelegate 文件中?这是我项目中唯一我不是 100% 确定的部分。
import StoreKit
import MediaPlayer
import UIKit
class AppleMusicPlayer: NSObject {
let applePlayer = MPMusicPlayerController.systemMusicPlayer()
func playID(productID: String) {
SKCloudServiceController.requestAuthorization { status in
let controller = SKCloudServiceController()
controller.requestCapabilitiesWithCompletionHandler { capabilities, error in
if capabilities != SKCloudServiceCapability.None {
MPMediaLibrary.defaultMediaLibrary().addItemWithProductID(productID) { entities, error in
self.appPlayer.setQueueWithStoreIDs([productID])
self.appPlayer.shuffleMode = .Songs
self.appPlayer.play()
}
}
}
}
}
}
在 MediaItem class 中有一个名为 MPMediaItemPropertyArtwork 的 属性。您将能够通过以下方式检索专辑的插图:
MPMediaItemArtwork *artwork = [mediaItem valueForProperty:MPMediaItemPropertyArtwork];
UIImage *albumImage = [itemArtwork imageWithSize:cgSizeYouWant];
这是 Apple Music 当前 API 中的一个错误。正如您提到的,不在用户库中但从 AM 流式传输的歌曲不会 return 专辑封面。
您应该在 bugreport.apple.com 提交功能增强(您也可以从 6 个月前 25413082 复制我的)。
与此同时,您最好的选择是使用 iTunes api 检索专辑插图,不幸的是,这并不是 return 100% 正确的结果...
我为此苦苦挣扎了一段时间。如果这是一个实际的错误,我不确定,但是您不能像您期望的那样将 UIImageView
设置为 nowPlayingItem
。您必须从 Apple Music 服务中提取图像 api。请参阅文档 here. Also have a look at the sample project here that Apple provides for a full understanding. Also here 是我如何克服此问题的完整示例。
func updateUserInterface() {
if musicPlayerManager.musicPlayerController.playbackState == .playing { //Check if anything is playing
if let currentItem = musicPlayerManager.musicPlayerController.nowPlayingItem {
songAlbumLabel.text = currentItem.albumTitle
songTitleLabel.text = currentItem.title
songArtistNameLabel.text = currentItem.artist
let albumTitle = currentItem.albumTitle //Changes here!
let artist = currentItem.artist //Changes here!
if let artwork = musicPlayerManager.musicPlayerController.nowPlayingItem?.artwork, let image = artwork.image(at: artworkImageView.frame.size) { // Check for local image
print("using local image")
artworkImageView.image = image
} else {
guard let developerToken = appleMusicManager.fetchDeveloperToken() else {print("oops");return}
let searchTypes = "songs"
var searchURLComponents = URLComponents()
searchURLComponents.scheme = "https"
searchURLComponents.host = "api.music.apple.com"
searchURLComponents.path = "/v1/catalog/"
searchURLComponents.path += "\(authorizationManager.cloudServiceStoreFrontCountryCode)"
searchURLComponents.path += "/search"
let expectedArtist = artist?.replacingOccurrences(of: " ", with: "+") //Changes here!
let artistExpected = expectedArtist?.replacingOccurrences(of: "&", with: "") //Changes here!
let expectingArtist = artistExpected?.replacingOccurrences(of: "++", with: "+") //Changes here!
let expectedAlbum = albumTitle?.replacingOccurrences(of: " ", with: "+") //Changes here!
searchURLComponents.queryItems = [
URLQueryItem(name: "term", value: (expectingArtist! + "-" + expectedAlbum!)),
URLQueryItem(name: "types", value: searchTypes)
] //Changes here!
var request = URLRequest(url: searchURLComponents.url!)
request.httpMethod = "GET"
request.addValue("Bearer \(developerToken)", forHTTPHeaderField: "Authorization")
let dataTask = URLSession.shared.dataTask(with: request) {
(data, response, error) in
print(response!)
if let searchData = data {
guard let results = try? self.appleMusicManager.processMediaItemSections(searchData) else { return}
self.mediaItem = results
let album = self.mediaItem[0][0]
let albumArtworkURL = album.artwork.imageUrl(self.artworkImageView.frame.size)
if let image = self.imageManager.cachedImage(url: albumArtworkURL) {
print("using cached image")
self.artworkImageView.image = image
}
else {
self.imageManager.fetchImage(url: albumArtworkURL) {(image) in
print("fetching image")
self.artworkImageView.image = image
}
}
}
}
dataTask.resume()
}
} else { // Need to set it to some kind of default values
artworkImageView.image = nil
songArtistNameLabel.text = " "
songTitleLabel.text = " "
songAlbumLabel.text = " "
}
}
}
我发现的最佳方法是使用从目录 Apple Music API 请求中获取歌曲,documented here。
您只需要传入歌曲标识符(用于播放的那个)和用于播放歌曲的店面标识符。与使用可能会失败的搜索请求的答案相比,这总是会产生准确的结果。
在我的音乐播放器中使用新的 Apple Music API(2016 年 5 月 12 日发布)在 iOS 9(swift,虽然我目前正在熟悉 Objective-C),我可以显示流媒体歌曲的信息,但不能显示插图。我正在使用 MediaPlayer、UIKit 和 StoreKit 框架。我已成功请求对 AddToCloudMusicLibrary 和 MusicCatalogPlayback 的授权。我成功地显示了我从 Apple Music 应用程序下载的歌曲中的 Apple Music 插图,以及我个人歌曲 collection 中的插图。我见过其他人有这方面的问题,没有运气......
在我求助于显示默认图像(这对 error-handling 来说是必要的)之前,我只是想再问一次,为了人们,或者从替代服务中提取。任何帮助都会很棒!在我的代码中并不是真正的错误,所以我不会显示它,除非被要求帮助解决这个问题。
我第一次尝试发布代码...这是我在名为 Authorization 的 swift 文件中的内容。我需要在任何地方引用此代码还是应该在 AppDelegate 文件中?这是我项目中唯一我不是 100% 确定的部分。
import StoreKit
import MediaPlayer
import UIKit
class AppleMusicPlayer: NSObject {
let applePlayer = MPMusicPlayerController.systemMusicPlayer()
func playID(productID: String) {
SKCloudServiceController.requestAuthorization { status in
let controller = SKCloudServiceController()
controller.requestCapabilitiesWithCompletionHandler { capabilities, error in
if capabilities != SKCloudServiceCapability.None {
MPMediaLibrary.defaultMediaLibrary().addItemWithProductID(productID) { entities, error in
self.appPlayer.setQueueWithStoreIDs([productID])
self.appPlayer.shuffleMode = .Songs
self.appPlayer.play()
}
}
}
}
}
}
在 MediaItem class 中有一个名为 MPMediaItemPropertyArtwork 的 属性。您将能够通过以下方式检索专辑的插图:
MPMediaItemArtwork *artwork = [mediaItem valueForProperty:MPMediaItemPropertyArtwork];
UIImage *albumImage = [itemArtwork imageWithSize:cgSizeYouWant];
这是 Apple Music 当前 API 中的一个错误。正如您提到的,不在用户库中但从 AM 流式传输的歌曲不会 return 专辑封面。
您应该在 bugreport.apple.com 提交功能增强(您也可以从 6 个月前 25413082 复制我的)。
与此同时,您最好的选择是使用 iTunes api 检索专辑插图,不幸的是,这并不是 return 100% 正确的结果...
我为此苦苦挣扎了一段时间。如果这是一个实际的错误,我不确定,但是您不能像您期望的那样将 UIImageView
设置为 nowPlayingItem
。您必须从 Apple Music 服务中提取图像 api。请参阅文档 here. Also have a look at the sample project here that Apple provides for a full understanding. Also here 是我如何克服此问题的完整示例。
func updateUserInterface() {
if musicPlayerManager.musicPlayerController.playbackState == .playing { //Check if anything is playing
if let currentItem = musicPlayerManager.musicPlayerController.nowPlayingItem {
songAlbumLabel.text = currentItem.albumTitle
songTitleLabel.text = currentItem.title
songArtistNameLabel.text = currentItem.artist
let albumTitle = currentItem.albumTitle //Changes here!
let artist = currentItem.artist //Changes here!
if let artwork = musicPlayerManager.musicPlayerController.nowPlayingItem?.artwork, let image = artwork.image(at: artworkImageView.frame.size) { // Check for local image
print("using local image")
artworkImageView.image = image
} else {
guard let developerToken = appleMusicManager.fetchDeveloperToken() else {print("oops");return}
let searchTypes = "songs"
var searchURLComponents = URLComponents()
searchURLComponents.scheme = "https"
searchURLComponents.host = "api.music.apple.com"
searchURLComponents.path = "/v1/catalog/"
searchURLComponents.path += "\(authorizationManager.cloudServiceStoreFrontCountryCode)"
searchURLComponents.path += "/search"
let expectedArtist = artist?.replacingOccurrences(of: " ", with: "+") //Changes here!
let artistExpected = expectedArtist?.replacingOccurrences(of: "&", with: "") //Changes here!
let expectingArtist = artistExpected?.replacingOccurrences(of: "++", with: "+") //Changes here!
let expectedAlbum = albumTitle?.replacingOccurrences(of: " ", with: "+") //Changes here!
searchURLComponents.queryItems = [
URLQueryItem(name: "term", value: (expectingArtist! + "-" + expectedAlbum!)),
URLQueryItem(name: "types", value: searchTypes)
] //Changes here!
var request = URLRequest(url: searchURLComponents.url!)
request.httpMethod = "GET"
request.addValue("Bearer \(developerToken)", forHTTPHeaderField: "Authorization")
let dataTask = URLSession.shared.dataTask(with: request) {
(data, response, error) in
print(response!)
if let searchData = data {
guard let results = try? self.appleMusicManager.processMediaItemSections(searchData) else { return}
self.mediaItem = results
let album = self.mediaItem[0][0]
let albumArtworkURL = album.artwork.imageUrl(self.artworkImageView.frame.size)
if let image = self.imageManager.cachedImage(url: albumArtworkURL) {
print("using cached image")
self.artworkImageView.image = image
}
else {
self.imageManager.fetchImage(url: albumArtworkURL) {(image) in
print("fetching image")
self.artworkImageView.image = image
}
}
}
}
dataTask.resume()
}
} else { // Need to set it to some kind of default values
artworkImageView.image = nil
songArtistNameLabel.text = " "
songTitleLabel.text = " "
songAlbumLabel.text = " "
}
}
}
我发现的最佳方法是使用从目录 Apple Music API 请求中获取歌曲,documented here。
您只需要传入歌曲标识符(用于播放的那个)和用于播放歌曲的店面标识符。与使用可能会失败的搜索请求的答案相比,这总是会产生准确的结果。