diff --git a/local_plugins/music_service/ios/music_service/Sources/music_service/MusicService.swift b/local_plugins/music_service/ios/music_service/Sources/music_service/MusicService.swift index 3d13dc7a3..74374fbc6 100644 --- a/local_plugins/music_service/ios/music_service/Sources/music_service/MusicService.swift +++ b/local_plugins/music_service/ios/music_service/Sources/music_service/MusicService.swift @@ -16,6 +16,7 @@ public class MusicService: NSObject { private var player: AVPlayer? private var playlist: [[String: Any]] = [] private var currentIndex = 0 + private var currentsongid = Int64(0) public var isPlaying = false private var flutterChannel: FlutterMethodChannel? private var progressTimer: Timer? @@ -34,7 +35,7 @@ public class MusicService: NSObject { private override init() { super.init() setupRemoteCommandCenter() - //setupAudioSession() + setupAudioSession() } public func initialize(serviceUrl: String, userToken: String) { @@ -44,15 +45,15 @@ public class MusicService: NSObject { } - // // MARK: - 音频会话设置 - // private func setupAudioSession() { - // do { - // try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.allowAirPlay, .allowBluetooth]) - // try AVAudioSession.sharedInstance().setActive(true) - // } catch { - // print("设置音频会话失败: \(error)") - // } - // } + // MARK: - 音频会话设置 + private func setupAudioSession() { + do { + try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.allowAirPlay, .allowBluetooth]) + try AVAudioSession.sharedInstance().setActive(true) + } catch { + print("设置音频会话失败: \(error)") + } + } // MARK: - 基础播放控制 func getCurrentUrlString() -> String? { @@ -153,7 +154,7 @@ public class MusicService: NSObject { // MARK: - 获取歌曲URL - public func getSongUrl(id: Int64, completion: @escaping (Result<[String: Any?], Error>) -> Void) { + public func getSongUrl(id: Int64,curragnt:Int,allagent:Int, completion: @escaping (Result<[String: Any?], Error>) -> Void) { guard !serviceUrl.isEmpty, let url = URL(string: "\(serviceUrl)/api/home/music_url") else { completion(.failure(NSError(domain: "MusicService", code: -1, userInfo: [NSLocalizedDescriptionKey: "Service URL is not configured"]))) return @@ -172,7 +173,12 @@ public class MusicService: NSObject { do { request.httpBody = try JSONSerialization.data(withJSONObject: body, options: []) } catch { - completion(.failure(error)) + if (allagent > 0 && curragnt < allagent){ + getSongUrl(id: id,curragnt: curragnt+1,allagent: allagent,completion: completion) + }else{ + completion(.failure(error)) + } + return } @@ -181,20 +187,32 @@ public class MusicService: NSObject { let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("获取URL请求失败: \(error.localizedDescription)") - completion(.failure(error)) + if (allagent > 0 && curragnt < allagent){ + self.getSongUrl(id: id,curragnt: curragnt+1,allagent: allagent,completion: completion) + }else{ + completion(.failure(error)) + } return } guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { let statusCode = (response as? HTTPURLResponse)?.statusCode ?? -1 print("获取URL失败,HTTP状态码: \(statusCode)") - completion(.failure(NSError(domain: "MusicService", code: statusCode, userInfo: [NSLocalizedDescriptionKey: "获取URL失败,HTTP状态码: \(statusCode)"]))) + if (allagent > 0 && curragnt < allagent){ + self.getSongUrl(id: id,curragnt: curragnt+1,allagent: allagent,completion: completion) + }else{ + completion(.failure(NSError(domain: "MusicService", code: statusCode, userInfo: [NSLocalizedDescriptionKey: "获取URL失败,HTTP状态码: \(statusCode)"]))) + } return } guard let data = data else { print("获取URL响应数据为空") - completion(.failure(NSError(domain: "MusicService", code: -2, userInfo: [NSLocalizedDescriptionKey: "响应数据为空"]))) + if (allagent > 0 && curragnt < allagent){ + self.getSongUrl(id: id,curragnt: curragnt+1,allagent: allagent,completion: completion) + }else{ + completion(.failure(NSError(domain: "MusicService", code: -2, userInfo: [NSLocalizedDescriptionKey: "响应数据为空"]))) + } return } @@ -202,13 +220,29 @@ public class MusicService: NSObject { if let jsonResponse = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] { let urlData = self.parseUrlFromResponse(jsonResponse: jsonResponse) print("获取URL成功: \(urlData)") - completion(.success(urlData)) + if (!urlData.isEmpty){ + completion(.success(urlData)) + }else{ + if (allagent > 0 && curragnt < allagent){ + self.getSongUrl(id: id,curragnt: curragnt+1,allagent: allagent,completion: completion) + }else{ + completion(.failure(NSError(domain: "MusicService", code: -3, userInfo: [NSLocalizedDescriptionKey: "获取连接失败!"]))) + } + } } else { - completion(.failure(NSError(domain: "MusicService", code: -3, userInfo: [NSLocalizedDescriptionKey: "解析JSON响应失败"]))) + if (allagent > 0 && curragnt < allagent){ + self.getSongUrl(id: id,curragnt: curragnt+1,allagent: allagent,completion: completion) + }else{ + completion(.failure(NSError(domain: "MusicService", code: -3, userInfo: [NSLocalizedDescriptionKey: "解析JSON响应失败"]))) + } } } catch { print("解析获取URL响应时发生异常: \(error.localizedDescription)") - completion(.failure(error)) + if (allagent > 0 && curragnt < allagent){ + self.getSongUrl(id: id,curragnt: curragnt+1,allagent: allagent,completion: completion) + }else{ + completion(.failure(error)) + } } } @@ -248,7 +282,7 @@ public class MusicService: NSObject { id = 0 currentIdInternal = 0 } - + currentsongid = id print("开始播放play id: \(id)") // 检查 URL 和时间戳 @@ -262,7 +296,7 @@ public class MusicService: NSObject { if needNewUrl { print("URL 不存在或已过期,重新获取 URL") // 调用 getSongUrl 获取新的 URL - getSongUrl(id: id) { [weak self] result in + getSongUrl(id: id,curragnt: 0,allagent: 3) { [weak self] result in DispatchQueue.main.async { switch result { case .success(let urlData): @@ -275,8 +309,11 @@ public class MusicService: NSObject { // 更新 playlist 中对应的歌曲数据 self?.updatePlaylistSong(songId: id, updatedSong: updatedSong) - // 使用新 URL 开始播放 - self?.startPlayback(song: updatedSong, url: newUrl) + if (self?.currentsongid == id) { + // 使用新 URL 开始播放 + self?.startPlayback(song: updatedSong, url: newUrl) + } + } else { print("获取到的 URL 为空") } @@ -601,20 +638,39 @@ public class MusicService: NSObject { // 异步加载封面图片 if !coverUrl.isEmpty, let url = URL(string: coverUrl) { + print("开始加载封面图片: \(coverUrl)") + DispatchQueue.global(qos: .background).async { - if let data = try? Data(contentsOf: url), - let image = UIImage(data: data) { - DispatchQueue.main.async { - nowPlayingInfo[MPMediaItemPropertyArtwork] = MPMediaItemArtwork(boundsSize: image.size) { _ in image } - MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo + // 创建带超时的URLRequest + var request = URLRequest(url: url) + request.timeoutInterval = 10.0 + + URLSession.shared.dataTask(with: request) { data, response, error in + if let error = error { + print("图片加载失败: \(error.localizedDescription)") + DispatchQueue.main.async { + MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo + } + return } - } else { + + guard let data = data, let image = UIImage(data: data) else { + print("图片数据无效或格式不支持") + DispatchQueue.main.async { + MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo + } + return + } + + print("图片加载成功") DispatchQueue.main.async { + nowPlayingInfo[MPMediaItemPropertyArtwork] = MPMediaItemArtwork(boundsSize: image.size) { _ in image } MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo } - } + }.resume() } } else { + print("封面图片URL为空") MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo }