From e79fde408513a1661dfe4b601eb4c9d14791bfc2 Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Fri, 19 Sep 2025 19:34:30 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0qq=E9=9F=B3=E4=B9=90=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Runner/Info.plist | 3 + .../chat_api/QQMusicSystemFunctionHandler.kt | 87 +++++++------------ .../chat_api/MusicSystemFunctionHandler.swift | 1 + .../QQMusicSystemFunctionHandler.swift | 1 + .../qq_music/QQMusicLoginManager.kt | 70 ++++++++++----- .../qq_music/QQMusicSingleton.kt | 3 +- 6 files changed, 87 insertions(+), 78 deletions(-) diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 1087023b6..ec7521c06 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -91,6 +91,9 @@ google.navigation googlemaps comgooglemaps + baidumap + amapuri + maps LSRequiresIPhoneOS diff --git a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/QQMusicSystemFunctionHandler.kt b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/QQMusicSystemFunctionHandler.kt index db3684402..a820c23d3 100644 --- a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/QQMusicSystemFunctionHandler.kt +++ b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/QQMusicSystemFunctionHandler.kt @@ -124,7 +124,26 @@ private class QQMusicSearchHandler(private val context: Context?) : FunctionHand qqMusicSingleton.searchSongs(keyword) { searchResult -> val result = if (searchResult.isSuccess) { val songs = searchResult.getOrNull() ?: emptyList() - + var playError: Throwable? = null + if (songs.isNotEmpty()) { + // 从搜索结果中提取歌曲MID列表 + val songMids = songs.mapNotNull { song -> + val songMap = song as Map + songMap["mid"] as? String + }.filter { it.isNotEmpty() } + + if (songMids.isNotEmpty()) { + // 播放搜索到的歌曲列表,从第一首开始播放 + qqMusicSingleton.playSongs(songMids, 0) { playResult -> + Log.d("QQMusicSearchHandler", "播放结果: ${playResult.isSuccess}") + if (!playResult.isSuccess) { + playError = playResult.exceptionOrNull() +// Log.e("QQMusicSearchHandler", "播放失败: ${playError?.message}") + } + } + } + } + // 根据搜索类型处理结果 val processedSongs = when (searchType) { 0 -> { // 歌曲搜索,返回所有结果 @@ -148,7 +167,18 @@ private class QQMusicSearchHandler(private val context: Context?) : FunctionHand val duration = songMap["duration"] ?: 0 "{\"mid\": \"$mid\", \"name\": \"$name\", \"artist\": \"$artist\", \"album\": \"$album\", \"duration\":$duration,\"pic\": \"$pic\"}" } - "{\"success\": true,\"iscard\": true, \"broadcast\": false, \"message\": \"搜索成功,正在播放\", \"data\": [$songsJson]}" + + if (songs.isNotEmpty()) { + if (playError == null){ + "{\"success\": true, \"iscard\": true, \"broadcast\": false, \"message\": \"搜索成功,正在播放\", \"data\": [$songsJson]}" + }else{ + Log.e("QQMusicSearchHandler", "播放失败: ${playError?.message}") + "{\"success\": false, \"iscard\": true, \"broadcast\": true, \"message\": \"${playError?.message}\", \"data\": [$songsJson]}" + } + + } else { + "{\"success\": false, \"message\": \"未找到相关歌曲\"}" + } } else { val error = searchResult.exceptionOrNull() "{\"success\": false, \"message\": \"搜索失败: ${error?.message}\"}" @@ -163,59 +193,6 @@ private class QQMusicSearchHandler(private val context: Context?) : FunctionHand } } } -//private class QQMusicSearchHandler(private val context: Context?) : FunctionHandler { -// override suspend fun handle(arguments: Map): String { -// return try { -// val keyword = arguments["keyword"] as? String ?: return "{\"success\": false, \"message\": \"缺少搜索关键词\"}" -// val searchType = arguments["searchType"] as? Int ?: 0 // 默认搜索歌曲 -// val qqMusicSingleton = QQMusicSingleton.getInstance() -// var result = "" -// -// // 直接调用搜索,内部会自动处理登录检查 -// qqMusicSingleton.searchSongs(keyword) { searchResult -> -// result = if (searchResult.isSuccess) { -// val songs = searchResult.getOrNull() ?: emptyList() -// -// // 根据搜索类型处理结果 -// val processedSongs = when (searchType) { -// 0 -> { // 歌曲搜索,只返回第一个结果 -//// if (songs.isNotEmpty()) listOf(songs.first()) else emptyList() -// songs -// } -// else -> { // 专辑、歌手等其他类型,返回所有结果 -// songs -// } -// } -// -// val songsJson = processedSongs.joinToString(",") { song -> -// val songMap = song as Map -// // 添加调试日志 -// Log.d("QQMusicSearchHandler", "原始数据: $songMap") -// // 修正字段名映射 -// val mid = songMap["mid"] ?: "unknown" -// val name = songMap["name"] ?: "unknown" -// val artist = songMap["singer"] ?: "unknown" -// val album = songMap["album"] ?: "" -// val pic = songMap["pic"] ?: "" -// val duration = songMap["duration"] ?: 0 -// "{\"mid\": \"$mid\", \"name\": \"$name\", \"artist\": \"$artist\", \"album\": \"$album\", \"duration\":$duration,\"pic\": \"$pic\"}" -// } -// "{\"success\": true, \"broadcast\": false, \"message\": \"搜索成功,增在播放\", \"data\": [$songsJson]}" -// } else { -// val error = searchResult.exceptionOrNull() -// "{\"success\": false, \"message\": \"搜索失败: ${error?.message}\"}" -// } -// } -// -// // 等待回调完成 -// delay(5000) -// result.ifEmpty { "{\"success\": false, \"message\": \"搜索超时\"}" } -// } catch (e: Exception) { -// Log.e("QQMusicSearchHandler", "QQ音乐搜索失败", e) -// "{\"success\": false, \"message\": \"搜索异常: ${e.message}\"}" -// } -// } -//} private class QQMusicPlaySongsHandler(private val context: Context?) : FunctionHandler { override suspend fun handle(arguments: Map): String { diff --git a/local_plugins/chat_api/ios/chat_api/Sources/chat_api/MusicSystemFunctionHandler.swift b/local_plugins/chat_api/ios/chat_api/Sources/chat_api/MusicSystemFunctionHandler.swift index c2e2c3409..9d65f4fdd 100644 --- a/local_plugins/chat_api/ios/chat_api/Sources/chat_api/MusicSystemFunctionHandler.swift +++ b/local_plugins/chat_api/ios/chat_api/Sources/chat_api/MusicSystemFunctionHandler.swift @@ -67,6 +67,7 @@ private class MusicSearchHandler: FunctionHandler { let result: [String: Any] = [ "success": true, "broadcast": false, + "iscard": true, "message": "搜索成功,正在播放", "data": songsJson ] 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 index c8c3144aa..2558ca63b 100644 --- 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 @@ -162,6 +162,7 @@ private class QQMusicSearchHandler: FunctionHandler { result = [ "success": true, "message": "Found \(items.count) songs", + "iscard": true, "broadcast": false, "data": songs ] diff --git a/local_plugins/qq_music/android/src/main/kotlin/com/yunqiinnovation/qq_music/QQMusicLoginManager.kt b/local_plugins/qq_music/android/src/main/kotlin/com/yunqiinnovation/qq_music/QQMusicLoginManager.kt index a9474d997..396c6cf76 100644 --- a/local_plugins/qq_music/android/src/main/kotlin/com/yunqiinnovation/qq_music/QQMusicLoginManager.kt +++ b/local_plugins/qq_music/android/src/main/kotlin/com/yunqiinnovation/qq_music/QQMusicLoginManager.kt @@ -1,6 +1,7 @@ package com.yunqiinnovation.qq_music import android.app.Activity +import android.app.ActivityManager import android.content.Context import android.os.Bundle import android.os.Handler @@ -18,12 +19,12 @@ import org.json.JSONTokener * 负责处理QQ音乐的登录授权流程 */ class QQMusicLoginManager(private val context: Context) { - + companion object { private const val TAG = "QQMusicLoginManager" private const val BASE_SCHEME = "voitrans://" private const val URI_LOGIN = BASE_SCHEME + "login" - + // 定义错误码常量,替代 LoginExampleActivity 中的常量 const val LOGIN_FAILED = 1 } @@ -32,7 +33,7 @@ class QQMusicLoginManager(private val context: Context) { private var qqMusicApi: IQQMusicApi? = null private lateinit var qqMusicApiWrapper: QQMusicApiWrapper private val handler = Handler(Looper.getMainLooper()) - + /** * 登录结果回调接口 */ @@ -51,57 +52,57 @@ class QQMusicLoginManager(private val context: Context) { */ fun startLogin(callback: LoginCallback) { Log.d(TAG, "开始QQ音乐登录流程") - + // 检查配置 if (Config.OPENID_APPID.isEmpty() || Config.OPENID_APP_PRIVATE_KEY.isEmpty()) { callback.onError("CONFIG_ERROR", "请先配置APPID和私钥") return } - + // 初始化绑定助手 qPlayBindHelper = QPlayBindHelper(context) - + // 开始绑定QQ音乐服务 bindQQMusicService(callback) } - + /** * 绑定QQ音乐服务 */ private fun bindQQMusicService(callback: LoginCallback) { Log.d(TAG, "开始绑定QQ音乐服务") - + qPlayBindHelper.ensureQQMusicBindByStartProcess { success -> if (success && qPlayBindHelper.isBindQQMusic()) { Log.d(TAG, "QQ音乐服务绑定成功") qqMusicApi = qPlayBindHelper.getQQMusicApi()!! qqMusicApiWrapper = QQMusicApiWrapper(qqMusicApi!!) - + // 检查是否已经授权 checkAuthStatus(callback) - + } else { Log.e(TAG, "QQ音乐服务绑定失败") callback.onError("APP_NOT_INSTALLED", "请先安装QQ音乐App才能使用音乐功能") } } } - + /** * 检查授权状态 */ private fun checkAuthStatus(callback: LoginCallback) { Log.d(TAG, "检查授权状态") - + val bundle = Bundle().apply { putInt(Keys.API_PARAM_KEY_SDK_VERSION, CommonCmd.SDK_VERSION) putString(Keys.API_PARAM_KEY_PLATFORM_TYPE, Config.BIND_PLATFORM) } - + try { val result = qqMusicApi?.execute("hi", bundle) val code = result?.getInt(Keys.API_RETURN_KEY_CODE) - + when (code) { ErrorCodes.ERROR_OK -> { // 已授权,直接请求登录信息 @@ -147,21 +148,46 @@ class QQMusicLoginManager(private val context: Context) { */ fun startAuthProcess2(callback: LoginCallback) { Log.d(TAG, "启动QQ音乐授权流程") - + if (isAppInForeground(context)) { + CommonCmd.loginQQMusic( + context, + context.packageName, + BASE_SCHEME + ) +// Log.d(TAG, "当前是前台服务") + } else { + // CommonCmd.loginQQMusic( + // context, + // context.packageName, + // BASE_SCHEME, + // ) + Log.d(TAG, "当前是后台服务") + } // 启动QQ音乐登录 // CommonCmd.startQQMusicProcess(context,context.packageName) - CommonCmd.loginQQMusic( - context, - context.packageName, - BASE_SCHEME - ) - callback.onSuccess() + isBindQQMusicService = true + + Handler(Looper.getMainLooper()).postDelayed({ + callback.onSuccess() + }, 1000) // 延迟500ms + + // 等待用户登录完成后进行身份验证 // handler.postDelayed({ // verifyIdentity(callback) // }, 3000) // 给用户足够的登录时间 } - + private fun isAppInForeground(context: Context): Boolean { + val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager + val appProcesses = activityManager.runningAppProcesses ?: return false + val packageName = context.packageName + for (appProcess in appProcesses) { + if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName == packageName) { + return true + } + } + return false + } /** * 启动授权流程 */ diff --git a/local_plugins/qq_music/android/src/main/kotlin/com/yunqiinnovation/qq_music/QQMusicSingleton.kt b/local_plugins/qq_music/android/src/main/kotlin/com/yunqiinnovation/qq_music/QQMusicSingleton.kt index 5c87e6c94..c69c781cd 100644 --- a/local_plugins/qq_music/android/src/main/kotlin/com/yunqiinnovation/qq_music/QQMusicSingleton.kt +++ b/local_plugins/qq_music/android/src/main/kotlin/com/yunqiinnovation/qq_music/QQMusicSingleton.kt @@ -573,7 +573,8 @@ class QQMusicSingleton private constructor() { musicManager?.bindQQMusicApiService() callback(Result.failure(Exception("播放失败: $errorMessage"))) } else if (errorCode == 1030) { - callback(Result.success(Unit)) + callback(Result.failure(Exception("播放失败: $errorMessage"))) +// callback(Result.success(Unit)) }else{ callback(Result.failure(Exception("播放失败: $errorMessage"))) }