Browse Source

qq音乐优化

weicu
liwei1dao 1 year ago
parent
commit
35441980f1
  1. BIN
      assets/images/qqmusic.png
  2. 14
      lib/data/services/qq_musoc.dart
  3. 58
      lib/modules/agent/controllers/agent_controller.dart
  4. 81
      lib/modules/agent/views/music_card.dart
  5. 84
      lib/modules/agent/views/qqmusic_card.dart
  6. 130
      lib/modules/music/views/music_playlist_view.dart
  7. 5
      lib/modules/qqmusic/controllers/qqmusic_playlist_controller.dart
  8. 151
      lib/modules/qqmusic/views/qqmusic_playlist_view.dart
  9. 3
      local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/QQMusicSystemFunctionHandler.kt
  10. 238
      local_plugins/qq_music/ios/qq_music/ios-sdk/QPlayAutoSDK/Headers/include/QPlayAutoDefine.h
  11. 188
      local_plugins/qq_music/ios/qq_music/ios-sdk/QPlayAutoSDK/Headers/include/QPlayAutoSDK.h
  12. BIN
      local_plugins/qq_music/ios/qq_music/ios-sdk/QPlayAutoSDK/libQPlayAutoSDK.a
  13. 1
      pubspec.yaml

BIN
assets/images/qqmusic.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

14
lib/data/services/qq_musoc.dart

@ -35,7 +35,7 @@ class QqMusocService extends GetxService {
final result = await _qqMusic.login();
if (result['success'] == true) {
print('QQ音乐自动登录成功: ${result['openId']}');
Future.delayed(Duration(milliseconds: 500), () {
Future.delayed(Duration(milliseconds: 1000), () {
syncCurrentPlayInfo();
});
} else {
@ -270,8 +270,9 @@ class QqMusocService extends GetxService {
currentPosition.value = 0;
// 启动全局状态监听
// print('🎵 [QQMusicService] 开始播放,启动全局状态监听');
syncCurrentPlayInfo();
Future.delayed(Duration(milliseconds: 500), () {
syncCurrentPlayInfo();
});
_notifyListeners();
}
@ -288,7 +289,12 @@ class QqMusocService extends GetxService {
final result = await _qqMusic.playMusic();
if (result['success'] == true) {
isPlaying.value = true;
startPlaybackStateMonitor();
currentPosition.value = 0;
// 启动全局状态监听
Future.delayed(Duration(milliseconds: 500), () {
syncCurrentPlayInfo();
});
_notifyListeners();
}
return result;

58
lib/modules/agent/controllers/agent_controller.dart

@ -3,6 +3,10 @@ import 'dart:convert';
import 'dart:ffi';
import 'dart:io';
import 'package:amap_service/amap_service.dart';
import 'package:voitrans/data/models/song_model.dart';
import 'package:voitrans/data/services/ble_manager.dart';
import 'package:voitrans/data/services/bluetooth_manager.dart';
import 'package:voitrans/data/services/qq_musoc.dart';
import '../../../data/services/novice_guide_service.dart';
import '/core/utils/upload_oss.dart';
import '/data/models/user_Info.dart';
@ -733,7 +737,9 @@ class AgentController extends GetxController {
as Map<String, dynamic>;
final data = qqmusic_search_songs['data'];
if (data != null && data is List) {
_qqmusicManager.syncCurrentPlayInfo();
Future.delayed(Duration(seconds: 1), () {
_qqmusicManager.syncCurrentPlayInfo();
});
}
} else if (metaResult.containsKey("maps_route_navigation")) {
//导航
@ -1967,4 +1973,54 @@ class AgentController extends GetxController {
await seekToProgress(
currentIdInternal, newPosition, newDuration, newProgress);
}
/// 处理来自系统通知栏的停止操作
Future<void> playQQMusic(
List<SongModel> songs, SongModel song, int index) async {
try {
if (_qqmusicManager.isPlaying.value) {
if (_qqmusicManager.currentSong.value?.mid == song.mid) {
// 当前歌曲正在播放,暂停它
await _qqmusicManager.pauseMusic();
} else {
final songMids = songs.map((s) => s.mid).toList();
// 其他歌曲正在播放,播放这首歌
final result = await _qqmusicManager.playSongs(
songMids: songMids,
index: index,
songList: [song],
currentSongModel: song,
);
if (result['success'] == true) {
// 播放成功后,如果歌曲不在当前列表中,保持列表显示状态不变
// Get.snackbar('开始播放', song.name);
_qqmusicManager.syncCurrentPlayInfo();
}
return;
}
} else {
if (_qqmusicManager.currentSong.value?.mid == song.mid) {
// 当前歌曲已暂停,恢复播放
await _qqmusicManager.resumeMusic();
} else {
final songMids = songs.map((s) => s.mid).toList();
// 播放新歌曲
final result = await _qqmusicManager.playSongs(
songMids: songMids,
index: index,
songList: [song],
currentSongModel: song,
);
if (result['success'] == true) {
// 播放成功后,如果歌曲不在当前列表中,保持列表显示状态不变
// Get.snackbar('开始播放', song.name);
_qqmusicManager.syncCurrentPlayInfo();
}
}
}
} catch (e) {
// 静默处理错误,避免影响用户体验
print('播放控制失败: $e');
}
}
}

81
lib/modules/agent/views/music_card.dart

@ -42,20 +42,60 @@ Widget buildMusicItem(BuildContext context, int id, String name, String url,
decoration: BoxDecoration(
color: isDarkMode ? Colors.grey[800] : Colors.grey[100],
borderRadius: BorderRadius.circular(8.r),
image: image.isNotEmpty
? DecorationImage(
image: NetworkImage(image),
fit: BoxFit.cover,
)
: null,
),
child: image.isEmpty
? Icon(
Icons.music_note,
size: 18.sp,
color: Theme.of(context).primaryColor,
)
: null,
child: Stack(
children: [
// 主图片
Container(
width: 50.w,
height: 50.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.r),
image: image.isNotEmpty
? DecorationImage(
image: NetworkImage(image),
fit: BoxFit.cover,
)
: null,
),
child: image.isEmpty
? Icon(
Icons.music_note,
size: 18.sp,
color: Theme.of(context).primaryColor,
)
: null,
),
// 右下角音乐图标
if (image.isNotEmpty)
Positioned(
right: 2.w,
bottom: 2.w,
child: Container(
width: 12.w,
height: 12.w,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(2.r),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 1,
offset: const Offset(0, 0.5),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(2.r),
child: Image.asset(
'assets/images/qqmusic.png',
fit: BoxFit.contain,
),
),
),
),
],
),
),
SizedBox(width: 12.w),
Expanded(
@ -158,21 +198,6 @@ Widget buildMusicContent(
),
),
const SizedBox(height: 12),
// Container(
// padding: const EdgeInsets.all(12),
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(12),
// boxShadow: [
// BoxShadow(
// color: Colors.black.withOpacity(0.03),
// blurRadius: 3,
// spreadRadius: 1,
// offset: const Offset(0, 1),
// ),
// ],
// ),
// child:
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [

84
lib/modules/agent/views/qqmusic_card.dart

@ -1,10 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:voitrans/modules/agent/widgets/circular_progress_button.dart';
import '../../../routes/app_routes.dart';
import '../../../data/services/qq_musoc.dart';
import '../../../data/models/song_model.dart';
import 'circular_progress_button.dart';
/// 构建音乐项目
Widget buildQQMusicItem(
@ -34,20 +34,46 @@ Widget buildQQMusicItem(
decoration: BoxDecoration(
color: isDarkMode ? Colors.grey[800] : Colors.grey[100],
borderRadius: BorderRadius.circular(8.r),
image: song.albumPic!.isNotEmpty
? DecorationImage(
image: NetworkImage(song.albumPic!),
fit: BoxFit.cover,
)
: null,
),
child: song.albumPic!.isEmpty
? Icon(
Icons.music_note,
size: 18.sp,
color: Theme.of(context).primaryColor,
)
: null,
child: Stack(
children: [
// 主图片
Container(
width: 50.w,
height: 50.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.r),
image: song.albumPic!.isNotEmpty
? DecorationImage(
image: NetworkImage(song.albumPic!),
fit: BoxFit.cover,
)
: null,
),
child: song.albumPic!.isEmpty
? Icon(
Icons.music_note,
size: 18.sp,
color: Theme.of(context).primaryColor,
)
: null,
),
// 右下角音乐图标
if (song.albumPic!.isNotEmpty)
Positioned(
right: 0.w,
bottom: 0.w,
child: Container(
width: 12.w,
height: 12.w,
child: Image.asset(
'assets/images/qqmusic.png',
fit: BoxFit.contain,
),
),
),
],
),
),
SizedBox(width: 12.w),
Expanded(
@ -105,12 +131,19 @@ Widget buildQQMusicItem(
} else {
final songMids = songs.map((s) => s.mid).toList();
// 其他歌曲正在播放,播放这首歌
await qqMusicService.playSongs(
final result = await qqMusicService.playSongs(
songMids: songMids,
index: index,
songList: [song],
currentSongModel: song,
);
if (result['success'] == true) {
// 播放成功后,如果歌曲不在当前列表中,保持列表显示状态不变
Get.snackbar('开始播放', song.name);
// qqMusicService.syncCurrentPlayInfo();
} else {
Get.snackbar('播放失败', result['error'] ?? '未知错误');
}
}
} else {
if (qqMusicService.currentSong.value?.mid == song.mid) {
@ -119,12 +152,19 @@ Widget buildQQMusicItem(
} else {
final songMids = songs.map((s) => s.mid).toList();
// 播放新歌曲
await qqMusicService.playSongs(
final result = await qqMusicService.playSongs(
songMids: songMids,
index: index,
songList: [song],
currentSongModel: song,
);
if (result['success'] == true) {
// 播放成功后,如果歌曲不在当前列表中,保持列表显示状态不变
Get.snackbar('开始播放', song.name);
// qqMusicService.syncCurrentPlayInfo();
} else {
Get.snackbar('播放失败', result['error'] ?? '未知错误');
}
}
}
} catch (e) {
@ -168,11 +208,13 @@ Widget buildQQMusicContent(BuildContext context, List<SongModel> songs) {
children: [
Row(
children: [
Icon(
Icons.music_note,
size: 16,
// ignore: deprecated_member_use
color: Theme.of(context).primaryColor.withOpacity(0.7),
Container(
width: 18.w,
height: 18.w,
child: Image.asset(
'assets/images/qqmusic.png',
fit: BoxFit.contain,
),
),
const SizedBox(width: 6),
Text(

130
lib/modules/music/views/music_playlist_view.dart

@ -265,28 +265,63 @@ class MusicPlaylistView extends StatelessWidget {
),
],
),
child: image.isNotEmpty
? ClipRRect(
borderRadius: BorderRadius.circular(10.r),
child: Image.network(
image,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return Icon(
Icons.music_note,
color: isDarkMode
? Colors.grey[500]
: Colors.grey[600],
size: 24.w,
);
},
child: Stack(
children: [
image.isNotEmpty
? ClipRRect(
borderRadius: BorderRadius.circular(10.r),
child: Image.network(
image,
width: 52.w,
height: 52.w,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return Icon(
Icons.music_note,
color: isDarkMode
? Colors.grey[500]
: Colors.grey[600],
size: 24.w,
);
},
),
)
: Icon(
Icons.music_note,
color:
isDarkMode ? Colors.grey[500] : Colors.grey[600],
size: 24.w,
),
// 右下角音乐图标
if (image.isNotEmpty)
Positioned(
right: 2.w,
bottom: 2.w,
child: Container(
width: 14.w,
height: 14.w,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(2.r),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 1,
offset: const Offset(0, 0.5),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(2.r),
child: Image.asset(
'assets/images/qqmusic.png',
fit: BoxFit.contain,
),
),
),
)
: Icon(
Icons.music_note,
color: isDarkMode ? Colors.grey[500] : Colors.grey[600],
size: 24.w,
),
],
),
),
SizedBox(width: 14.w),
// 歌曲信息
@ -391,17 +426,50 @@ class MusicPlaylistView extends StatelessWidget {
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(16.r),
child: coverUrl.isNotEmpty
? Image.network(
coverUrl,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return _buildDefaultCover(isDarkMode, size: size);
},
)
: _buildDefaultCover(isDarkMode, size: size),
child: Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(16.r),
child: coverUrl.isNotEmpty
? Image.network(
coverUrl,
fit: BoxFit.cover,
width: size,
height: size,
errorBuilder: (context, error, stackTrace) {
return _buildDefaultCover(isDarkMode, size: size);
},
)
: _buildDefaultCover(isDarkMode, size: size),
),
// 右下角音乐图标
Positioned(
right: 4.w,
bottom: 4.w,
child: Container(
width: size * 0.25,
height: size * 0.25,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4.r),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 2,
offset: const Offset(0, 1),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(4.r),
child: Image.asset(
'assets/images/qqmusic.png',
fit: BoxFit.contain,
),
),
),
),
],
),
);
}

5
lib/modules/qqmusic/controllers/qqmusic_playlist_controller.dart

@ -144,6 +144,7 @@ class QQMusicPlaylistController extends GetxController {
/// 播放歌曲
Future<void> playSong(SongModel song, {List<SongModel>? songList}) async {
try {
displayIsPlaying.value = true;
// 使用传入的歌曲列表或当前播放列表
final List<SongModel> finalSongList = songList ?? playlist.toList();
final songMids = finalSongList.map((s) => s.mid).toList();
@ -162,8 +163,10 @@ class QQMusicPlaylistController extends GetxController {
if (result['success'] == true) {
// 播放成功后,如果歌曲不在当前列表中,保持列表显示状态不变
Get.snackbar('开始播放', song.name);
// _qqMusicService.syncCurrentPlayInfo();
} else {
Get.snackbar('播放失败', result['error'] ?? '未知错误');
displayIsPlaying.value = false;
}
return;
}
@ -181,7 +184,7 @@ class QQMusicPlaylistController extends GetxController {
if (result['success'] == true) {
displayIsPlaying.value = true;
_qqMusicService.syncCurrentPlayInfo();
// _qqMusicService.syncCurrentPlayInfo();
Get.snackbar('开始播放', song.name);
} else {
displayIsPlaying.value = false;

151
lib/modules/qqmusic/views/qqmusic_playlist_view.dart

@ -1,11 +1,10 @@
import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:voitrans/modules/agent/widgets/circular_progress_button.dart';
import 'package:voitrans/modules/qqmusic/controllers/qqmusic_playlist_controller.dart';
import 'package:voitrans/data/models/song_model.dart'; // Use the data model instead
import '../../../core/utils/logger.dart';
import '../../agent/controllers/agent_controller.dart';
import '../../agent/views/circular_progress_button.dart';
class QqmusicPlaylistView extends GetView<QQMusicPlaylistController> {
const QqmusicPlaylistView({Key? key}) : super(key: key);
@ -211,19 +210,40 @@ class QqmusicPlaylistView extends GetView<QQMusicPlaylistController> {
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(10.r),
child: Image.network(
song.albumPic ?? '',
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return Icon(
Icons.music_note,
color: isDarkMode ? Colors.grey[500] : Colors.grey[600],
size: 24.w,
);
},
),
child: Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(10.r),
child: Image.network(
song.albumPic ?? '',
width: 52.w,
height: 52.w,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return Icon(
Icons.music_note,
color: isDarkMode
? Colors.grey[500]
: Colors.grey[600],
size: 24.w,
);
},
),
),
// 右下角音乐图标
Positioned(
right: 0.w,
bottom: 0.w,
child: Container(
width: 14.w,
height: 14.w,
child: Image.asset(
'assets/images/qqmusic.png',
fit: BoxFit.contain,
),
),
),
],
)),
SizedBox(width: 14.w),
// 歌曲信息
@ -325,17 +345,39 @@ class QqmusicPlaylistView extends GetView<QQMusicPlaylistController> {
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(16.r),
child: coverUrl.isNotEmpty
? Image.network(
coverUrl,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return _buildDefaultCover(isDarkMode, size: size);
},
)
: _buildDefaultCover(isDarkMode, size: size),
child: Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(16.r),
child: coverUrl.isNotEmpty
? Image.network(
coverUrl,
fit: BoxFit.cover,
width: size,
height: size,
errorBuilder: (context, error, stackTrace) {
return _buildDefaultCover(isDarkMode, size: size);
},
)
: _buildDefaultCover(isDarkMode, size: size),
),
// 右下角音乐图标
Positioned(
right: 0.w,
bottom: 0.w,
child: Container(
width: size * 0.3,
height: size * 0.3,
child: ClipRRect(
borderRadius: BorderRadius.circular(4.r),
child: Image.asset(
'assets/images/qqmusic.png',
fit: BoxFit.contain,
),
),
),
),
],
),
);
}
@ -603,61 +645,4 @@ class QqmusicPlaylistView extends GetView<QQMusicPlaylistController> {
final seconds = duration.inSeconds % 60;
return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
}
// 播放/暂停切换
// Future<void> _togglePlayPause() async {
// if (controller.actualIsPlaying.value) {
// await controller.musicPause();
// } else {
// await controller.musicResume();
// }
// }
// 播放上一曲
Future<void> _playPrevious(
AgentController controller, List<Map<String, dynamic>> playlist) async {
// 防止重复点击导致的状态混乱
if (controller.isLoadingMusic.value) {
return;
}
try {
// 设置加载状态,防止重复操作
controller.isLoadingMusic.value = true;
// 更新播放列表上下文
controller.updateCurrentPlaylistContext(
playlist, controller.currentId.value);
// 执行上一曲操作
await controller.playPrevious();
} finally {
// 确保加载状态被重置
controller.isLoadingMusic.value = false;
}
}
// 播放下一曲
Future<void> _playNext(
AgentController controller, List<Map<String, dynamic>> playlist) async {
// 防止重复点击导致的状态混乱
if (controller.isLoadingMusic.value) {
return;
}
try {
// 设置加载状态,防止重复操作
controller.isLoadingMusic.value = true;
// 更新播放列表上下文
controller.updateCurrentPlaylistContext(
playlist, controller.currentId.value);
// 执行下一曲操作
await controller.playNext();
} finally {
// 确保加载状态被重置
controller.isLoadingMusic.value = false;
}
}
}

3
local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/QQMusicSystemFunctionHandler.kt

@ -212,7 +212,8 @@ private class QQMusicSearchHandler(private val context: Context?) : FunctionHand
// 根据搜索类型处理结果
val processedSongs = when (searchType) {
0 -> { // 歌曲搜索,只返回第一个结果
if (songs.isNotEmpty()) listOf(songs.first()) else emptyList()
// if (songs.isNotEmpty()) listOf(songs.first()) else emptyList()
songs
}
else -> { // 专辑、歌手等其他类型,返回所有结果
songs

238
local_plugins/qq_music/ios/qq_music/ios-sdk/QPlayAutoSDK/Headers/include/QPlayAutoDefine.h

@ -0,0 +1,238 @@
//
// 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<NSCoding>
@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<QPlayAutoListItem*> *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 <NSCoding>
@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 <NSCoding>
@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<QPlayAutoSentence *> *sentences;
- (NSString *)sentenceAtTime:(NSTimeInterval)time;
@end
#endif /* QPlayAutoDefine_h */

188
local_plugins/qq_music/ios/qq_music/ios-sdk/QPlayAutoSDK/Headers/include/QPlayAutoSDK.h

@ -0,0 +1,188 @@
//
// QPlayAutoSDK.h
// QPlayAutoSDK
//
// Created by travisli(李鞠佑) on 2018/11/5.
// Copyright © 2018年 腾讯音乐. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "QPlayAutoDefine.h"
#define APP_DEVICE_TYPE (3)
NS_ASSUME_NONNULL_BEGIN
typedef void (^QPlayAutoResultItemsBlock)(NSInteger errorCode,NSArray<QPlayAutoListItem *> *_Nullable items);
typedef void (^QPlayAutoResultParentItemBlock)(NSInteger errorCode,QPlayAutoListItem *parentItem);
extern NSString const * QPlayAutoSDKVersion;
@protocol QPlayAutoSDKDelegate <NSObject>
//连接状态变化回调
- (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<QPlayAutoSDKDelegate>) 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<QPlayAutoListItem*> *)songList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion;
/// 通过歌曲Mid列表播放歌曲
/// @param songMidList 歌曲Mid列表
/// @param playIndex 播放索引
/// @param completion 回调
+ (void)playSongMidAtIndex:(NSArray<NSString*> *)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

BIN
local_plugins/qq_music/ios/qq_music/ios-sdk/QPlayAutoSDK/libQPlayAutoSDK.a

Binary file not shown.

1
pubspec.yaml

@ -142,5 +142,6 @@ flutter:
- assets/js/
- assets/images/headphone_new4.png
- assets/images/headphone_new3.png
- assets/images/qqmusic.png
- .env
- .mcp.json

Loading…
Cancel
Save