Browse Source

上传qq音乐优化逻辑

newdev_shunjiawei
liwei1dao 1 year ago
parent
commit
e79fde4085
  1. 3
      ios/Runner/Info.plist
  2. 87
      local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/QQMusicSystemFunctionHandler.kt
  3. 1
      local_plugins/chat_api/ios/chat_api/Sources/chat_api/MusicSystemFunctionHandler.swift
  4. 1
      local_plugins/chat_api/ios/chat_api/Sources/chat_api/QQMusicSystemFunctionHandler.swift
  5. 70
      local_plugins/qq_music/android/src/main/kotlin/com/yunqiinnovation/qq_music/QQMusicLoginManager.kt
  6. 3
      local_plugins/qq_music/android/src/main/kotlin/com/yunqiinnovation/qq_music/QQMusicSingleton.kt

3
ios/Runner/Info.plist

@ -91,6 +91,9 @@
<string>google.navigation</string> <string>google.navigation</string>
<string>googlemaps</string> <string>googlemaps</string>
<string>comgooglemaps</string> <string>comgooglemaps</string>
<string>baidumap</string>
<string>amapuri</string>
<string>maps</string>
</array> </array>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>

87
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 -> qqMusicSingleton.searchSongs(keyword) { searchResult ->
val result = if (searchResult.isSuccess) { val result = if (searchResult.isSuccess) {
val songs = searchResult.getOrNull() ?: emptyList() val songs = searchResult.getOrNull() ?: emptyList()
var playError: Throwable? = null
if (songs.isNotEmpty()) {
// 从搜索结果中提取歌曲MID列表
val songMids = songs.mapNotNull { song ->
val songMap = song as Map<String, Any?>
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) { val processedSongs = when (searchType) {
0 -> { // 歌曲搜索,返回所有结果 0 -> { // 歌曲搜索,返回所有结果
@ -148,7 +167,18 @@ private class QQMusicSearchHandler(private val context: Context?) : FunctionHand
val duration = songMap["duration"] ?: 0 val duration = songMap["duration"] ?: 0
"{\"mid\": \"$mid\", \"name\": \"$name\", \"artist\": \"$artist\", \"album\": \"$album\", \"duration\":$duration,\"pic\": \"$pic\"}" "{\"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 { } else {
val error = searchResult.exceptionOrNull() val error = searchResult.exceptionOrNull()
"{\"success\": false, \"message\": \"搜索失败: ${error?.message}\"}" "{\"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, Any>): 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<String, Any?>
// // 添加调试日志
// 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 { private class QQMusicPlaySongsHandler(private val context: Context?) : FunctionHandler {
override suspend fun handle(arguments: Map<String, Any>): String { override suspend fun handle(arguments: Map<String, Any>): String {

1
local_plugins/chat_api/ios/chat_api/Sources/chat_api/MusicSystemFunctionHandler.swift

@ -67,6 +67,7 @@ private class MusicSearchHandler: FunctionHandler {
let result: [String: Any] = [ let result: [String: Any] = [
"success": true, "success": true,
"broadcast": false, "broadcast": false,
"iscard": true,
"message": "搜索成功,正在播放", "message": "搜索成功,正在播放",
"data": songsJson "data": songsJson
] ]

1
local_plugins/chat_api/ios/chat_api/Sources/chat_api/QQMusicSystemFunctionHandler.swift

@ -162,6 +162,7 @@ private class QQMusicSearchHandler: FunctionHandler {
result = [ result = [
"success": true, "success": true,
"message": "Found \(items.count) songs", "message": "Found \(items.count) songs",
"iscard": true,
"broadcast": false, "broadcast": false,
"data": songs "data": songs
] ]

70
local_plugins/qq_music/android/src/main/kotlin/com/yunqiinnovation/qq_music/QQMusicLoginManager.kt

@ -1,6 +1,7 @@
package com.yunqiinnovation.qq_music package com.yunqiinnovation.qq_music
import android.app.Activity import android.app.Activity
import android.app.ActivityManager
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
@ -18,12 +19,12 @@ import org.json.JSONTokener
* 负责处理QQ音乐的登录授权流程 * 负责处理QQ音乐的登录授权流程
*/ */
class QQMusicLoginManager(private val context: Context) { class QQMusicLoginManager(private val context: Context) {
companion object { companion object {
private const val TAG = "QQMusicLoginManager" private const val TAG = "QQMusicLoginManager"
private const val BASE_SCHEME = "voitrans://" private const val BASE_SCHEME = "voitrans://"
private const val URI_LOGIN = BASE_SCHEME + "login" private const val URI_LOGIN = BASE_SCHEME + "login"
// 定义错误码常量,替代 LoginExampleActivity 中的常量 // 定义错误码常量,替代 LoginExampleActivity 中的常量
const val LOGIN_FAILED = 1 const val LOGIN_FAILED = 1
} }
@ -32,7 +33,7 @@ class QQMusicLoginManager(private val context: Context) {
private var qqMusicApi: IQQMusicApi? = null private var qqMusicApi: IQQMusicApi? = null
private lateinit var qqMusicApiWrapper: QQMusicApiWrapper private lateinit var qqMusicApiWrapper: QQMusicApiWrapper
private val handler = Handler(Looper.getMainLooper()) private val handler = Handler(Looper.getMainLooper())
/** /**
* 登录结果回调接口 * 登录结果回调接口
*/ */
@ -51,57 +52,57 @@ class QQMusicLoginManager(private val context: Context) {
*/ */
fun startLogin(callback: LoginCallback) { fun startLogin(callback: LoginCallback) {
Log.d(TAG, "开始QQ音乐登录流程") Log.d(TAG, "开始QQ音乐登录流程")
// 检查配置 // 检查配置
if (Config.OPENID_APPID.isEmpty() || Config.OPENID_APP_PRIVATE_KEY.isEmpty()) { if (Config.OPENID_APPID.isEmpty() || Config.OPENID_APP_PRIVATE_KEY.isEmpty()) {
callback.onError("CONFIG_ERROR", "请先配置APPID和私钥") callback.onError("CONFIG_ERROR", "请先配置APPID和私钥")
return return
} }
// 初始化绑定助手 // 初始化绑定助手
qPlayBindHelper = QPlayBindHelper(context) qPlayBindHelper = QPlayBindHelper(context)
// 开始绑定QQ音乐服务 // 开始绑定QQ音乐服务
bindQQMusicService(callback) bindQQMusicService(callback)
} }
/** /**
* 绑定QQ音乐服务 * 绑定QQ音乐服务
*/ */
private fun bindQQMusicService(callback: LoginCallback) { private fun bindQQMusicService(callback: LoginCallback) {
Log.d(TAG, "开始绑定QQ音乐服务") Log.d(TAG, "开始绑定QQ音乐服务")
qPlayBindHelper.ensureQQMusicBindByStartProcess { success -> qPlayBindHelper.ensureQQMusicBindByStartProcess { success ->
if (success && qPlayBindHelper.isBindQQMusic()) { if (success && qPlayBindHelper.isBindQQMusic()) {
Log.d(TAG, "QQ音乐服务绑定成功") Log.d(TAG, "QQ音乐服务绑定成功")
qqMusicApi = qPlayBindHelper.getQQMusicApi()!! qqMusicApi = qPlayBindHelper.getQQMusicApi()!!
qqMusicApiWrapper = QQMusicApiWrapper(qqMusicApi!!) qqMusicApiWrapper = QQMusicApiWrapper(qqMusicApi!!)
// 检查是否已经授权 // 检查是否已经授权
checkAuthStatus(callback) checkAuthStatus(callback)
} else { } else {
Log.e(TAG, "QQ音乐服务绑定失败") Log.e(TAG, "QQ音乐服务绑定失败")
callback.onError("APP_NOT_INSTALLED", "请先安装QQ音乐App才能使用音乐功能") callback.onError("APP_NOT_INSTALLED", "请先安装QQ音乐App才能使用音乐功能")
} }
} }
} }
/** /**
* 检查授权状态 * 检查授权状态
*/ */
private fun checkAuthStatus(callback: LoginCallback) { private fun checkAuthStatus(callback: LoginCallback) {
Log.d(TAG, "检查授权状态") Log.d(TAG, "检查授权状态")
val bundle = Bundle().apply { val bundle = Bundle().apply {
putInt(Keys.API_PARAM_KEY_SDK_VERSION, CommonCmd.SDK_VERSION) putInt(Keys.API_PARAM_KEY_SDK_VERSION, CommonCmd.SDK_VERSION)
putString(Keys.API_PARAM_KEY_PLATFORM_TYPE, Config.BIND_PLATFORM) putString(Keys.API_PARAM_KEY_PLATFORM_TYPE, Config.BIND_PLATFORM)
} }
try { try {
val result = qqMusicApi?.execute("hi", bundle) val result = qqMusicApi?.execute("hi", bundle)
val code = result?.getInt(Keys.API_RETURN_KEY_CODE) val code = result?.getInt(Keys.API_RETURN_KEY_CODE)
when (code) { when (code) {
ErrorCodes.ERROR_OK -> { ErrorCodes.ERROR_OK -> {
// 已授权,直接请求登录信息 // 已授权,直接请求登录信息
@ -147,21 +148,46 @@ class QQMusicLoginManager(private val context: Context) {
*/ */
fun startAuthProcess2(callback: LoginCallback) { fun startAuthProcess2(callback: LoginCallback) {
Log.d(TAG, "启动QQ音乐授权流程") 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音乐登录 // 启动QQ音乐登录
// CommonCmd.startQQMusicProcess(context,context.packageName) // CommonCmd.startQQMusicProcess(context,context.packageName)
CommonCmd.loginQQMusic( isBindQQMusicService = true
context,
context.packageName, Handler(Looper.getMainLooper()).postDelayed({
BASE_SCHEME callback.onSuccess()
) }, 1000) // 延迟500ms
callback.onSuccess()
// 等待用户登录完成后进行身份验证 // 等待用户登录完成后进行身份验证
// handler.postDelayed({ // handler.postDelayed({
// verifyIdentity(callback) // verifyIdentity(callback)
// }, 3000) // 给用户足够的登录时间 // }, 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
}
/** /**
* 启动授权流程 * 启动授权流程
*/ */

3
local_plugins/qq_music/android/src/main/kotlin/com/yunqiinnovation/qq_music/QQMusicSingleton.kt

@ -573,7 +573,8 @@ class QQMusicSingleton private constructor() {
musicManager?.bindQQMusicApiService() musicManager?.bindQQMusicApiService()
callback(Result.failure(Exception("播放失败: $errorMessage"))) callback(Result.failure(Exception("播放失败: $errorMessage")))
} else if (errorCode == 1030) { } else if (errorCode == 1030) {
callback(Result.success(Unit)) callback(Result.failure(Exception("播放失败: $errorMessage")))
// callback(Result.success(Unit))
}else{ }else{
callback(Result.failure(Exception("播放失败: $errorMessage"))) callback(Result.failure(Exception("播放失败: $errorMessage")))
} }

Loading…
Cancel
Save