diff --git a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt index 742a0834d..68cd3460a 100644 --- a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt +++ b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt @@ -830,6 +830,9 @@ object AgentService : CoroutineScope { if (systemPrompt.isNotEmpty()) { val mapdata = UserPortrait.getAll().toMutableMap() mapdata["language"] = language + // 添加当前时间(格式化字符串) + val currentTimeFormatted = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date()) + mapdata["current_time"] = currentTimeFormatted // Log.d(TAG, "liwei--------- 用户画像: ${mapdata}") val _systemPrompt = Utils.fillTemplate(systemPrompt, mapdata) messagesWithSystemPrompt.put(createSystemMessage(_systemPrompt)) diff --git a/local_plugins/agent_service/ios/agent_service/Package.swift b/local_plugins/agent_service/ios/agent_service/Package.swift index 83f572fff..c22abc0ec 100644 --- a/local_plugins/agent_service/ios/agent_service/Package.swift +++ b/local_plugins/agent_service/ios/agent_service/Package.swift @@ -16,8 +16,8 @@ let package = Package( .package(path: "../../../chat_storage/ios/chat_storage"), .package(path: "../../../location_service/ios/location_service"), .package(path: "../../../music_service/ios/music_service"), - .package(path: "../../../music_service/ios/user_portrait") - + .package(path: "../../../music_service/ios/user_portrait"), + .package(path: "../../../qq_music/ios/qq_music"), ], targets: [ .target( @@ -32,6 +32,7 @@ let package = Package( .product(name: "location-service", package: "location_service"), .product(name: "music-service", package: "music_service"), .product(name: "user-portrait", package: "user_portrait"), + .product(name: "qq-music", package: "qq_music"), ], path: "Sources/agent_service", resources: [ diff --git a/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift b/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift index 574689e3b..b644659c3 100644 --- a/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift +++ b/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift @@ -10,6 +10,7 @@ import chat_api import chat_storage import music_service import user_portrait +import qq_music protocol AgentServiceListener: AnyObject { func onEvent(eventName: String, data: [String: Any]) @@ -497,6 +498,10 @@ audioStream.saveAudioDataTo(data: audioData) var info = UserPortrait.shared.getAll() info["language"] = self.language + // Add current time (formatted string) + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" + info["current_time"] = dateFormatter.string(from: Date()) // 添加调试日志 print("系统提示词模板: \(systemPrompt)") print("用户画像数据: \(info)") @@ -730,6 +735,8 @@ private func handleJSONDictionary(_ jsonDict: [String: Any], toolName: String) - processMusicListCard(musics) } else if let cardNavigation = jsonDict["card_navigation"] as? [String: Any] { processNavigationCard(cardNavigation) + } else if let cardQQMusiclist = jsonDict["data"] as? [[String: Any]], toolName == "qqmusic_searchandplay_songs" { + processQQMusicPlayList(cardQQMusiclist) } let metaStr: String @@ -777,7 +784,31 @@ private func jsonToString(_ json: [String: Any]) -> String? { return nil } } - + private func processQQMusicPlayList(_ musics: [[String: Any]]){ + // 如果 playlist 中有有效的歌曲,开始播放 + if !musics.isEmpty { + // 从songs中提取mid字段构建songMids列表 + let songMids = musics.compactMap { song in + song["mid"] as? String + }.filter { !$0.isEmpty } + + if !songMids.isEmpty { + // 调用QPlayAutoManager的playSongs方法 + + QPlayAutoManager.shared.playSongs(mids: songMids, index: 0) { success, errorMessage in + if success { + print("QQ音乐播放列表启动成功,共\(songMids.count)首歌曲") + } else { + print("QQ音乐播放列表启动失败: \(errorMessage ?? "未知错误")") + } + } + } else { + print("音乐列表中没有有效的mid,未启动播放服务") + } + } else { + print("音乐列表为空,未启动播放服务") + } + } // 处理音乐卡片 private func processMusicCard(_ cardMusic: [String: Any]) { let id = cardMusic["id"] as? Int ?? 0 @@ -831,6 +862,7 @@ private func jsonToString(_ json: [String: Any]) -> String? { // 实际处理导航逻辑 print("启动导航: 从 \(start) 到 \(end)") } + // 后台播放单曲 private func processMusicPlay(_ song: [String: Any]) { sendEvent(name: "music_play", data: song) @@ -843,6 +875,8 @@ private func jsonToString(_ json: [String: Any]) -> String? { MusicService.shared.playPlaylist(songs: songs) } + + // 添加定位监听 // private func addlocationmonitor(){ // // 通常放在启动后或模块初始化时 diff --git a/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureAsrHelper.swift b/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureAsrHelper.swift index 8e3e6a85e..d5223221f 100644 --- a/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureAsrHelper.swift +++ b/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureAsrHelper.swift @@ -299,7 +299,7 @@ public class AzureAsrHelper: NSObject { audioStream?.setAudioConfig(sampleRate: sampleRate, channels: channels) // 设置录音文件的配置 - recordfile?.setAudioConfig(sampleRate: sampleRate, channels: channels) + // recordfile?.setAudioConfig(sampleRate: sampleRate, channels: channels) print("音频配置设置成功") return true @@ -720,11 +720,11 @@ public class AzureAsrHelper: NSObject { ) // 如果已经有推流,重新创建 - if pushAudioStream != nil { - let audioStreamFormat = SPXAudioStreamFormat() - audioStreamFormat?.initUsingPCM(withSampleRate: UInt(sampleRate), bitsPerSample: 16, channels: UInt(channels)) - pushAudioStream = SPXPushAudioInputStream(audioFormat: audioStreamFormat) - } + // if pushAudioStream != nil { + // let audioStreamFormat = SPXAudioStreamFormat() + // audioStreamFormat?.initUsingPCM(withSampleRate: UInt(sampleRate), bitsPerSample: 16, channels: UInt(channels)) + // pushAudioStream = SPXPushAudioInputStream(audioFormat: audioStreamFormat) + // } print("AudioStream音频配置设置完成") } diff --git a/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureSpeechPlugin.swift b/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureSpeechPlugin.swift index 4d18c9c71..03481ad77 100644 --- a/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureSpeechPlugin.swift +++ b/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureSpeechPlugin.swift @@ -272,9 +272,9 @@ import os.log case "pauseRecord": azureAsrHelper.pauseRecord() result(true) - case "resumeRecord": - azureAsrHelper.resumeRecord() - result(true) + // case "resumeRecord": + // azureAsrHelper.resumeRecord() + // result(true) case "stopRecord": guard let args = call.arguments as? [String: Any], diff --git a/local_plugins/chat_api/ios/chat_api/Package.swift b/local_plugins/chat_api/ios/chat_api/Package.swift index 590fd4a5c..8f7b3378a 100644 --- a/local_plugins/chat_api/ios/chat_api/Package.swift +++ b/local_plugins/chat_api/ios/chat_api/Package.swift @@ -16,6 +16,9 @@ let package = Package( .package(url: "https://github.com/MacPaw/OpenAI.git", from: "0.4.3"), .package(url: "https://github.com/modelcontextprotocol/swift-sdk.git", from: "0.9.0"), .package(path: "../../../location_service/ios/location_service"), + .package(path: "../../../qq_music/ios/qq_music"), + + ], targets: [ .target( @@ -23,6 +26,7 @@ let package = Package( dependencies: [ .product(name: "MCP", package: "swift-sdk"), .product(name: "OpenAI", package: "OpenAI"), + .product(name: "qq-music", package: "qq_music"), .product(name: "location-service", package: "location_service") ], exclude: [] diff --git a/local_plugins/chat_api/ios/chat_api/Sources/chat_api/MCPClient.swift b/local_plugins/chat_api/ios/chat_api/Sources/chat_api/MCPClient.swift index 35a9df702..85bcc05e6 100644 --- a/local_plugins/chat_api/ios/chat_api/Sources/chat_api/MCPClient.swift +++ b/local_plugins/chat_api/ios/chat_api/Sources/chat_api/MCPClient.swift @@ -434,7 +434,11 @@ public class MCPClient { do { let handler = SystemFunctionHandler() handler.registerAllFunctions(client: self) - } catch { + + // 初始化QQ音乐功能 + let qqMusicHandler = QQMusicSystemFunctionHandler() + qqMusicHandler.registerAllFunctions(client: self) + } catch { // 静默处理错误 } } diff --git a/local_plugins/chat_api/ios/chat_api/Sources/chat_api/QQMusicSystemFunctionHandler.swift b/local_plugins/chat_api/ios/chat_api/Sources/chat_api/QQMusicSystemFunctionHandler.swift new file mode 100644 index 000000000..8a3ad5fa0 --- /dev/null +++ b/local_plugins/chat_api/ios/chat_api/Sources/chat_api/QQMusicSystemFunctionHandler.swift @@ -0,0 +1,282 @@ +import Foundation +import qq_music + +class QQMusicSystemFunctionHandler { + + // 添加 registerAllFunctions 方法 + func registerAllFunctions(client: MCPClient) { + // 注册QQ音乐搜索和播放功能 + client.registerLocalFunction( + name: "qqmusic_searchandplay_songs", + description: "搜索并播放QQ音乐歌曲", + parameters: [ + "type": "object", + "properties": [ + "keyword": [ + "type": "string", + "description": "搜索关键词" + ] + ], + "required": ["keyword"] + ], + handler: QQMusicSearchHandler() + ) + + // 注册暂停功能 + client.registerLocalFunction( + name: "qqmusic_pause", + description: "暂停QQ音乐播放", + parameters: [ + "type": "object", + "properties": [:] as [String: Any], + "required": [] as [String] + ], + handler: QQMusicPauseHandler() + ) + + // 注册恢复播放功能 + client.registerLocalFunction( + name: "qqmusic_resume", + description: "恢复QQ音乐播放", + parameters: [ + "type": "object", + "properties": [:] as [String: Any], + "required": [] as [String] + ], + handler: QQMusicResumeHandler() + ) + + // 注册停止功能 + client.registerLocalFunction( + name: "qqmusic_stop", + description: "停止QQ音乐播放", + parameters: [ + "type": "object", + "properties": [:] as [String: Any], + "required": [] as [String] + ], + handler: QQMusicStopHandler() + ) + + // 注册下一首功能 + client.registerLocalFunction( + name: "qqmusic_next", + description: "播放下一首歌曲", + parameters: [ + "type": "object", + "properties": [:] as [String: Any], + "required": [] as [String] + ], + handler: QQMusicNextHandler() + ) + + // 注册上一首功能 + client.registerLocalFunction( + name: "qqmusic_previous", + description: "播放上一首歌曲", + parameters: [ + "type": "object", + "properties": [:] as [String: Any], + "required": [] as [String] + ], + handler: QQMusicPreviousHandler() + ) + + // 注册获取播放状态功能 + client.registerLocalFunction( + name: "qqmusic_get_playback_state", + description: "获取QQ音乐播放状态", + parameters: [ + "type": "object", + "properties": [:] as [String: Any], + "required": [] as [String] + ], + handler: QQMusicGetPlaybackStateHandler() + ) + + // 注册获取当前歌曲功能 + client.registerLocalFunction( + name: "qqmusic_get_current_song", + description: "获取当前播放的歌曲信息", + parameters: [ + "type": "object", + "properties": [:] as [String: Any], + "required": [] as [String] + ], + handler: QQMusicGetCurrentSongHandler() + ) + + // 注册获取播放时间功能 + client.registerLocalFunction( + name: "qqmusic_get_play_time", + description: "获取播放时间信息", + parameters: [ + "type": "object", + "properties": [:] as [String: Any], + "required": [] as [String] + ], + handler: QQMusicGetPlayTimeHandler() + ) + } +} + +// MARK: - Private Handler Classes + +private class QQMusicSearchHandler: FunctionHandler { + func handle(arguments: [String: Any]) async throws -> String { + guard let keyword = arguments["keyword"] as? String else { + let result: [String: Any] = ["success": false, "error": "Missing keyword parameter"] + let jsonData = try JSONSerialization.data(withJSONObject: result) + return String(data: jsonData, encoding: .utf8) ?? "{}" + } + + return await withCheckedContinuation { continuation in + // 直接调用QPlayAutoManager的搜索接口 + QPlayAutoManager.shared.search(keyword: keyword, searchType: .song) { items in + var result: [String: Any] + + if let items = items, !items.isEmpty { + let songs = items.map { item -> [String: Any] in + return [ + "mid": item.mid ?? "", + "name": item.name ?? "", + "artist": item.singer?.name ?? "", + "album": item.album ?? "", + "duration": item.duration, + "pic": item.coverUri ?? "" + ] + } + result = [ + "success": true, + "message": "Found \(items.count) songs and started playing", + "data": songs + ] + } else { + result = ["success": false, "error": "No songs found"] + } + + do { + let jsonData = try JSONSerialization.data(withJSONObject: result) + let jsonString = String(data: jsonData, encoding: .utf8) ?? "{}" + continuation.resume(returning: jsonString) + } catch { + continuation.resume(returning: "{\"success\": false, \"error\": \"JSON serialization failed\"}") + } + } + } + } +} + +private class QQMusicPauseHandler: FunctionHandler { + func handle(arguments: [String: Any]) async throws -> String { + QPlayAutoManager.shared.pause() + let result: [String: Any] = ["success": true, "message": "Music paused"] + let jsonData = try JSONSerialization.data(withJSONObject: result) + return String(data: jsonData, encoding: .utf8) ?? "{}" + } +} + +private class QQMusicResumeHandler: FunctionHandler { + func handle(arguments: [String: Any]) async throws -> String { + QPlayAutoManager.shared.play() + let result: [String: Any] = ["success": true, "message": "Music resumed"] + let jsonData = try JSONSerialization.data(withJSONObject: result) + return String(data: jsonData, encoding: .utf8) ?? "{}" + } +} + +private class QQMusicStopHandler: FunctionHandler { + func handle(arguments: [String: Any]) async throws -> String { + QPlayAutoManager.shared.stop() + let result: [String: Any] = ["success": true, "message": "Music stopped"] + let jsonData = try JSONSerialization.data(withJSONObject: result) + return String(data: jsonData, encoding: .utf8) ?? "{}" + } +} + +private class QQMusicNextHandler: FunctionHandler { + func handle(arguments: [String: Any]) async throws -> String { + QPlayAutoManager.shared.next() + let result: [String: Any] = ["success": true, "message": "Skipped to next song"] + let jsonData = try JSONSerialization.data(withJSONObject: result) + return String(data: jsonData, encoding: .utf8) ?? "{}" + } +} + +private class QQMusicPreviousHandler: FunctionHandler { + func handle(arguments: [String: Any]) async throws -> String { + QPlayAutoManager.shared.previous() + let result: [String: Any] = ["success": true, "message": "Skipped to previous song"] + let jsonData = try JSONSerialization.data(withJSONObject: result) + return String(data: jsonData, encoding: .utf8) ?? "{}" + } +} + +private class QQMusicGetPlaybackStateHandler: FunctionHandler { + func handle(arguments: [String: Any]) async throws -> String { + let playState = QPlayAutoManager.shared.currentPlayState + let isConnected = QPlayAutoManager.shared.isConnected + + var state = "unknown" + switch playState { + case .playing: + state = "playing" + case .pause: + state = "paused" + case .stop: + state = "stopped" + default: + state = "unknown" + } + + let result: [String: Any] = [ + "success": true, + "state": state, + "connected": isConnected + ] + + let jsonData = try JSONSerialization.data(withJSONObject: result) + return String(data: jsonData, encoding: .utf8) ?? "{}" + } +} + +private class QQMusicGetCurrentSongHandler: FunctionHandler { + func handle(arguments: [String: Any]) async throws -> String { + var result: [String: Any] + + if let currentSong = QPlayAutoManager.shared.currentSong { + result = [ + "success": true, + "song": [ + "id": currentSong.id ?? "", + "name": currentSong.name ?? "", + "artist": currentSong.singer?.name ?? "", + "album": currentSong.album ?? "", + "duration": currentSong.duration + ] + ] + } else { + result = ["success": false, "error": "No current song"] + } + + let jsonData = try JSONSerialization.data(withJSONObject: result) + return String(data: jsonData, encoding: .utf8) ?? "{}" + } +} + +private class QQMusicGetPlayTimeHandler: FunctionHandler { + func handle(arguments: [String: Any]) async throws -> String { + let currentProgress = QPlayAutoManager.shared.currentProgress + let currentSong = QPlayAutoManager.shared.currentSong + let totalDuration = currentSong?.duration ?? 0 + + let result: [String: Any] = [ + "success": true, + "current_time": currentProgress, + "total_time": totalDuration + ] + + let jsonData = try JSONSerialization.data(withJSONObject: result) + return String(data: jsonData, encoding: .utf8) ?? "{}" + } +} diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/Info.plist b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/Info.plist index e6de23ef5..8f986d715 100644 --- a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/Info.plist +++ b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/Info.plist @@ -6,13 +6,13 @@ BinaryPath - libQPlayAutoSDK-x86_64.a + libQPlayAutoSDK_x86_64.a HeadersPath Headers LibraryIdentifier ios-x86_64-simulator LibraryPath - libQPlayAutoSDK-x86_64.a + libQPlayAutoSDK_x86_64.a SupportedArchitectures x86_64 @@ -24,13 +24,13 @@ BinaryPath - libQPlayAutoSDK-arm64.a + libQPlayAutoSDK_arm64.a HeadersPath Headers LibraryIdentifier ios-arm64 LibraryPath - libQPlayAutoSDK-arm64.a + libQPlayAutoSDK_arm64.a SupportedArchitectures arm64 diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/include/QPlayAutoDefine.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/QPlayAutoDefine.h similarity index 100% rename from local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/include/QPlayAutoDefine.h rename to local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/QPlayAutoDefine.h diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/QPlayAutoSDK.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/QPlayAutoSDK.h index ebdf38741..da332dc87 100644 --- a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/QPlayAutoSDK.h +++ b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/QPlayAutoSDK.h @@ -1,7 +1,188 @@ // // QPlayAutoSDK.h -// QPlayAutoSDK Umbrella Header +// QPlayAutoSDK // +// Created by travisli(李鞠佑) on 2018/11/5. +// Copyright © 2018年 腾讯音乐. All rights reserved. +// + +#import +#import "QPlayAutoDefine.h" + +#define APP_DEVICE_TYPE (3) + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^QPlayAutoResultItemsBlock)(NSInteger errorCode,NSArray *_Nullable items); +typedef void (^QPlayAutoResultParentItemBlock)(NSInteger errorCode,QPlayAutoListItem *parentItem); + +extern NSString const * QPlayAutoSDKVersion; + +@protocol QPlayAutoSDKDelegate + +//连接状态变化回调 +- (void)onQPlayAutoConnectStateChanged:(QPlayAutoConnectState)newState; +//播放状态状态变化回调 +- (void)onQPlayAutoPlayStateChanged:(QPlayAutoPlayState)playState song:(QPlayAutoListItem *)song position:(NSInteger)position; +//歌曲播放进度 +- (void)onQPlayAutoPlayProgressChanged:(QPlayAutoListItem *)song progress:(NSTimeInterval)progress duration:(NSTimeInterval)duration; +//歌曲收藏状态变化 +- (void)onSongFavoriteStateChange:(NSString*)songID isFavorite:(BOOL)isFavorite; +//播放状态事件变化 +- (void)onPlayModeChange:(QPlayAutoPlayMode)playMode; +//定时关闭事件 +- (void)onPlayPausedByTimeoff; +//登陆状态 +- (void)onLoginStateDidChanged:(BOOL)isLoginOK; +@end + + + +@interface QPlayAutoSDK : NSObject + +/// 注册App +/// @param name 名称 +/// @param brand 品牌 +/// @param deviceId ? +/// @param scheme 授权成功后Q音跳转合作方的scheme +/// @param appId Q音分配的Id +/// @param secretKey 合作方私钥 +/// @param bundleId 合作方包名 ++ (void)registerAppWithName:(NSString *)name brand:(NSString *)brand deviceId:(NSString *)deviceId scheme:(NSString *)scheme appId:(NSString *)appId secretKey:(NSString *)secretKey bundleId:(NSString *)bundleId; + +/// 播放状态 ++ (QPlayAutoPlayMode)currentPlayMode; +/// 当前歌曲 ++ (QPlayAutoListItem *_Nullable)currentSong; +/// 当前播放状态 ++ (QPlayAutoPlayState)currentPlayState; +/// 当前播放进度 ++ (NSTimeInterval)currentProgress; +/// QQ音乐是否登录 ++ (BOOL)isLoginOK; +/// 检查QQ音乐是否已安装 ++ (BOOL)isQQMusicInstalled; +/// 是否已连接 ++ (BOOL)isConnected; +/// 连接中 ++ (BOOL)isConnecting; +///QQ音乐设备信息 ++ (NSDictionary *)deviceInfo; + ++(NSString *)openId; ++(NSString *)openToken; + + +///是否可以处理回调url ++ (BOOL)canHandleOpenURL:(NSURL *)url; +///处理回调url ++ (BOOL)handleOpenURL:(NSURL *)url; + +/// 回调代理 ++ (void)setDelegate:(id) delegate; + + +/// 拉端连接QPlay +/// - Parameter forceLogin: 是否强制登录 ++ (void)connectAndForceLogin:(BOOL)forceLogin; +/// 停止 ++ (void)stop; + + +/// 二次热启动连接(需要联系Q音打开此功能才能使用) +/// - Parameters: +/// - timeout: 超时时间 +/// - completion: 回调 ++ (void)reconnectWithTimeout:(NSTimeInterval)timeout completion:(QPlayAutoRequestFinishBlock)completion; + +/// 跳转QQ音乐登录 +/// @param bundleId 合作方bundleId +/// @param callbackUrl 跳转合作方url ++ (BOOL)loginQQMusicWithBundleId:(NSString *)bundleId callbackUrl:(NSString *)callbackUrl; + + +/// 获取数据 +/// @param parent 父 +/// @param pageIndex 页码 +/// @param pageSize 页大小 +/// @param completion 回调 ++ (void)getDataItemsFromParent:(QPlayAutoListItem *)parent pageIndex:(NSUInteger)pageIndex pageSize:(NSUInteger)pageSize completion:(QPlayAutoResultParentItemBlock)completion; + + +/// 设置播放模式 +/// @param playMode 播放模式 +/// @param block 回调 ++ (NSInteger)setPlayMode:(QPlayAutoPlayMode)playMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; + + +/// 设置播放整首还是高潮 +/// @param assencceMode 高潮还是整首 +/// @param block 回调 ++ (NSInteger)setAssenceMode:(QPlayAutoAssenceMode)assencceMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; + +/// 收藏/取消收藏(歌曲id) +/// @param song 歌曲 +/// @param isFavorite 收藏/取消收藏 +/// @param completion 回调 ++ (void)setFavoriteStateWithSong:(QPlayAutoListItem *)song isFavorite:(BOOL)isFavorite completion:(void (^)(NSInteger errorCode))completion; + +/// 播放歌曲 +/// @param songList 歌曲列表 +/// @param playIndex 播放索引 +/// @param completion 回调 ++ (void)playAtIndex:(NSArray *)songList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; + + +/// 通过歌曲Mid列表播放歌曲 +/// @param songMidList 歌曲Mid列表 +/// @param playIndex 播放索引 +/// @param completion 回调 ++ (void)playSongMidAtIndex:(NSArray *)songMidList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; + + +///播放下一首 ++ (void)playerPlayNextWithCompletion:(void (^)(NSInteger errorCode))completion; + +///播放上一首 ++ (void)playerPlayPrevWithCompletion:(void (^)(NSInteger errorCode))completion; + +///播放暂停 ++ (void)playerPlayPause; + +///播放恢复 ++ (void)playerPlayResumeWithCompletion:(void (^)(NSInteger errorCode))completion; + +///Seek到指定位置 ++ (void)playerSeek:(NSInteger)position; + + +/// 搜索歌曲 +/// @param keyword 关键词 +/// @param type 搜索类型 +/// @param firstPage 是否第一页 +/// @param completion 回调 ++ (NSInteger)search:(NSString *)keyword + type:(QPlayAutoSearchType)type + firstPage:(BOOL)firstPage + completion:(QPlayAutoResultItemsBlock)completion; + +/// 相似歌曲 +/// @param song 歌曲 +/// @param completion 回调 ++ (void)requestSimilarWithSong:(QPlayAutoListItem *)song completion:(QPlayAutoResultItemsBlock)completion; + + +/// 查询歌词 +/// @param song 歌曲 +/// @param completion 回调 ++ (void)requestLyricWithSong:(QPlayAutoListItem *)song completion:(void (^)(NSInteger errorCode,QPlayAutoLyric *_Nullable lyric))completion; + + +/// 获取特定歌曲列表 +/// @param type 列表类型 +/// @param completion 回调 ++ (void)requestSonglistWithType:(QPlayAutoSongListType)type completion:(QPlayAutoResultItemsBlock)completion; + +@end -#import "include/QPlayAutoSDK.h" -#import "include/QPlayAutoDefine.h" +NS_ASSUME_NONNULL_END diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/include/QPlayAutoSDK.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/include/QPlayAutoSDK.h deleted file mode 100644 index da332dc87..000000000 --- a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/include/QPlayAutoSDK.h +++ /dev/null @@ -1,188 +0,0 @@ -// -// QPlayAutoSDK.h -// QPlayAutoSDK -// -// Created by travisli(李鞠佑) on 2018/11/5. -// Copyright © 2018年 腾讯音乐. All rights reserved. -// - -#import -#import "QPlayAutoDefine.h" - -#define APP_DEVICE_TYPE (3) - -NS_ASSUME_NONNULL_BEGIN - -typedef void (^QPlayAutoResultItemsBlock)(NSInteger errorCode,NSArray *_Nullable items); -typedef void (^QPlayAutoResultParentItemBlock)(NSInteger errorCode,QPlayAutoListItem *parentItem); - -extern NSString const * QPlayAutoSDKVersion; - -@protocol QPlayAutoSDKDelegate - -//连接状态变化回调 -- (void)onQPlayAutoConnectStateChanged:(QPlayAutoConnectState)newState; -//播放状态状态变化回调 -- (void)onQPlayAutoPlayStateChanged:(QPlayAutoPlayState)playState song:(QPlayAutoListItem *)song position:(NSInteger)position; -//歌曲播放进度 -- (void)onQPlayAutoPlayProgressChanged:(QPlayAutoListItem *)song progress:(NSTimeInterval)progress duration:(NSTimeInterval)duration; -//歌曲收藏状态变化 -- (void)onSongFavoriteStateChange:(NSString*)songID isFavorite:(BOOL)isFavorite; -//播放状态事件变化 -- (void)onPlayModeChange:(QPlayAutoPlayMode)playMode; -//定时关闭事件 -- (void)onPlayPausedByTimeoff; -//登陆状态 -- (void)onLoginStateDidChanged:(BOOL)isLoginOK; -@end - - - -@interface QPlayAutoSDK : NSObject - -/// 注册App -/// @param name 名称 -/// @param brand 品牌 -/// @param deviceId ? -/// @param scheme 授权成功后Q音跳转合作方的scheme -/// @param appId Q音分配的Id -/// @param secretKey 合作方私钥 -/// @param bundleId 合作方包名 -+ (void)registerAppWithName:(NSString *)name brand:(NSString *)brand deviceId:(NSString *)deviceId scheme:(NSString *)scheme appId:(NSString *)appId secretKey:(NSString *)secretKey bundleId:(NSString *)bundleId; - -/// 播放状态 -+ (QPlayAutoPlayMode)currentPlayMode; -/// 当前歌曲 -+ (QPlayAutoListItem *_Nullable)currentSong; -/// 当前播放状态 -+ (QPlayAutoPlayState)currentPlayState; -/// 当前播放进度 -+ (NSTimeInterval)currentProgress; -/// QQ音乐是否登录 -+ (BOOL)isLoginOK; -/// 检查QQ音乐是否已安装 -+ (BOOL)isQQMusicInstalled; -/// 是否已连接 -+ (BOOL)isConnected; -/// 连接中 -+ (BOOL)isConnecting; -///QQ音乐设备信息 -+ (NSDictionary *)deviceInfo; - -+(NSString *)openId; -+(NSString *)openToken; - - -///是否可以处理回调url -+ (BOOL)canHandleOpenURL:(NSURL *)url; -///处理回调url -+ (BOOL)handleOpenURL:(NSURL *)url; - -/// 回调代理 -+ (void)setDelegate:(id) delegate; - - -/// 拉端连接QPlay -/// - Parameter forceLogin: 是否强制登录 -+ (void)connectAndForceLogin:(BOOL)forceLogin; -/// 停止 -+ (void)stop; - - -/// 二次热启动连接(需要联系Q音打开此功能才能使用) -/// - Parameters: -/// - timeout: 超时时间 -/// - completion: 回调 -+ (void)reconnectWithTimeout:(NSTimeInterval)timeout completion:(QPlayAutoRequestFinishBlock)completion; - -/// 跳转QQ音乐登录 -/// @param bundleId 合作方bundleId -/// @param callbackUrl 跳转合作方url -+ (BOOL)loginQQMusicWithBundleId:(NSString *)bundleId callbackUrl:(NSString *)callbackUrl; - - -/// 获取数据 -/// @param parent 父 -/// @param pageIndex 页码 -/// @param pageSize 页大小 -/// @param completion 回调 -+ (void)getDataItemsFromParent:(QPlayAutoListItem *)parent pageIndex:(NSUInteger)pageIndex pageSize:(NSUInteger)pageSize completion:(QPlayAutoResultParentItemBlock)completion; - - -/// 设置播放模式 -/// @param playMode 播放模式 -/// @param block 回调 -+ (NSInteger)setPlayMode:(QPlayAutoPlayMode)playMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; - - -/// 设置播放整首还是高潮 -/// @param assencceMode 高潮还是整首 -/// @param block 回调 -+ (NSInteger)setAssenceMode:(QPlayAutoAssenceMode)assencceMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; - -/// 收藏/取消收藏(歌曲id) -/// @param song 歌曲 -/// @param isFavorite 收藏/取消收藏 -/// @param completion 回调 -+ (void)setFavoriteStateWithSong:(QPlayAutoListItem *)song isFavorite:(BOOL)isFavorite completion:(void (^)(NSInteger errorCode))completion; - -/// 播放歌曲 -/// @param songList 歌曲列表 -/// @param playIndex 播放索引 -/// @param completion 回调 -+ (void)playAtIndex:(NSArray *)songList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; - - -/// 通过歌曲Mid列表播放歌曲 -/// @param songMidList 歌曲Mid列表 -/// @param playIndex 播放索引 -/// @param completion 回调 -+ (void)playSongMidAtIndex:(NSArray *)songMidList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; - - -///播放下一首 -+ (void)playerPlayNextWithCompletion:(void (^)(NSInteger errorCode))completion; - -///播放上一首 -+ (void)playerPlayPrevWithCompletion:(void (^)(NSInteger errorCode))completion; - -///播放暂停 -+ (void)playerPlayPause; - -///播放恢复 -+ (void)playerPlayResumeWithCompletion:(void (^)(NSInteger errorCode))completion; - -///Seek到指定位置 -+ (void)playerSeek:(NSInteger)position; - - -/// 搜索歌曲 -/// @param keyword 关键词 -/// @param type 搜索类型 -/// @param firstPage 是否第一页 -/// @param completion 回调 -+ (NSInteger)search:(NSString *)keyword - type:(QPlayAutoSearchType)type - firstPage:(BOOL)firstPage - completion:(QPlayAutoResultItemsBlock)completion; - -/// 相似歌曲 -/// @param song 歌曲 -/// @param completion 回调 -+ (void)requestSimilarWithSong:(QPlayAutoListItem *)song completion:(QPlayAutoResultItemsBlock)completion; - - -/// 查询歌词 -/// @param song 歌曲 -/// @param completion 回调 -+ (void)requestLyricWithSong:(QPlayAutoListItem *)song completion:(void (^)(NSInteger errorCode,QPlayAutoLyric *_Nullable lyric))completion; - - -/// 获取特定歌曲列表 -/// @param type 列表类型 -/// @param completion 回调 -+ (void)requestSonglistWithType:(QPlayAutoSongListType)type completion:(QPlayAutoResultItemsBlock)completion; - -@end - -NS_ASSUME_NONNULL_END diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/module.modulemap b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/module.modulemap index 93a770bad..a31ac1264 100644 --- a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/module.modulemap +++ b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/module.modulemap @@ -1,5 +1,8 @@ -framework module QPlayAutoSDK { - umbrella header "QPlayAutoSDK.h" +module QPlayAutoSDK { + header "QPlayAutoSDK.h" + header "QPlayAutoDefine.h" + export * - module * { export * } + + link "QPlayAutoSDK" } diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/libQPlayAutoSDK-arm64.a b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/libQPlayAutoSDK_arm64.a similarity index 100% rename from local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/libQPlayAutoSDK-arm64.a rename to local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/libQPlayAutoSDK_arm64.a diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/include/QPlayAutoDefine.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/QPlayAutoDefine.h similarity index 100% rename from local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/include/QPlayAutoDefine.h rename to local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/QPlayAutoDefine.h diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/QPlayAutoSDK.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/QPlayAutoSDK.h index ebdf38741..da332dc87 100644 --- a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/QPlayAutoSDK.h +++ b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/QPlayAutoSDK.h @@ -1,7 +1,188 @@ // // QPlayAutoSDK.h -// QPlayAutoSDK Umbrella Header +// QPlayAutoSDK // +// Created by travisli(李鞠佑) on 2018/11/5. +// Copyright © 2018年 腾讯音乐. All rights reserved. +// + +#import +#import "QPlayAutoDefine.h" + +#define APP_DEVICE_TYPE (3) + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^QPlayAutoResultItemsBlock)(NSInteger errorCode,NSArray *_Nullable items); +typedef void (^QPlayAutoResultParentItemBlock)(NSInteger errorCode,QPlayAutoListItem *parentItem); + +extern NSString const * QPlayAutoSDKVersion; + +@protocol QPlayAutoSDKDelegate + +//连接状态变化回调 +- (void)onQPlayAutoConnectStateChanged:(QPlayAutoConnectState)newState; +//播放状态状态变化回调 +- (void)onQPlayAutoPlayStateChanged:(QPlayAutoPlayState)playState song:(QPlayAutoListItem *)song position:(NSInteger)position; +//歌曲播放进度 +- (void)onQPlayAutoPlayProgressChanged:(QPlayAutoListItem *)song progress:(NSTimeInterval)progress duration:(NSTimeInterval)duration; +//歌曲收藏状态变化 +- (void)onSongFavoriteStateChange:(NSString*)songID isFavorite:(BOOL)isFavorite; +//播放状态事件变化 +- (void)onPlayModeChange:(QPlayAutoPlayMode)playMode; +//定时关闭事件 +- (void)onPlayPausedByTimeoff; +//登陆状态 +- (void)onLoginStateDidChanged:(BOOL)isLoginOK; +@end + + + +@interface QPlayAutoSDK : NSObject + +/// 注册App +/// @param name 名称 +/// @param brand 品牌 +/// @param deviceId ? +/// @param scheme 授权成功后Q音跳转合作方的scheme +/// @param appId Q音分配的Id +/// @param secretKey 合作方私钥 +/// @param bundleId 合作方包名 ++ (void)registerAppWithName:(NSString *)name brand:(NSString *)brand deviceId:(NSString *)deviceId scheme:(NSString *)scheme appId:(NSString *)appId secretKey:(NSString *)secretKey bundleId:(NSString *)bundleId; + +/// 播放状态 ++ (QPlayAutoPlayMode)currentPlayMode; +/// 当前歌曲 ++ (QPlayAutoListItem *_Nullable)currentSong; +/// 当前播放状态 ++ (QPlayAutoPlayState)currentPlayState; +/// 当前播放进度 ++ (NSTimeInterval)currentProgress; +/// QQ音乐是否登录 ++ (BOOL)isLoginOK; +/// 检查QQ音乐是否已安装 ++ (BOOL)isQQMusicInstalled; +/// 是否已连接 ++ (BOOL)isConnected; +/// 连接中 ++ (BOOL)isConnecting; +///QQ音乐设备信息 ++ (NSDictionary *)deviceInfo; + ++(NSString *)openId; ++(NSString *)openToken; + + +///是否可以处理回调url ++ (BOOL)canHandleOpenURL:(NSURL *)url; +///处理回调url ++ (BOOL)handleOpenURL:(NSURL *)url; + +/// 回调代理 ++ (void)setDelegate:(id) delegate; + + +/// 拉端连接QPlay +/// - Parameter forceLogin: 是否强制登录 ++ (void)connectAndForceLogin:(BOOL)forceLogin; +/// 停止 ++ (void)stop; + + +/// 二次热启动连接(需要联系Q音打开此功能才能使用) +/// - Parameters: +/// - timeout: 超时时间 +/// - completion: 回调 ++ (void)reconnectWithTimeout:(NSTimeInterval)timeout completion:(QPlayAutoRequestFinishBlock)completion; + +/// 跳转QQ音乐登录 +/// @param bundleId 合作方bundleId +/// @param callbackUrl 跳转合作方url ++ (BOOL)loginQQMusicWithBundleId:(NSString *)bundleId callbackUrl:(NSString *)callbackUrl; + + +/// 获取数据 +/// @param parent 父 +/// @param pageIndex 页码 +/// @param pageSize 页大小 +/// @param completion 回调 ++ (void)getDataItemsFromParent:(QPlayAutoListItem *)parent pageIndex:(NSUInteger)pageIndex pageSize:(NSUInteger)pageSize completion:(QPlayAutoResultParentItemBlock)completion; + + +/// 设置播放模式 +/// @param playMode 播放模式 +/// @param block 回调 ++ (NSInteger)setPlayMode:(QPlayAutoPlayMode)playMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; + + +/// 设置播放整首还是高潮 +/// @param assencceMode 高潮还是整首 +/// @param block 回调 ++ (NSInteger)setAssenceMode:(QPlayAutoAssenceMode)assencceMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; + +/// 收藏/取消收藏(歌曲id) +/// @param song 歌曲 +/// @param isFavorite 收藏/取消收藏 +/// @param completion 回调 ++ (void)setFavoriteStateWithSong:(QPlayAutoListItem *)song isFavorite:(BOOL)isFavorite completion:(void (^)(NSInteger errorCode))completion; + +/// 播放歌曲 +/// @param songList 歌曲列表 +/// @param playIndex 播放索引 +/// @param completion 回调 ++ (void)playAtIndex:(NSArray *)songList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; + + +/// 通过歌曲Mid列表播放歌曲 +/// @param songMidList 歌曲Mid列表 +/// @param playIndex 播放索引 +/// @param completion 回调 ++ (void)playSongMidAtIndex:(NSArray *)songMidList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; + + +///播放下一首 ++ (void)playerPlayNextWithCompletion:(void (^)(NSInteger errorCode))completion; + +///播放上一首 ++ (void)playerPlayPrevWithCompletion:(void (^)(NSInteger errorCode))completion; + +///播放暂停 ++ (void)playerPlayPause; + +///播放恢复 ++ (void)playerPlayResumeWithCompletion:(void (^)(NSInteger errorCode))completion; + +///Seek到指定位置 ++ (void)playerSeek:(NSInteger)position; + + +/// 搜索歌曲 +/// @param keyword 关键词 +/// @param type 搜索类型 +/// @param firstPage 是否第一页 +/// @param completion 回调 ++ (NSInteger)search:(NSString *)keyword + type:(QPlayAutoSearchType)type + firstPage:(BOOL)firstPage + completion:(QPlayAutoResultItemsBlock)completion; + +/// 相似歌曲 +/// @param song 歌曲 +/// @param completion 回调 ++ (void)requestSimilarWithSong:(QPlayAutoListItem *)song completion:(QPlayAutoResultItemsBlock)completion; + + +/// 查询歌词 +/// @param song 歌曲 +/// @param completion 回调 ++ (void)requestLyricWithSong:(QPlayAutoListItem *)song completion:(void (^)(NSInteger errorCode,QPlayAutoLyric *_Nullable lyric))completion; + + +/// 获取特定歌曲列表 +/// @param type 列表类型 +/// @param completion 回调 ++ (void)requestSonglistWithType:(QPlayAutoSongListType)type completion:(QPlayAutoResultItemsBlock)completion; + +@end -#import "include/QPlayAutoSDK.h" -#import "include/QPlayAutoDefine.h" +NS_ASSUME_NONNULL_END diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/include/QPlayAutoSDK.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/include/QPlayAutoSDK.h deleted file mode 100644 index da332dc87..000000000 --- a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/include/QPlayAutoSDK.h +++ /dev/null @@ -1,188 +0,0 @@ -// -// QPlayAutoSDK.h -// QPlayAutoSDK -// -// Created by travisli(李鞠佑) on 2018/11/5. -// Copyright © 2018年 腾讯音乐. All rights reserved. -// - -#import -#import "QPlayAutoDefine.h" - -#define APP_DEVICE_TYPE (3) - -NS_ASSUME_NONNULL_BEGIN - -typedef void (^QPlayAutoResultItemsBlock)(NSInteger errorCode,NSArray *_Nullable items); -typedef void (^QPlayAutoResultParentItemBlock)(NSInteger errorCode,QPlayAutoListItem *parentItem); - -extern NSString const * QPlayAutoSDKVersion; - -@protocol QPlayAutoSDKDelegate - -//连接状态变化回调 -- (void)onQPlayAutoConnectStateChanged:(QPlayAutoConnectState)newState; -//播放状态状态变化回调 -- (void)onQPlayAutoPlayStateChanged:(QPlayAutoPlayState)playState song:(QPlayAutoListItem *)song position:(NSInteger)position; -//歌曲播放进度 -- (void)onQPlayAutoPlayProgressChanged:(QPlayAutoListItem *)song progress:(NSTimeInterval)progress duration:(NSTimeInterval)duration; -//歌曲收藏状态变化 -- (void)onSongFavoriteStateChange:(NSString*)songID isFavorite:(BOOL)isFavorite; -//播放状态事件变化 -- (void)onPlayModeChange:(QPlayAutoPlayMode)playMode; -//定时关闭事件 -- (void)onPlayPausedByTimeoff; -//登陆状态 -- (void)onLoginStateDidChanged:(BOOL)isLoginOK; -@end - - - -@interface QPlayAutoSDK : NSObject - -/// 注册App -/// @param name 名称 -/// @param brand 品牌 -/// @param deviceId ? -/// @param scheme 授权成功后Q音跳转合作方的scheme -/// @param appId Q音分配的Id -/// @param secretKey 合作方私钥 -/// @param bundleId 合作方包名 -+ (void)registerAppWithName:(NSString *)name brand:(NSString *)brand deviceId:(NSString *)deviceId scheme:(NSString *)scheme appId:(NSString *)appId secretKey:(NSString *)secretKey bundleId:(NSString *)bundleId; - -/// 播放状态 -+ (QPlayAutoPlayMode)currentPlayMode; -/// 当前歌曲 -+ (QPlayAutoListItem *_Nullable)currentSong; -/// 当前播放状态 -+ (QPlayAutoPlayState)currentPlayState; -/// 当前播放进度 -+ (NSTimeInterval)currentProgress; -/// QQ音乐是否登录 -+ (BOOL)isLoginOK; -/// 检查QQ音乐是否已安装 -+ (BOOL)isQQMusicInstalled; -/// 是否已连接 -+ (BOOL)isConnected; -/// 连接中 -+ (BOOL)isConnecting; -///QQ音乐设备信息 -+ (NSDictionary *)deviceInfo; - -+(NSString *)openId; -+(NSString *)openToken; - - -///是否可以处理回调url -+ (BOOL)canHandleOpenURL:(NSURL *)url; -///处理回调url -+ (BOOL)handleOpenURL:(NSURL *)url; - -/// 回调代理 -+ (void)setDelegate:(id) delegate; - - -/// 拉端连接QPlay -/// - Parameter forceLogin: 是否强制登录 -+ (void)connectAndForceLogin:(BOOL)forceLogin; -/// 停止 -+ (void)stop; - - -/// 二次热启动连接(需要联系Q音打开此功能才能使用) -/// - Parameters: -/// - timeout: 超时时间 -/// - completion: 回调 -+ (void)reconnectWithTimeout:(NSTimeInterval)timeout completion:(QPlayAutoRequestFinishBlock)completion; - -/// 跳转QQ音乐登录 -/// @param bundleId 合作方bundleId -/// @param callbackUrl 跳转合作方url -+ (BOOL)loginQQMusicWithBundleId:(NSString *)bundleId callbackUrl:(NSString *)callbackUrl; - - -/// 获取数据 -/// @param parent 父 -/// @param pageIndex 页码 -/// @param pageSize 页大小 -/// @param completion 回调 -+ (void)getDataItemsFromParent:(QPlayAutoListItem *)parent pageIndex:(NSUInteger)pageIndex pageSize:(NSUInteger)pageSize completion:(QPlayAutoResultParentItemBlock)completion; - - -/// 设置播放模式 -/// @param playMode 播放模式 -/// @param block 回调 -+ (NSInteger)setPlayMode:(QPlayAutoPlayMode)playMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; - - -/// 设置播放整首还是高潮 -/// @param assencceMode 高潮还是整首 -/// @param block 回调 -+ (NSInteger)setAssenceMode:(QPlayAutoAssenceMode)assencceMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; - -/// 收藏/取消收藏(歌曲id) -/// @param song 歌曲 -/// @param isFavorite 收藏/取消收藏 -/// @param completion 回调 -+ (void)setFavoriteStateWithSong:(QPlayAutoListItem *)song isFavorite:(BOOL)isFavorite completion:(void (^)(NSInteger errorCode))completion; - -/// 播放歌曲 -/// @param songList 歌曲列表 -/// @param playIndex 播放索引 -/// @param completion 回调 -+ (void)playAtIndex:(NSArray *)songList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; - - -/// 通过歌曲Mid列表播放歌曲 -/// @param songMidList 歌曲Mid列表 -/// @param playIndex 播放索引 -/// @param completion 回调 -+ (void)playSongMidAtIndex:(NSArray *)songMidList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; - - -///播放下一首 -+ (void)playerPlayNextWithCompletion:(void (^)(NSInteger errorCode))completion; - -///播放上一首 -+ (void)playerPlayPrevWithCompletion:(void (^)(NSInteger errorCode))completion; - -///播放暂停 -+ (void)playerPlayPause; - -///播放恢复 -+ (void)playerPlayResumeWithCompletion:(void (^)(NSInteger errorCode))completion; - -///Seek到指定位置 -+ (void)playerSeek:(NSInteger)position; - - -/// 搜索歌曲 -/// @param keyword 关键词 -/// @param type 搜索类型 -/// @param firstPage 是否第一页 -/// @param completion 回调 -+ (NSInteger)search:(NSString *)keyword - type:(QPlayAutoSearchType)type - firstPage:(BOOL)firstPage - completion:(QPlayAutoResultItemsBlock)completion; - -/// 相似歌曲 -/// @param song 歌曲 -/// @param completion 回调 -+ (void)requestSimilarWithSong:(QPlayAutoListItem *)song completion:(QPlayAutoResultItemsBlock)completion; - - -/// 查询歌词 -/// @param song 歌曲 -/// @param completion 回调 -+ (void)requestLyricWithSong:(QPlayAutoListItem *)song completion:(void (^)(NSInteger errorCode,QPlayAutoLyric *_Nullable lyric))completion; - - -/// 获取特定歌曲列表 -/// @param type 列表类型 -/// @param completion 回调 -+ (void)requestSonglistWithType:(QPlayAutoSongListType)type completion:(QPlayAutoResultItemsBlock)completion; - -@end - -NS_ASSUME_NONNULL_END diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/module.modulemap b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/module.modulemap index 93a770bad..a31ac1264 100644 --- a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/module.modulemap +++ b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/module.modulemap @@ -1,5 +1,8 @@ -framework module QPlayAutoSDK { - umbrella header "QPlayAutoSDK.h" +module QPlayAutoSDK { + header "QPlayAutoSDK.h" + header "QPlayAutoDefine.h" + export * - module * { export * } + + link "QPlayAutoSDK" } diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/libQPlayAutoSDK-x86_64.a b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/libQPlayAutoSDK_x86_64.a similarity index 100% rename from local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/libQPlayAutoSDK-x86_64.a rename to local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/libQPlayAutoSDK_x86_64.a diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/Headers/include/QPlayAutoDefine.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/Headers/include/QPlayAutoDefine.h deleted file mode 100644 index b1ebee15a..000000000 --- a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/Headers/include/QPlayAutoDefine.h +++ /dev/null @@ -1,238 +0,0 @@ -// -// QPlayAutoDefine.h -// QPlayAutoSDK -// -// Created by travisli(李鞠佑) on 2018/11/17. -// Copyright © 2018年 腾讯音乐. All rights reserved. -// - -#ifndef QPlayAutoDefine_h -#define QPlayAutoDefine_h - -extern NSString *const kQPlayAutoItemRootID; -extern NSString *const kQPlayAutoArgument_Count; -extern NSString *const kQPlayAutoArgument_PageIndex; -extern NSString *const kQPlayAutoArgument_ParentID; -extern NSString *const kQPlayAutoArgument_Lists; -extern NSString *const kQPlayAutoArgument_PlayMode; -extern NSString *const kQPlayAutoArgument_IsFav; -extern NSString *const kQPlayAutoArgument_Position; -extern NSString *const kQPlayAutoArgument_Song; -extern NSString *const kQPlayAutoArgument_SongID; -extern NSString *const kQPlayAutoArgument_State; -extern NSString *const kQPlayAutoArgument_Error; - -/* - QPlayAuto错误 - */ -typedef NS_ENUM(NSUInteger, QPlayAutoError) -{ - QPlayAuto_OK=0, //成功 - QPlayAuto_QueryAutoFailed=100, //查询车机信息失败 - QPlayAuto_QueryMobileFailed=101, //查询移动设备失败 - QPlayAuto_QuerySongsFailed_WithoutID=102, //查询歌单数据失败,父 ID 不存在 - QPlayAuto_QuerySongsFailed_NoNetwork=103, //查询歌单数据失败,移动设备网络不通,无法下载数据 - QPlayAuto_QuerySongsFailed_Unknow=104, //查询歌单数据失败,原因未知 - QPlayAuto_SongIDError=105, //歌曲 ID 不存在 - QPlayAuto_ReadError=106, //读取数据错误 - QPlayAuto_ParamError=107, //参数错误 - QPlayAuto_SystemError=108, //系统调用错误 - QPlayAuto_CopyRightError=109, //无法播放,没有版权 - QPlayAuto_LoginError=110, //无法读取,没有登录 - QPlayAuto_PcmRepeat=111, //PCM 请求重复 - QPlayAuto_NoPermission=112, //没有权限 - QPlayAuto_NeedBuy = 113, //无法播放(数字专辑) - QPlayAuto_NotSupportFormat=114, //无法播放(不支持格式) - QPlayAuto_NeedAuth=115, //需要授权 - QPlayAuto_NeedVIP = 116, //无法播放(需要购买VIP) - QPlayAuto_TryListen = 117, //试听歌曲,购买听完整版 - QPlayAuto_TrafficAlert = 118, //无法播放(流量弹窗阻断) - QPlayAuto_OnlyWifi = 119, //无法播放(仅Wifi弹窗阻断) - QPlayAuto_AlreadyConnected=120, //已经连接车机 - QPlayAuto_SeekError = 121, //拖拽进度错误 - QPlayAuto_NoListenRight = 122, //无法播放(无版权) - QPlayAuto_SongNotMatch=123, //歌曲不匹配 - QPlayAuto_Disconnect=124, //连接已断开 -}; - -/** - QPlayAuto连接状态 - */ -typedef NS_ENUM(NSUInteger, QPlayAutoConnectState) -{ - QPlayAutoConnectState_Connected = 0, //连接成功 - QPlayAutoConnectState_Disconnect = 1, //断开连接 - QPlayAutoConnectState_Failed = -1, //连接失败 - QPlayAutoConnectState_Cancel = -2, //连接取消 -}; - -/* - QPlayAutoListItem类型 - */ -typedef NS_ENUM(NSUInteger, QPlayAutoListItemType) -{ - QPlayAutoListItemType_Song = 1, //歌曲 - QPlayAutoListItemType_Normal = 2, //普通目录 - QPlayAutoListItemType_Radio = 3, //电台 - QPlayAutoListItemType_Folder = 4, //歌单 - QPlayAutoListItemType_Album = 5, //专辑 -}; - -typedef NS_ENUM(NSUInteger, QPlayAutoSongListType) -{ - QPlayAutoSongListType_Daily = 108, //每日30首 -}; - - -/** - QPlayAuto播放状态 - */ -typedef NS_ENUM(NSUInteger, QPlayAutoPlayState) -{ - QPlayAutoPlayState_Stop=0, //停止 - QPlayAutoPlayState_Playing=1, //播放 - QPlayAutoPlayState_Pause=2 //暂停 -}; - -typedef NS_ENUM(NSInteger, QPlayAutoAssenceMode) -{ - QPlayAutoAssenceMode_Full = 0, // 默认整首播放 - QPlayAutoAssenceMode_Part = 1, // 仅播放精华片段 -}; - -/** - QPlayAuto播放模式 - */ -typedef NS_ENUM(NSUInteger, QPlayAutoPlayMode) -{ - QPlayAutoPlayMode_SequenceCircle=0, //列表循环 - QPlayAutoPlayMode_SingleCircle=1, //单曲循环 - QPlayAutoPlayMode_RandomCircle=2 //随机播放 -}; - -/** - QPlayAuto搜索类型 - */ -typedef NS_ENUM(NSInteger, QPlayAutoSearchType) -{ - QPlayAutoSearchType_Song = 0, //歌曲 - QPlayAutoSearchType_Album = 2, //专辑 - QPlayAutoSearchType_Folder = 3, //歌单 - QPlayAutoSearchType_Composite = 100, //综合 -}; - -typedef NS_ENUM(NSInteger, QPlayAutoVipState) -{ - QPlayAutoVipState_Normal = 0, - QPlayAutoVipState_VIP = 1, - QPlayAutoVipState_SVIP = 2, -}; - -/** - 第三方App信息 - */ -@interface QPlayAutoAppInfo : NSObject - -@property (nonatomic,strong) NSString *deviceId; //AppId -@property (nonatomic,assign) NSInteger deviceType; -@property (nonatomic,strong) NSString *scheme; //跳转scheme -@property (nonatomic,strong) NSString *brand; //品牌 -@property (nonatomic,strong) NSString *name; //名称 -@property (nonatomic,strong) NSString *appId; //名称 -@property (nonatomic,strong) NSString *secretKey; //私钥 -@property (nonatomic,strong) NSString *bundleId; //bundleId -@property (nonatomic,assign) NSInteger qmCommandPort; //Q音接收命令端口 -@property (nonatomic,strong) NSString *qmHost; //Q音接收命令IP -@property (nonatomic,strong) NSDate *lastConnectDate;//上次连接的日期 -@end - -@interface QPlayAutoSinger : NSObject -@property (nonatomic,strong) NSString *ID; //ID -@property (nonatomic,strong) NSString *Mid; //Mid -@property (nonatomic,strong) NSString *name; //名称 -@end - - -/* - QPlayAuto列表项(歌单、电台、排行榜、歌曲、etc) - */ -@interface QPlayAutoListItem: NSObject - -@property (nonatomic,strong) NSString *ID; //ID -@property (nonatomic,strong) NSString *Name; //名称 -@property (nonatomic,strong) NSString *SubName; //副标题 -@property (nonatomic,strong) QPlayAutoSinger *singer; //歌手 -@property (nonatomic,strong) NSString *Album; //专辑 -@property (nonatomic,strong) NSString *Mid; -@property (nonatomic,assign) QPlayAutoVipState vipState; -@property (nonatomic,assign) QPlayAutoListItemType Type; -@property (nonatomic,assign) NSInteger Duration; //时长 -@property (nonatomic,strong) NSString *CoverUri; //封面Uri -@property (nonatomic,assign) NSInteger totalCount; //总数 -@property (nonatomic,assign) BOOL isFav; //是否收藏 -@property (nonatomic,assign) BOOL isOrigin; //是否原唱 -@property (nonatomic,assign) BOOL isNoAudioSource; //无音源 -@property (nonatomic,strong) NSMutableArray *items; //子列表 -@property (nonatomic,weak) QPlayAutoListItem *parentItem; //父节点 - -@property (nonatomic,assign) BOOL isTryListen; //是否试听歌曲 -@property (nonatomic,readonly) BOOL isSong; //歌曲 -@property (nonatomic,readonly) BOOL isFolder;//歌单 -@property (nonatomic,readonly) BOOL isAlbum; //专辑 -@property (nonatomic,readonly) BOOL isRadio; //电台 -@property (nonatomic,readonly) BOOL isDirectory; //普通目录 - -@property (nonatomic,readonly) BOOL isVIP; //VIP歌曲 -@property (nonatomic,readonly) BOOL isSVIP; //SVIP歌曲 - -- (instancetype)initWithDictionary:(NSDictionary*)dict; -- (instancetype)initSongWithId:(NSString *)identifier isFav:(BOOL)isFav; -- (instancetype)initWithId:(NSString *)identifier type:(QPlayAutoListItemType)type; - -//是否是根节点 -- (BOOL)isRoot; - -//是否有更多 -- (BOOL)hasMore; - -- (QPlayAutoListItem*)findItemWithID:(NSString*)ID; - -@end - -/** - QPlayAuto请求回调 - - @param success 是否成功 - @param dict 结果Dictionary - */ -typedef void (^QPlayAutoRequestFinishBlock)(BOOL success, NSDictionary *dict); - - -@interface QPlayAutoRequestBase : NSObject - -/** 请求类型 */ -@property (nonatomic, assign) int type; - -@end - -@interface QPlayAutoSentence : NSObject -@property (nonatomic, assign) NSInteger startTime; -@property (nonatomic, assign) NSInteger duration; -@property (nonatomic, strong) NSString *text; -@property (nonatomic, readonly) NSString *startTimeText; -@property (nonatomic, readonly) NSString *endTimeText; -@end - -@interface QPlayAutoLyric : NSObject -@property(nonatomic,assign) BOOL isTxtType;//歌词是不是纯文本的歌词,没有时间标记 -@property(nonatomic,strong) NSString *songId; -@property(nonatomic,strong) NSString *songName; -@property(nonatomic,strong) NSString *singerName; -@property(nonatomic,strong) NSString *albumName; -@property(nonatomic,readonly) NSString *text;//所有歌词文本 -@property(nonatomic,strong) NSArray *sentences; -- (NSString *)sentenceAtTime:(NSTimeInterval)time; -@end - - -#endif /* QPlayAutoDefine_h */ diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/Headers/include/QPlayAutoSDK.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/Headers/include/QPlayAutoSDK.h deleted file mode 100644 index da332dc87..000000000 --- a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/Headers/include/QPlayAutoSDK.h +++ /dev/null @@ -1,188 +0,0 @@ -// -// QPlayAutoSDK.h -// QPlayAutoSDK -// -// Created by travisli(李鞠佑) on 2018/11/5. -// Copyright © 2018年 腾讯音乐. All rights reserved. -// - -#import -#import "QPlayAutoDefine.h" - -#define APP_DEVICE_TYPE (3) - -NS_ASSUME_NONNULL_BEGIN - -typedef void (^QPlayAutoResultItemsBlock)(NSInteger errorCode,NSArray *_Nullable items); -typedef void (^QPlayAutoResultParentItemBlock)(NSInteger errorCode,QPlayAutoListItem *parentItem); - -extern NSString const * QPlayAutoSDKVersion; - -@protocol QPlayAutoSDKDelegate - -//连接状态变化回调 -- (void)onQPlayAutoConnectStateChanged:(QPlayAutoConnectState)newState; -//播放状态状态变化回调 -- (void)onQPlayAutoPlayStateChanged:(QPlayAutoPlayState)playState song:(QPlayAutoListItem *)song position:(NSInteger)position; -//歌曲播放进度 -- (void)onQPlayAutoPlayProgressChanged:(QPlayAutoListItem *)song progress:(NSTimeInterval)progress duration:(NSTimeInterval)duration; -//歌曲收藏状态变化 -- (void)onSongFavoriteStateChange:(NSString*)songID isFavorite:(BOOL)isFavorite; -//播放状态事件变化 -- (void)onPlayModeChange:(QPlayAutoPlayMode)playMode; -//定时关闭事件 -- (void)onPlayPausedByTimeoff; -//登陆状态 -- (void)onLoginStateDidChanged:(BOOL)isLoginOK; -@end - - - -@interface QPlayAutoSDK : NSObject - -/// 注册App -/// @param name 名称 -/// @param brand 品牌 -/// @param deviceId ? -/// @param scheme 授权成功后Q音跳转合作方的scheme -/// @param appId Q音分配的Id -/// @param secretKey 合作方私钥 -/// @param bundleId 合作方包名 -+ (void)registerAppWithName:(NSString *)name brand:(NSString *)brand deviceId:(NSString *)deviceId scheme:(NSString *)scheme appId:(NSString *)appId secretKey:(NSString *)secretKey bundleId:(NSString *)bundleId; - -/// 播放状态 -+ (QPlayAutoPlayMode)currentPlayMode; -/// 当前歌曲 -+ (QPlayAutoListItem *_Nullable)currentSong; -/// 当前播放状态 -+ (QPlayAutoPlayState)currentPlayState; -/// 当前播放进度 -+ (NSTimeInterval)currentProgress; -/// QQ音乐是否登录 -+ (BOOL)isLoginOK; -/// 检查QQ音乐是否已安装 -+ (BOOL)isQQMusicInstalled; -/// 是否已连接 -+ (BOOL)isConnected; -/// 连接中 -+ (BOOL)isConnecting; -///QQ音乐设备信息 -+ (NSDictionary *)deviceInfo; - -+(NSString *)openId; -+(NSString *)openToken; - - -///是否可以处理回调url -+ (BOOL)canHandleOpenURL:(NSURL *)url; -///处理回调url -+ (BOOL)handleOpenURL:(NSURL *)url; - -/// 回调代理 -+ (void)setDelegate:(id) delegate; - - -/// 拉端连接QPlay -/// - Parameter forceLogin: 是否强制登录 -+ (void)connectAndForceLogin:(BOOL)forceLogin; -/// 停止 -+ (void)stop; - - -/// 二次热启动连接(需要联系Q音打开此功能才能使用) -/// - Parameters: -/// - timeout: 超时时间 -/// - completion: 回调 -+ (void)reconnectWithTimeout:(NSTimeInterval)timeout completion:(QPlayAutoRequestFinishBlock)completion; - -/// 跳转QQ音乐登录 -/// @param bundleId 合作方bundleId -/// @param callbackUrl 跳转合作方url -+ (BOOL)loginQQMusicWithBundleId:(NSString *)bundleId callbackUrl:(NSString *)callbackUrl; - - -/// 获取数据 -/// @param parent 父 -/// @param pageIndex 页码 -/// @param pageSize 页大小 -/// @param completion 回调 -+ (void)getDataItemsFromParent:(QPlayAutoListItem *)parent pageIndex:(NSUInteger)pageIndex pageSize:(NSUInteger)pageSize completion:(QPlayAutoResultParentItemBlock)completion; - - -/// 设置播放模式 -/// @param playMode 播放模式 -/// @param block 回调 -+ (NSInteger)setPlayMode:(QPlayAutoPlayMode)playMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; - - -/// 设置播放整首还是高潮 -/// @param assencceMode 高潮还是整首 -/// @param block 回调 -+ (NSInteger)setAssenceMode:(QPlayAutoAssenceMode)assencceMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; - -/// 收藏/取消收藏(歌曲id) -/// @param song 歌曲 -/// @param isFavorite 收藏/取消收藏 -/// @param completion 回调 -+ (void)setFavoriteStateWithSong:(QPlayAutoListItem *)song isFavorite:(BOOL)isFavorite completion:(void (^)(NSInteger errorCode))completion; - -/// 播放歌曲 -/// @param songList 歌曲列表 -/// @param playIndex 播放索引 -/// @param completion 回调 -+ (void)playAtIndex:(NSArray *)songList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; - - -/// 通过歌曲Mid列表播放歌曲 -/// @param songMidList 歌曲Mid列表 -/// @param playIndex 播放索引 -/// @param completion 回调 -+ (void)playSongMidAtIndex:(NSArray *)songMidList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; - - -///播放下一首 -+ (void)playerPlayNextWithCompletion:(void (^)(NSInteger errorCode))completion; - -///播放上一首 -+ (void)playerPlayPrevWithCompletion:(void (^)(NSInteger errorCode))completion; - -///播放暂停 -+ (void)playerPlayPause; - -///播放恢复 -+ (void)playerPlayResumeWithCompletion:(void (^)(NSInteger errorCode))completion; - -///Seek到指定位置 -+ (void)playerSeek:(NSInteger)position; - - -/// 搜索歌曲 -/// @param keyword 关键词 -/// @param type 搜索类型 -/// @param firstPage 是否第一页 -/// @param completion 回调 -+ (NSInteger)search:(NSString *)keyword - type:(QPlayAutoSearchType)type - firstPage:(BOOL)firstPage - completion:(QPlayAutoResultItemsBlock)completion; - -/// 相似歌曲 -/// @param song 歌曲 -/// @param completion 回调 -+ (void)requestSimilarWithSong:(QPlayAutoListItem *)song completion:(QPlayAutoResultItemsBlock)completion; - - -/// 查询歌词 -/// @param song 歌曲 -/// @param completion 回调 -+ (void)requestLyricWithSong:(QPlayAutoListItem *)song completion:(void (^)(NSInteger errorCode,QPlayAutoLyric *_Nullable lyric))completion; - - -/// 获取特定歌曲列表 -/// @param type 列表类型 -/// @param completion 回调 -+ (void)requestSonglistWithType:(QPlayAutoSongListType)type completion:(QPlayAutoResultItemsBlock)completion; - -@end - -NS_ASSUME_NONNULL_END diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK-arm64.a b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK-arm64.a deleted file mode 100644 index 727801538..000000000 Binary files a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK-arm64.a and /dev/null differ diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK-x86_64.a b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK-x86_64.a deleted file mode 100644 index 2d6587ba2..000000000 Binary files a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK-x86_64.a and /dev/null differ diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK.a b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK.a deleted file mode 100644 index 2ad7aa0a1..000000000 Binary files a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK.a and /dev/null differ diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/module.modulemap b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/module.modulemap deleted file mode 100644 index 3720696ae..000000000 --- a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/module.modulemap +++ /dev/null @@ -1,8 +0,0 @@ -module QPlayAutoSDK { - header "Headers/include/QPlayAutoSDK.h" - header "Headers/include/QPlayAutoDefine.h" - - export * - - link "QPlayAutoSDK" -} \ No newline at end of file diff --git a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QPlayAutoManager.swift b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QPlayAutoManager.swift index 1c09142d6..b42039b64 100644 --- a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QPlayAutoManager.swift +++ b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QPlayAutoManager.swift @@ -7,10 +7,180 @@ import QPlayAutoSDK @objc public static let shared = QPlayAutoManager() private var delegates: [WeakDelegate] = [] + private var isAppRegistered = false + // 添加登录状态维护 + private var _isLoginOK = false + private var loginCompletionHandlers: [(Bool) -> Void] = [] + + // 添加token存储相关常量 + private static let STORED_OPEN_ID_KEY = "QQMusic_OpenID" + private static let STORED_OPEN_TOKEN_KEY = "QQMusic_OpenToken" + private static let STORED_LOGIN_TIME_KEY = "QQMusic_LoginTime" + private static let TOKEN_EXPIRE_TIME: TimeInterval = 30 * 24 * 60 * 60 // 30天过期 + + // QQ音乐配置常量 + private static let OPENID_APPID = "2000000921" + private static let OPENID_APP_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" + + "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALWuTayxg0296yfm\n" + + "h8WhunybY1BEFt9fB4qb3TGvB0vkd+oKDoBdiTevtgwSL47h4O0ISNTQqqmVOvk1\n" + + "EQMGcLESBEdHquPX2uOplwmmVWx1un9NYB4JKaHmUkCXOIoiCgmEY052zFY2T+a0\n" + + "RfFiaUTc0wRMynquE8Qp18i23IUBAgMBAAECgYBf/s1D5jd+qE7MMl6i6iVjGaeM\n" + + "Da4YMFoHvvtM+TJdw0Yo/09SPBn4tnr2PdWrJWZ3V91DtU23dQZIDuYCNzDrOkVr\n" + + "93W5Pkqprdbde6qRhWm1VTZVN7h85DStGBzovSxQ6DQNHZFzIriJkfGDjPopmIil\n" + + "awQvMPlS3lLYkzHwAQJBAOWBlshEMHXeqXekjJExwX7YSy2oabWXtllCFbcPprAY\n" + + "MiM8cdNsEhnhrsmdBN4crqTQKJq/ATaYFhzASuIiZ2ECQQDKp17+A3u6q7RZ3Vmb\n" + + "khvAATQpVK5loCOzuyPU7/UGU49AO1DIaPwDvaUqL6PuF9eFrcRHA5AFbBjOgYNn\n" + + "piGhAkEAr5gMo0D4ytYHVxDAs74by071hgNajaN70qLrNlp1MDny8l6mwBnpZ3/y\n" + + "WTMXrFDJljPlPTByXzDRikHdiVLFQQJATMOTpxK4tqA+A+BmBhkVa+jI0nMiUJqV\n" + + "i4py60EuBoR2efU+B3xFIkGfI9jB9vmPCTMma2P9FSC6UNccaJG0oQJBAJYb6Ch9\n" + + "yowGPpY1CShaR+TfauUreJBd4PSpu8mFlYUssp2AXYcJM51RMzrZKXvTTOvwkStc\n" + + "NRCBcPVAYcVUnXo=\n" + + "-----END PRIVATE KEY-----" private override init() { super.init() QPlayAutoSDK.setDelegate(self) + + // Register for app lifecycle notifications + NotificationCenter.default.addObserver( + self, + selector: #selector(appWillTerminate), + name: UIApplication.willTerminateNotification, + object: nil + ) + + NotificationCenter.default.addObserver( + self, + selector: #selector(appDidEnterBackground), + name: UIApplication.didEnterBackgroundNotification, + object: nil + ) + + registerAppWithDefaultConfig() + + // 启用自动登录 + tryAutoLoginWithStoredToken() + } + + @objc private func appWillTerminate() { + stop() + } + + @objc private func appDidEnterBackground() { + // Optionally stop SDK when app goes to background + // stop() + } + + + + // MARK: - Token存储和自动登录 + + /// 尝试使用保存的token自动登录 + private func tryAutoLoginWithStoredToken() { + guard let storedOpenId = UserDefaults.standard.string(forKey: Self.STORED_OPEN_ID_KEY), + let storedOpenToken = UserDefaults.standard.string(forKey: Self.STORED_OPEN_TOKEN_KEY), + let loginTime = UserDefaults.standard.object(forKey: Self.STORED_LOGIN_TIME_KEY) as? Date else { + print("QPlayAutoManager: 没有找到保存的token") + return + } + + // 检查token是否过期 + let currentTime = Date() + if currentTime.timeIntervalSince(loginTime) > Self.TOKEN_EXPIRE_TIME { + print("QPlayAutoManager: 保存的token已过期,清除本地存储") + clearStoredToken() + return + } + + print("QPlayAutoManager: 找到有效的保存token,尝试自动登录") + print("QPlayAutoManager: OpenID: \(storedOpenId)") + print("QPlayAutoManager: OpenToken: \(storedOpenToken.prefix(20))...") + + // 这里可以尝试使用保存的token进行连接 + // 注意:QPlayAutoSDK可能需要重新连接来验证token有效性 + connect(forceLogin: false) + } + + /// 保存登录token + private func saveLoginToken() { + let openId = QPlayAutoSDK.openId() + let openToken = QPlayAutoSDK.openToken() + + guard !openId.isEmpty, !openToken.isEmpty else { + print("QPlayAutoManager: 无法获取token信息") + return + } + + UserDefaults.standard.set(openId, forKey: Self.STORED_OPEN_ID_KEY) + UserDefaults.standard.set(openToken, forKey: Self.STORED_OPEN_TOKEN_KEY) + UserDefaults.standard.set(Date(), forKey: Self.STORED_LOGIN_TIME_KEY) + UserDefaults.standard.synchronize() + + print("QPlayAutoManager: Token已保存到本地存储") + print("QPlayAutoManager: OpenID: \(openId)") + print("QPlayAutoManager: OpenToken: \(openToken.prefix(20))...") + } + + /// 清除保存的token + private func clearStoredToken() { + UserDefaults.standard.removeObject(forKey: Self.STORED_OPEN_ID_KEY) + UserDefaults.standard.removeObject(forKey: Self.STORED_OPEN_TOKEN_KEY) + UserDefaults.standard.removeObject(forKey: Self.STORED_LOGIN_TIME_KEY) + UserDefaults.standard.synchronize() + print("QPlayAutoManager: 已清除本地保存的token") + } + + /// 获取保存的token信息 + @objc public func getStoredTokenInfo() -> [String: Any]? { + guard let openId = UserDefaults.standard.string(forKey: Self.STORED_OPEN_ID_KEY), + let openToken = UserDefaults.standard.string(forKey: Self.STORED_OPEN_TOKEN_KEY), + let loginTime = UserDefaults.standard.object(forKey: Self.STORED_LOGIN_TIME_KEY) as? Date else { + return nil + } + + return [ + "openId": openId, + "openToken": openToken, + "loginTime": loginTime, + "isExpired": Date().timeIntervalSince(loginTime) > Self.TOKEN_EXPIRE_TIME + ] + } + + /// 手动清除token(用于登出) + @objc public func logout() { + clearStoredToken() + _isLoginOK = false + QPlayAutoSDK.stop() + print("QPlayAutoManager: 用户已登出,token已清除") + } + + private func registerAppWithDefaultConfig() { + guard !isAppRegistered else { + print("QPlayAutoManager: App already registered, skipping") + return + } + + // 确保完全停止之前的实例,避免端口占用 + QPlayAutoSDK.stop() + + // 添加短暂延迟确保资源完全释放 + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + let deviceId = UIDevice.current.identifierForVendor?.uuidString ?? "unknown_device" + let bundleId = Bundle.main.bundleIdentifier ?? "com.saitong.voitrans" + + QPlayAutoSDK.registerApp( + withName: "VoiTrans", + brand: "SaiTong", + deviceId: deviceId, + scheme: "qqmusic", + appId: Self.OPENID_APPID, + secretKey: Self.OPENID_APP_PRIVATE_KEY, + bundleId: bundleId + ) + + self.isAppRegistered = true + print("QPlayAutoManager: App registered successfully") + } } // MARK: - Delegate Management @@ -50,12 +220,36 @@ import QPlayAutoSDK // MARK: - Connection Management @objc public func connect(forceLogin: Bool = false) { + guard isAppRegistered else { + print("QPlayAutoManager: App not registered, registering first") + registerAppWithDefaultConfig() + return // 添加这个return语句 + } + + // Add retry mechanism for socket errors + connectWithRetry(forceLogin: forceLogin, retryCount: 3) + } + + private func connectWithRetry(forceLogin: Bool, retryCount: Int) { + guard retryCount > 0 else { + print("QPlayAutoManager: Connection failed after all retries") + return + } + QPlayAutoSDK.connectAndForceLogin(forceLogin) + + // If connection fails due to socket error, retry after cleanup + DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { + if !self.isConnected { + print("QPlayAutoManager: Connection failed, retrying... (\(retryCount - 1) attempts left)") + QPlayAutoSDK.stop() + self.connectWithRetry(forceLogin: forceLogin, retryCount: retryCount - 1) + } + } } @objc public func reconnect(timeout: TimeInterval, completion: @escaping (Bool, [String: Any]?) -> Void) { QPlayAutoSDK.reconnect(withTimeout: timeout) { (success, dict) in - // 修复:直接使用Bool类型,不进行Int比较 completion(success, dict as? [String: Any]) } } @@ -64,40 +258,261 @@ import QPlayAutoSDK QPlayAutoSDK.stop() } + // MARK: - 登录状态管理 + // 在第206行之前添加新的方法 + private func ensureQQMusicInstalledAndLoginAndExecute( + _ operation: @escaping () -> Void, + onQQMusicNotInstalled: (() -> Void)? = nil, + onLoginFailed: (() -> Void)? = nil + ) { + // 首先检查QQ音乐是否已安装 + guard isQQMusicInstalled else { + print("QPlayAutoManager: QQ音乐未安装,无法执行操作") + onQQMusicNotInstalled?() + return + } + + // QQ音乐已安装,继续检查登录状态 + ensureLoginAndExecute(operation, onLoginFailed: onLoginFailed) + } + + // 修改现有的ensureLoginAndExecute方法(第206行开始) + private func ensureLoginAndExecute(_ operation: @escaping () -> Void, onLoginFailed: (() -> Void)? = nil) { + if isLoginOK { + // 已登录,直接执行操作 + operation() + } else { + // 未登录,先登录 + print("QPlayAutoManager: 未登录,正在尝试登录...") + performLogin { [weak self] success in + if success { + print("QPlayAutoManager: 登录成功,执行操作") + operation() + } else { + print("QPlayAutoManager: 登录失败,无法执行操作") + onLoginFailed?() + } + } + } + } + + private func performLogin(completion: @escaping (Bool) -> Void) { + // 如果正在登录中,将回调添加到队列 + loginCompletionHandlers.append(completion) + + // 如果已经有登录请求在处理,直接返回 + if loginCompletionHandlers.count > 1 { + return + } + + // 强制登录 + connect(forceLogin: true) + + // 设置超时检查 + DispatchQueue.main.asyncAfter(deadline: .now() + 10.0) { [weak self] in + self?.checkLoginTimeout() + } + } + + private func checkLoginTimeout() { + if !loginCompletionHandlers.isEmpty && !isLoginOK { + print("QPlayAutoManager: 登录超时") + notifyLoginCompletion(false) + } + } + + private func notifyLoginCompletion(_ success: Bool) { + let handlers = loginCompletionHandlers + loginCompletionHandlers.removeAll() + + for handler in handlers { + handler(success) + } + } + // MARK: - 播放控制 @objc public func play() { - // 使用新的方法名 - QPlayAutoSDK.playerPlayResume { errorCode in - print("Resume play result: \(errorCode)") + ensureQQMusicInstalledAndLoginAndExecute { + QPlayAutoSDK.playerPlayResume { errorCode in + print("Resume play result: \(errorCode)") + } + } onQQMusicNotInstalled: { + print("QPlayAutoManager: 播放失败 - QQ音乐未安装") + } onLoginFailed: { + print("QPlayAutoManager: 播放失败 - 登录失败") } } @objc public func play(songId: String) { - // 播放特定歌曲需要先搜索或使用歌曲列表 - // 这里提供一个简化的实现 - QPlayAutoSDK.playerPlayResume { errorCode in - print("Play song result: \(errorCode)") + ensureQQMusicInstalledAndLoginAndExecute { + // 使用正确的方法播放指定歌曲 + QPlayAutoSDK.playSongMid(atIndex: [songId], play: 0) { errorCode in + print("Play song result: \(errorCode)") + } + } onQQMusicNotInstalled: { + print("QPlayAutoManager: 播放歌曲失败 - QQ音乐未安装") + } onLoginFailed: { + print("QPlayAutoManager: 播放歌曲失败 - 登录失败") } } - @objc public func pause() { - QPlayAutoSDK.playerPlayPause() + @objc public func playSongs(mids: [String], index: Int = 0, completion: @escaping (Bool, String?) -> Void) { + guard !mids.isEmpty else { + completion(false, "歌曲列表为空") + return + } + + guard index >= 0 && index < mids.count else { + completion(false, "播放索引超出范围") + return + } + + ensureLoginAndExecute { + QPlayAutoSDK.playSongMid(atIndex: mids, play: index) { errorCode in + if errorCode == 0 { + completion(true, nil) + print("QQ音乐播放列表启动成功,共\(mids.count)首歌曲") + } else { + let errorMessage = "QQ音乐播放列表启动失败,错误码: \(errorCode)" + completion(false, errorMessage) + print(errorMessage) + } + } + } onLoginFailed: { + completion(false, "登录失败,无法播放歌曲列表") + } } @objc public func next() { - QPlayAutoSDK.playerPlayNext { errorCode in - print("Next song result: \(errorCode)") + ensureQQMusicInstalledAndLoginAndExecute { + QPlayAutoSDK.playerPlayNext { errorCode in + print("Next song result: \(errorCode)") + } + } onQQMusicNotInstalled: { + print("QPlayAutoManager: 下一首失败 - QQ音乐未安装") + } onLoginFailed: { + print("QPlayAutoManager: 下一首失败 - 登录失败") } } @objc public func previous() { - QPlayAutoSDK.playerPlayPrev { errorCode in - print("Previous song result: \(errorCode)") + ensureQQMusicInstalledAndLoginAndExecute { + QPlayAutoSDK.playerPlayPrev { errorCode in + print("Previous song result: \(errorCode)") + } + } onQQMusicNotInstalled: { + print("QPlayAutoManager: 上一首失败 - QQ音乐未安装") + } onLoginFailed: { + print("QPlayAutoManager: 上一首失败 - 登录失败") + } + } + + @objc public func pause() { + ensureLoginAndExecute { + QPlayAutoSDK.playerPlayPause() + } onLoginFailed: { + print("QPlayAutoManager: 暂停失败 - 登录失败") } } @objc public func seek(to position: TimeInterval) { - QPlayAutoSDK.playerSeek(Int(position)) + ensureLoginAndExecute { + QPlayAutoSDK.playerSeek(Int(position)) + } onLoginFailed: { + print("QPlayAutoManager: 跳转播放位置失败 - 登录失败") + } + } + + // MARK: - 扩展功能方法(需要添加登录检查) + + /// 设置播放模式 + @objc public func setPlayMode(_ playMode: QPlayAutoPlayMode, completion: @escaping (Bool) -> Void) { + ensureLoginAndExecute { + QPlayAutoSDK.setPlayMode(playMode) { (success, dict) in + completion(success) + } + } onLoginFailed: { + print("QPlayAutoManager: 设置播放模式失败 - 登录失败") + completion(false) + } + } + + /// 收藏/取消收藏歌曲 + @objc public func setFavoriteState(song: QPlayAutoListItem, isFavorite: Bool, completion: @escaping (Bool) -> Void) { + ensureLoginAndExecute { + QPlayAutoSDK.setFavoriteStateWithSong(song, isFavorite: isFavorite) { errorCode in + completion(errorCode == 0) + } + } onLoginFailed: { + print("QPlayAutoManager: 设置收藏状态失败 - 登录失败") + completion(false) + } + } + + /// 获取相似歌曲 + @objc public func requestSimilarSongs(song: QPlayAutoListItem, completion: @escaping ([QPlayAutoListItem]?, Error?) -> Void) { + ensureLoginAndExecute { + QPlayAutoSDK.requestSimilar(withSong: song) { errorCode, items in + if errorCode == 0 { + completion(items, nil) + } else { + let error = NSError(domain: "QPlayAutoManager", code: Int(errorCode), userInfo: [NSLocalizedDescriptionKey: "请求相似歌曲失败"]) + completion(nil, error) + } + } + } onLoginFailed: { + print("QPlayAutoManager: 请求相似歌曲失败 - 登录失败") + let error = NSError(domain: "QPlayAutoManager", code: -1, userInfo: [NSLocalizedDescriptionKey: "QQ音乐未安装"]) + completion(nil, error) + } + } + + /// 获取歌词 + @objc public func requestLyric(song: QPlayAutoListItem, completion: @escaping (QPlayAutoLyric?, Error?) -> Void) { + ensureLoginAndExecute { + QPlayAutoSDK.requestLyric(withSong: song) { errorCode, lyric in + if errorCode == 0 { + completion(lyric, nil) + } else { + let error = NSError(domain: "QPlayAutoManager", code: Int(errorCode), userInfo: [NSLocalizedDescriptionKey: "请求歌词失败"]) + completion(nil, error) + } + } + } onLoginFailed: { + print("QPlayAutoManager: 请求歌词失败 - 登录失败") + let error = NSError(domain: "QPlayAutoManager", code: -1, userInfo: [NSLocalizedDescriptionKey: "QQ音乐未安装"]) + completion(nil, error) + } + } + + /// 获取歌曲列表 + @objc public func requestSonglist(type: QPlayAutoSongListType, completion: @escaping ([QPlayAutoListItem]?, Error?) -> Void) { + ensureLoginAndExecute { + QPlayAutoSDK.requestSonglist(with: type) { errorCode, items in + if errorCode == 0 { + completion(items, nil) + } else { + let error = NSError(domain: "QPlayAutoManager", code: Int(errorCode), userInfo: [NSLocalizedDescriptionKey: "请求歌单失败"]) + completion(nil, error) + } + } + } onLoginFailed: { + print("QPlayAutoManager: 请求歌单失败 - 登录失败") + let error = NSError(domain: "QPlayAutoManager", code: -1, userInfo: [NSLocalizedDescriptionKey: "QQ音乐未安装"]) + completion(nil, error) + } + } + + /// 播放指定歌曲列表 + @objc public func playAtIndex(songList: [QPlayAutoListItem], playIndex: Int, completion: @escaping (Bool) -> Void) { + ensureLoginAndExecute { + QPlayAutoSDK.play(atIndex: songList, play: playIndex) { errorCode in + completion(errorCode == 0) + } + } onLoginFailed: { + print("QPlayAutoManager: 播放指定索引歌曲失败 - QQ音乐未安装") + completion(false) + } } // MARK: - 状态查询 @@ -137,7 +552,6 @@ import QPlayAutoSDK return QPlayAutoSDK.deviceInfo() as? [String: Any] ?? [:] } - // Add missing properties @objc public var openId: String? { return QPlayAutoSDK.openId() } @@ -149,21 +563,56 @@ import QPlayAutoSDK // MARK: - URL Handling @objc public func canHandleOpenURL(url: String) -> Bool { guard let nsurl = URL(string: url) else { return false } + + // 检查QQ音乐是否安装 + guard isQQMusicInstalled else { + print("QPlayAutoManager: QQ音乐未安装,无法处理URL") + return false + } + + // 检查登录状态 + guard isLoginOK else { + print("QPlayAutoManager: 未登录,无法处理URL") + return false + } + return QPlayAutoSDK.canHandleOpen(nsurl) } @objc public func handleOpenURL(_ url: URL) -> Bool { - return QPlayAutoSDK.handleOpen(url) + // 检查QQ音乐是否安装 + guard isQQMusicInstalled else { + print("QPlayAutoManager: QQ音乐未安装,无法处理URL") + return false + } + + // 检查登录状态 + guard isLoginOK else { + print("QPlayAutoManager: 未登录,无法处理URL") + return false + } + + do { + return QPlayAutoSDK.handleOpen(url) + } catch { + print("QPlayAutoManager: 处理URL时发生错误: \(error)") + return false + } } - // MARK: - Search and Content + // MARK: - Search and Content(添加登录检查) @objc public func search( keyword: String, searchType: QPlayAutoSearchType, completion: @escaping ([QPlayAutoListItem]?) -> Void ) { - QPlayAutoSDK.search(keyword, type: searchType, firstPage: true) { (error, items) in - completion(items) + ensureLoginAndExecute { + QPlayAutoSDK.search(keyword, type: searchType, firstPage: true) { (error, items) in + completion(items) + } + } onLoginFailed: { + print("QPlayAutoManager: 搜索失败 - 登录失败") + completion(nil) } } @@ -171,20 +620,27 @@ import QPlayAutoSDK playlistId: String, completion: @escaping ([QPlayAutoListItem]?) -> Void ) { - // Create a QPlayAutoListItem object - // with the playlistId to use as parentItem - let parentItem = QPlayAutoListItem() - parentItem.id = playlistId - - QPlayAutoSDK.getDataItems(fromParent: parentItem, pageIndex: 0, pageSize: 50) { (error, items) in - // 修复:确保items是正确的类型 - if error == 0 { - completion(items as? [QPlayAutoListItem]) - } else { - completion(nil) + ensureLoginAndExecute { + let parentItem = QPlayAutoListItem() + parentItem.id = playlistId + + QPlayAutoSDK.getDataItems(fromParent: parentItem, pageIndex: 0, pageSize: 50) { (error, items) in + if error == 0 { + completion(items as? [QPlayAutoListItem]) + } else { + completion(nil) + } } + } onLoginFailed: { + print("QPlayAutoManager: 获取播放列表失败 - 登录失败") + completion(nil) } } + + // 添加公开的登录方法 + @objc public func login(completion: @escaping (Bool) -> Void) { + performLogin(completion: completion) + } } // MARK: - QPlayAutoSDKDelegate @@ -233,8 +689,21 @@ extension QPlayAutoManager: QPlayAutoSDKDelegate { } public func onLoginStateDidChanged(_ isLoginOK: Bool) { + print("QPlayAutoManager: Login state changed to \(isLoginOK)") + _isLoginOK = isLoginOK + + // 登录成功时保存token + if isLoginOK { + saveLoginToken() + notifyLoginCompletion(true) + } else { + // 登录失败时清除可能无效的token + clearStoredToken() + } + + // 通知所有代理 cleanupDelegates() - for weakDelegate in delegates { + delegates.forEach { weakDelegate in weakDelegate.delegate?.onLoginStateDidChanged?(isLoginOK) } } @@ -258,4 +727,4 @@ private class WeakDelegate { init(_ delegate: QPlayAutoManagerDelegate) { self.delegate = delegate } -} \ No newline at end of file +} diff --git a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QqMusicPlugin.swift b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QqMusicPlugin.swift index 3b61d1890..31e9e6fdb 100644 --- a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QqMusicPlugin.swift +++ b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QqMusicPlugin.swift @@ -149,8 +149,8 @@ public class QqMusicPlugin: NSObject, FlutterPlugin { // 新增:登录功能 private func handleLogin(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - let isLoginOK = QPlayAutoManager.shared.isLoginOK - if isLoginOK { + // 如果已经登录,直接返回登录信息 + if QPlayAutoManager.shared.isLoginOK { let openId = QPlayAutoManager.shared.openId ?? "" let openToken = QPlayAutoManager.shared.openToken ?? "" result([ @@ -159,8 +159,25 @@ public class QqMusicPlugin: NSObject, FlutterPlugin { "openToken": openToken, "expireTime": "" ]) - } else { - result(FlutterError(code: "LOGIN_FAILED", message: "User not logged in", details: nil)) + return + } + + // 如果未登录,主动执行登录 + QPlayAutoManager.shared.login { success in + DispatchQueue.main.async { + if success { + let openId = QPlayAutoManager.shared.openId ?? "" + let openToken = QPlayAutoManager.shared.openToken ?? "" + result([ + "success": true, + "openId": openId, + "openToken": openToken, + "expireTime": "" + ]) + } else { + result(FlutterError(code: "LOGIN_FAILED", message: "登录失败", details: nil)) + } + } } } @@ -173,22 +190,27 @@ public class QqMusicPlugin: NSObject, FlutterPlugin { } let searchType = args["searchType"] as? Int ?? 0 + print("开始搜索歌曲,关键词: \(keyword), 类型: \(searchType)") QPlayAutoManager.shared.search(keyword: keyword, searchType: QPlayAutoSearchType(rawValue: searchType) ?? .song) { items in - if let items = items { - let songs = items.map { item -> [String: Any] in - return [ - "id": item.id ?? "", - "name": item.name ?? "", - "artist": item.singer?.name ?? "", - "album": item.album ?? "", - "duration": item.duration, - "mid": item.id ?? "" - ] + DispatchQueue.main.async { + if let items = items { + print("搜索成功,找到 \(items.count) 首歌曲") + let songs = items.map { item -> [String: Any] in + return [ + "id": item.id ?? "", + "name": item.name ?? "", + "artist": item.singer?.name ?? "", + "album": item.album ?? "", + "duration": item.duration, + "mid": item.id ?? "" + ] + } + result(["success": true, "songs": songs]) + } else { + print("搜索失败,未找到歌曲") + result(FlutterError(code: "SEARCH_FAILED", message: "Search failed", details: nil)) } - result(["success": true, "songs": songs]) - } else { - result(FlutterError(code: "SEARCH_FAILED", message: "Search failed", details: nil)) } } } @@ -204,12 +226,13 @@ public class QqMusicPlugin: NSObject, FlutterPlugin { let index = args["index"] as? Int ?? 0 - if index < songMids.count { - let songId = songMids[index] - QPlayAutoManager.shared.play(songId: songId) - result(["success": true]) - } else { - result(FlutterError(code: "PLAY_FAILED", message: "Invalid index", details: nil)) + // 使用 playSongs 方法播放整个列表 + QPlayAutoManager.shared.playSongs(mids: songMids, index: index) { success, errorMessage in + if success { + result(["success": true]) + } else { + result(FlutterError(code: "PLAY_FAILED", message: errorMessage ?? "播放失败", details: nil)) + } } } @@ -405,18 +428,60 @@ public class QqMusicPlugin: NSObject, FlutterPlugin { // 第405-409行 - handleSyncCurrentPlayInfo方法 private func handleSyncCurrentPlayInfo(result: @escaping FlutterResult) { - if let song = QPlayAutoManager.shared.currentSong { - let playInfo: [String: Any] = [ - "id": song.id ?? "", - "name": song.name ?? "", - "artist": song.singer?.name ?? "", - "album": song.album ?? "", - "duration": song.duration - ] - result(["success": true, "data": playInfo]) - } else { - result(FlutterError(code: "NO_CURRENT_SONG", message: "No current song playing", details: nil)) - } + // 构建同步数据 + var syncData: [String: Any] = [:] + + // 获取当前歌曲信息 + if let song = QPlayAutoManager.shared.currentSong { + let currentSong: [String: Any] = [ + "id": song.id ?? "", + "mid": song.mid ?? "", + "name": song.name ?? "", + "singer": song.singer?.name ?? "", + "album": song.album ?? "", + "duration": song.duration, + "pic": song.coverUri ?? "" + ] + syncData["currentSong"] = currentSong + } else { + syncData["currentSong"] = nil + } + + // 获取播放状态 - 使用正确的枚举成员名称 + let playState = QPlayAutoManager.shared.currentPlayState + let isPlaying: Bool + let playStateValue: Int + + switch playState { + case .playing: + isPlaying = true + playStateValue = 1 + case .pause: + isPlaying = false + playStateValue = 2 + case .stop: + isPlaying = false + playStateValue = 0 + default: + isPlaying = false + playStateValue = 0 + } + + syncData["isPlaying"] = isPlaying + syncData["playState"] = playStateValue + + // 获取播放时间 + let currentProgress = QPlayAutoManager.shared.currentProgress + let currentTime = Int64(currentProgress) // 转换为秒 + let totalTime = Int64(QPlayAutoManager.shared.currentSong?.duration ?? 0) + + syncData["currentTime"] = currentTime + syncData["totalTime"] = totalTime + + // 添加同步时间戳 + syncData["syncTimestamp"] = Int64(Date().timeIntervalSince1970 * 1000) // 毫秒时间戳 + + result(["success": true, "data": syncData]) } // 第492-496行 - 重复的handleGetPlaylistContent方法(需要删除) @@ -469,4 +534,4 @@ extension QqMusicPlugin: QPlayAutoManagerDelegate { public func onLoginStateDidChanged(_ isLogin: Bool) { eventSink?(["type": "loginStateChanged", "isLogin": isLogin]) } -} \ No newline at end of file +} diff --git a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/QPlayAutoDefine.h b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/QPlayAutoDefine.h index 3ccbd092d..b1ebee15a 100644 --- a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/QPlayAutoDefine.h +++ b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/QPlayAutoDefine.h @@ -78,6 +78,12 @@ typedef NS_ENUM(NSUInteger, QPlayAutoListItemType) QPlayAutoListItemType_Album = 5, //专辑 }; +typedef NS_ENUM(NSUInteger, QPlayAutoSongListType) +{ + QPlayAutoSongListType_Daily = 108, //每日30首 +}; + + /** QPlayAuto播放状态 */ @@ -88,6 +94,12 @@ typedef NS_ENUM(NSUInteger, QPlayAutoPlayState) QPlayAutoPlayState_Pause=2 //暂停 }; +typedef NS_ENUM(NSInteger, QPlayAutoAssenceMode) +{ + QPlayAutoAssenceMode_Full = 0, // 默认整首播放 + QPlayAutoAssenceMode_Part = 1, // 仅播放精华片段 +}; + /** QPlayAuto播放模式 */ @@ -121,74 +133,86 @@ typedef NS_ENUM(NSInteger, QPlayAutoVipState) */ @interface QPlayAutoAppInfo : NSObject -@property (nonatomic,strong) NSString *deviceId; +@property (nonatomic,strong) NSString *deviceId; //AppId @property (nonatomic,assign) NSInteger deviceType; -@property (nonatomic,strong) NSString *scheme; -@property (nonatomic,strong) NSString *brand; -@property (nonatomic,strong) NSString *name; -@property (nonatomic,strong) NSString *appId; -@property (nonatomic,strong) NSString *secretKey; -@property (nonatomic,strong) NSString *bundleId; -@property (nonatomic,assign) NSInteger qmCommandPort; -@property (nonatomic,strong) NSString *qmHost; -@property (nonatomic,strong) NSDate *lastConnectDate; +@property (nonatomic,strong) NSString *scheme; //跳转scheme +@property (nonatomic,strong) NSString *brand; //品牌 +@property (nonatomic,strong) NSString *name; //名称 +@property (nonatomic,strong) NSString *appId; //名称 +@property (nonatomic,strong) NSString *secretKey; //私钥 +@property (nonatomic,strong) NSString *bundleId; //bundleId +@property (nonatomic,assign) NSInteger qmCommandPort; //Q音接收命令端口 +@property (nonatomic,strong) NSString *qmHost; //Q音接收命令IP +@property (nonatomic,strong) NSDate *lastConnectDate;//上次连接的日期 @end @interface QPlayAutoSinger : NSObject -@property (nonatomic,strong) NSString *ID; -@property (nonatomic,strong) NSString *Mid; -@property (nonatomic,strong) NSString *name; +@property (nonatomic,strong) NSString *ID; //ID +@property (nonatomic,strong) NSString *Mid; //Mid +@property (nonatomic,strong) NSString *name; //名称 @end + /* QPlayAuto列表项(歌单、电台、排行榜、歌曲、etc) */ @interface QPlayAutoListItem: NSObject -@property (nonatomic,strong) NSString *ID; -@property (nonatomic,strong) NSString *Name; -@property (nonatomic,strong) NSString *SubName; -@property (nonatomic,strong) QPlayAutoSinger *singer; -@property (nonatomic,strong) NSString *Album; +@property (nonatomic,strong) NSString *ID; //ID +@property (nonatomic,strong) NSString *Name; //名称 +@property (nonatomic,strong) NSString *SubName; //副标题 +@property (nonatomic,strong) QPlayAutoSinger *singer; //歌手 +@property (nonatomic,strong) NSString *Album; //专辑 @property (nonatomic,strong) NSString *Mid; @property (nonatomic,assign) QPlayAutoVipState vipState; @property (nonatomic,assign) QPlayAutoListItemType Type; -@property (nonatomic,assign) NSInteger Duration; -@property (nonatomic,strong) NSString *CoverUri; -@property (nonatomic,assign) NSInteger totalCount; -@property (nonatomic,assign) BOOL isFav; -@property (nonatomic,assign) BOOL isOrigin; -@property (nonatomic,assign) BOOL isNoAudioSource; -@property (nonatomic,strong) NSMutableArray *items; -@property (nonatomic,weak) QPlayAutoListItem *parentItem; - -@property (nonatomic,assign) BOOL isTryListen; -@property (nonatomic,readonly) BOOL isSong; -@property (nonatomic,readonly) BOOL isFolder; -@property (nonatomic,readonly) BOOL isAlbum; -@property (nonatomic,readonly) BOOL isRadio; -@property (nonatomic,readonly) BOOL isDirectory; - -@property (nonatomic,readonly) BOOL isVIP; -@property (nonatomic,readonly) BOOL isSVIP; +@property (nonatomic,assign) NSInteger Duration; //时长 +@property (nonatomic,strong) NSString *CoverUri; //封面Uri +@property (nonatomic,assign) NSInteger totalCount; //总数 +@property (nonatomic,assign) BOOL isFav; //是否收藏 +@property (nonatomic,assign) BOOL isOrigin; //是否原唱 +@property (nonatomic,assign) BOOL isNoAudioSource; //无音源 +@property (nonatomic,strong) NSMutableArray *items; //子列表 +@property (nonatomic,weak) QPlayAutoListItem *parentItem; //父节点 + +@property (nonatomic,assign) BOOL isTryListen; //是否试听歌曲 +@property (nonatomic,readonly) BOOL isSong; //歌曲 +@property (nonatomic,readonly) BOOL isFolder;//歌单 +@property (nonatomic,readonly) BOOL isAlbum; //专辑 +@property (nonatomic,readonly) BOOL isRadio; //电台 +@property (nonatomic,readonly) BOOL isDirectory; //普通目录 + +@property (nonatomic,readonly) BOOL isVIP; //VIP歌曲 +@property (nonatomic,readonly) BOOL isSVIP; //SVIP歌曲 - (instancetype)initWithDictionary:(NSDictionary*)dict; - (instancetype)initSongWithId:(NSString *)identifier isFav:(BOOL)isFav; - (instancetype)initWithId:(NSString *)identifier type:(QPlayAutoListItemType)type; +//是否是根节点 - (BOOL)isRoot; + +//是否有更多 - (BOOL)hasMore; + - (QPlayAutoListItem*)findItemWithID:(NSString*)ID; @end /** QPlayAuto请求回调 + + @param success 是否成功 + @param dict 结果Dictionary */ typedef void (^QPlayAutoRequestFinishBlock)(BOOL success, NSDictionary *dict); + @interface QPlayAutoRequestBase : NSObject + +/** 请求类型 */ @property (nonatomic, assign) int type; + @end @interface QPlayAutoSentence : NSObject @@ -200,14 +224,15 @@ typedef void (^QPlayAutoRequestFinishBlock)(BOOL success, NSDictionary *dict); @end @interface QPlayAutoLyric : NSObject -@property(nonatomic,assign) BOOL isTxtType; +@property(nonatomic,assign) BOOL isTxtType;//歌词是不是纯文本的歌词,没有时间标记 @property(nonatomic,strong) NSString *songId; @property(nonatomic,strong) NSString *songName; @property(nonatomic,strong) NSString *singerName; @property(nonatomic,strong) NSString *albumName; -@property(nonatomic,readonly) NSString *text; +@property(nonatomic,readonly) NSString *text;//所有歌词文本 @property(nonatomic,strong) NSArray *sentences; - (NSString *)sentenceAtTime:(NSTimeInterval)time; @end -#endif /* QPlayAutoDefine_h */ \ No newline at end of file + +#endif /* QPlayAutoDefine_h */ diff --git a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/QPlayAutoSDK.h b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/QPlayAutoSDK.h index cbb1665b0..da332dc87 100644 --- a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/QPlayAutoSDK.h +++ b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/QPlayAutoSDK.h @@ -36,9 +36,18 @@ extern NSString const * QPlayAutoSDKVersion; - (void)onLoginStateDidChanged:(BOOL)isLoginOK; @end + + @interface QPlayAutoSDK : NSObject /// 注册App +/// @param name 名称 +/// @param brand 品牌 +/// @param deviceId ? +/// @param scheme 授权成功后Q音跳转合作方的scheme +/// @param appId Q音分配的Id +/// @param secretKey 合作方私钥 +/// @param bundleId 合作方包名 + (void)registerAppWithName:(NSString *)name brand:(NSString *)brand deviceId:(NSString *)deviceId scheme:(NSString *)scheme appId:(NSString *)appId secretKey:(NSString *)secretKey bundleId:(NSString *)bundleId; /// 播放状态 @@ -63,6 +72,7 @@ extern NSString const * QPlayAutoSDKVersion; +(NSString *)openId; +(NSString *)openToken; + ///是否可以处理回调url + (BOOL)canHandleOpenURL:(NSURL *)url; ///处理回调url @@ -71,27 +81,108 @@ extern NSString const * QPlayAutoSDKVersion; /// 回调代理 + (void)setDelegate:(id) delegate; + /// 拉端连接QPlay +/// - Parameter forceLogin: 是否强制登录 + (void)connectAndForceLogin:(BOOL)forceLogin; /// 停止 + (void)stop; -/// 二次热启动连接 + +/// 二次热启动连接(需要联系Q音打开此功能才能使用) +/// - Parameters: +/// - timeout: 超时时间 +/// - completion: 回调 + (void)reconnectWithTimeout:(NSTimeInterval)timeout completion:(QPlayAutoRequestFinishBlock)completion; -/// 播放控制 -+ (void)play; -+ (void)pause; -+ (void)next; -+ (void)previous; -+ (void)seekToTime:(NSTimeInterval)time; +/// 跳转QQ音乐登录 +/// @param bundleId 合作方bundleId +/// @param callbackUrl 跳转合作方url ++ (BOOL)loginQQMusicWithBundleId:(NSString *)bundleId callbackUrl:(NSString *)callbackUrl; + + +/// 获取数据 +/// @param parent 父 +/// @param pageIndex 页码 +/// @param pageSize 页大小 +/// @param completion 回调 ++ (void)getDataItemsFromParent:(QPlayAutoListItem *)parent pageIndex:(NSUInteger)pageIndex pageSize:(NSUInteger)pageSize completion:(QPlayAutoResultParentItemBlock)completion; + + +/// 设置播放模式 +/// @param playMode 播放模式 +/// @param block 回调 ++ (NSInteger)setPlayMode:(QPlayAutoPlayMode)playMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; + + +/// 设置播放整首还是高潮 +/// @param assencceMode 高潮还是整首 +/// @param block 回调 ++ (NSInteger)setAssenceMode:(QPlayAutoAssenceMode)assencceMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; + +/// 收藏/取消收藏(歌曲id) +/// @param song 歌曲 +/// @param isFavorite 收藏/取消收藏 +/// @param completion 回调 ++ (void)setFavoriteStateWithSong:(QPlayAutoListItem *)song isFavorite:(BOOL)isFavorite completion:(void (^)(NSInteger errorCode))completion; + +/// 播放歌曲 +/// @param songList 歌曲列表 +/// @param playIndex 播放索引 +/// @param completion 回调 ++ (void)playAtIndex:(NSArray *)songList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; + + +/// 通过歌曲Mid列表播放歌曲 +/// @param songMidList 歌曲Mid列表 +/// @param playIndex 播放索引 +/// @param completion 回调 ++ (void)playSongMidAtIndex:(NSArray *)songMidList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; + + +///播放下一首 ++ (void)playerPlayNextWithCompletion:(void (^)(NSInteger errorCode))completion; + +///播放上一首 ++ (void)playerPlayPrevWithCompletion:(void (^)(NSInteger errorCode))completion; + +///播放暂停 ++ (void)playerPlayPause; + +///播放恢复 ++ (void)playerPlayResumeWithCompletion:(void (^)(NSInteger errorCode))completion; + +///Seek到指定位置 ++ (void)playerSeek:(NSInteger)position; + + +/// 搜索歌曲 +/// @param keyword 关键词 +/// @param type 搜索类型 +/// @param firstPage 是否第一页 +/// @param completion 回调 ++ (NSInteger)search:(NSString *)keyword + type:(QPlayAutoSearchType)type + firstPage:(BOOL)firstPage + completion:(QPlayAutoResultItemsBlock)completion; + +/// 相似歌曲 +/// @param song 歌曲 +/// @param completion 回调 ++ (void)requestSimilarWithSong:(QPlayAutoListItem *)song completion:(QPlayAutoResultItemsBlock)completion; + + +/// 查询歌词 +/// @param song 歌曲 +/// @param completion 回调 ++ (void)requestLyricWithSong:(QPlayAutoListItem *)song completion:(void (^)(NSInteger errorCode,QPlayAutoLyric *_Nullable lyric))completion; -/// 搜索 -+ (void)searchWithKeyword:(NSString *)keyword type:(QPlayAutoSearchType)type pageIndex:(NSInteger)pageIndex completion:(QPlayAutoResultItemsBlock)completion; -/// 获取歌单内容 -+ (void)getItemsWithParentItem:(QPlayAutoListItem *)parentItem pageIndex:(NSInteger)pageIndex completion:(QPlayAutoResultItemsBlock)completion; +/// 获取特定歌曲列表 +/// @param type 列表类型 +/// @param completion 回调 ++ (void)requestSonglistWithType:(QPlayAutoSongListType)type completion:(QPlayAutoResultItemsBlock)completion; @end -NS_ASSUME_NONNULL_END \ No newline at end of file +NS_ASSUME_NONNULL_END