You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
311 lines
8.1 KiB
311 lines
8.1 KiB
import 'package:flutter/services.dart';
|
|
|
|
class QqMusic {
|
|
static final QqMusic _instance = QqMusic._internal();
|
|
|
|
/// 获取单例
|
|
factory QqMusic() => _instance;
|
|
|
|
// 方法通道
|
|
final MethodChannel _methodChannel = const MethodChannel(
|
|
'com.yunqiinnovation.qq_music',
|
|
);
|
|
|
|
// 内部构造函数
|
|
QqMusic._internal() {}
|
|
|
|
/// 登陆qq音乐
|
|
/// 返回登录结果,包含 openId, openToken, expireTime
|
|
Future<Map<String, dynamic>> login() async {
|
|
try {
|
|
final result = await _methodChannel.invokeMethod('login');
|
|
return Map<String, dynamic>.from(result);
|
|
} on PlatformException catch (e) {
|
|
return {'success': false, 'error': e.message ?? '登录失败', 'code': e.code};
|
|
}
|
|
}
|
|
|
|
/// 搜索歌曲
|
|
/// [keyword] 搜索关键词
|
|
/// [searchType] 搜索类型 0-歌曲 1-专辑 2-歌手
|
|
Future<Map<String, dynamic>> searchSongs({
|
|
required String keyword,
|
|
int searchType = 7, // Data.SearchType.SEARCH_TYPE_SONG
|
|
}) async {
|
|
try {
|
|
final result = await _methodChannel.invokeMethod('searchSongs', {
|
|
'keyword': keyword,
|
|
'searchType': searchType,
|
|
});
|
|
return Map<String, dynamic>.from(result);
|
|
} on PlatformException catch (e) {
|
|
return {'success': false, 'error': e.message ?? '搜索失败', 'code': e.code};
|
|
}
|
|
}
|
|
|
|
/// 播放歌曲列表
|
|
/// [songMids] 歌曲MID列表
|
|
/// [index] 开始播放的索引,默认为0
|
|
Future<Map<String, dynamic>> playSongs({
|
|
required List<String> songMids,
|
|
int index = 0,
|
|
}) async {
|
|
try {
|
|
final result = await _methodChannel.invokeMethod('playSongs', {
|
|
'songMids': songMids,
|
|
'index': index,
|
|
});
|
|
return Map<String, dynamic>.from(result);
|
|
} on PlatformException catch (e) {
|
|
return {'success': false, 'error': e.message ?? '播放失败', 'code': e.code};
|
|
}
|
|
}
|
|
|
|
/// 播放音乐
|
|
Future<Map<String, dynamic>> playMusic() async {
|
|
try {
|
|
final result = await _methodChannel.invokeMethod('playMusic');
|
|
return Map<String, dynamic>.from(result);
|
|
} on PlatformException catch (e) {
|
|
return {'success': false, 'error': e.message ?? '播放失败', 'code': e.code};
|
|
}
|
|
}
|
|
|
|
/// 暂停音乐
|
|
Future<Map<String, dynamic>> pauseMusic() async {
|
|
try {
|
|
final result = await _methodChannel.invokeMethod('pauseMusic');
|
|
return Map<String, dynamic>.from(result);
|
|
} on PlatformException catch (e) {
|
|
return {'success': false, 'error': e.message ?? '暂停失败', 'code': e.code};
|
|
}
|
|
}
|
|
|
|
/// 自动暂停音乐
|
|
Future<Map<String, dynamic>> autopauseMusic() async {
|
|
try {
|
|
final result = await _methodChannel.invokeMethod('autopauseMusic');
|
|
return Map<String, dynamic>.from(result);
|
|
} on PlatformException catch (e) {
|
|
return {'success': false, 'error': e.message ?? '自动暂停失败', 'code': e.code};
|
|
}
|
|
}
|
|
|
|
/// 恢复播放
|
|
Future<Map<String, dynamic>> resumeMusic() async {
|
|
try {
|
|
final result = await _methodChannel.invokeMethod('resumeMusic');
|
|
return Map<String, dynamic>.from(result);
|
|
} on PlatformException catch (e) {
|
|
return {'success': false, 'error': e.message ?? '恢复播放失败', 'code': e.code};
|
|
}
|
|
}
|
|
|
|
/// 停止音乐
|
|
Future<Map<String, dynamic>> stopMusic() async {
|
|
try {
|
|
final result = await _methodChannel.invokeMethod('stopMusic');
|
|
return Map<String, dynamic>.from(result);
|
|
} on PlatformException catch (e) {
|
|
return {'success': false, 'error': e.message ?? '停止失败', 'code': e.code};
|
|
}
|
|
}
|
|
|
|
/// 下一首
|
|
Future<Map<String, dynamic>> skipToNext() async {
|
|
try {
|
|
final result = await _methodChannel.invokeMethod('skipToNext');
|
|
return Map<String, dynamic>.from(result);
|
|
} on PlatformException catch (e) {
|
|
return {
|
|
'success': false,
|
|
'error': e.message ?? '切换下一首失败',
|
|
'code': e.code,
|
|
};
|
|
}
|
|
}
|
|
|
|
/// 上一首
|
|
Future<Map<String, dynamic>> skipToPrevious() async {
|
|
try {
|
|
final result = await _methodChannel.invokeMethod('skipToPrevious');
|
|
return Map<String, dynamic>.from(result);
|
|
} on PlatformException catch (e) {
|
|
return {
|
|
'success': false,
|
|
'error': e.message ?? '切换上一首失败',
|
|
'code': e.code,
|
|
};
|
|
}
|
|
}
|
|
|
|
/// 获取播放状态
|
|
Future<Map<String, dynamic>> getPlaybackState() async {
|
|
try {
|
|
final result = await _methodChannel.invokeMethod('getPlaybackState');
|
|
return Map<String, dynamic>.from(result);
|
|
} on PlatformException catch (e) {
|
|
return {
|
|
'success': false,
|
|
'error': e.message ?? '获取播放状态失败',
|
|
'code': e.code,
|
|
};
|
|
}
|
|
}
|
|
|
|
/// 获取当前播放歌曲
|
|
Future<Map<String, dynamic>> getCurrentSong() async {
|
|
try {
|
|
final result = await _methodChannel.invokeMethod('getCurrentSong');
|
|
return Map<String, dynamic>.from(result);
|
|
} on PlatformException catch (e) {
|
|
return {
|
|
'success': false,
|
|
'error': e.message ?? '获取当前歌曲失败',
|
|
'code': e.code,
|
|
};
|
|
}
|
|
}
|
|
|
|
/// 获取播放时长
|
|
Future<Map<String, dynamic>> getPlayTime() async {
|
|
try {
|
|
final result = await _methodChannel.invokeMethod('getPlayTime');
|
|
return Map<String, dynamic>.from(result);
|
|
} on PlatformException catch (e) {
|
|
return {
|
|
'success': false,
|
|
'error': e.message ?? '获取播放时长失败',
|
|
'code': e.code,
|
|
};
|
|
}
|
|
}
|
|
|
|
/// 同步当前播放信息
|
|
Future<Map<String, dynamic>> syncCurrentPlayInfo() async {
|
|
try {
|
|
final result = await _methodChannel.invokeMethod('syncCurrentPlayInfo');
|
|
return Map<String, dynamic>.from(result);
|
|
} catch (e) {
|
|
throw Exception('同步播放信息失败: $e');
|
|
}
|
|
}
|
|
|
|
/// 获取平台版本
|
|
Future<String?> getPlatformVersion() async {
|
|
try {
|
|
final version = await _methodChannel.invokeMethod<String>(
|
|
'getPlatformVersion',
|
|
);
|
|
return version;
|
|
} on PlatformException catch (e) {
|
|
throw Exception('获取平台版本失败: ${e.message}');
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 登录结果类
|
|
class QQMusicLoginResult {
|
|
final bool success;
|
|
final String? openId;
|
|
final String? openToken;
|
|
final String? expireTime;
|
|
final String? error;
|
|
final String? code;
|
|
|
|
QQMusicLoginResult({
|
|
required this.success,
|
|
this.openId,
|
|
this.openToken,
|
|
this.expireTime,
|
|
this.error,
|
|
this.code,
|
|
});
|
|
|
|
factory QQMusicLoginResult.fromMap(Map<String, dynamic> map) {
|
|
return QQMusicLoginResult(
|
|
success: map['success'] ?? false,
|
|
openId: map['openId'],
|
|
openToken: map['openToken'],
|
|
expireTime: map['expireTime'],
|
|
error: map['error'],
|
|
code: map['code'],
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 搜索结果类
|
|
class QQMusicSearchResult {
|
|
final bool success;
|
|
final List<QQMusicSong>? songs;
|
|
final String? error;
|
|
final String? code;
|
|
|
|
QQMusicSearchResult({
|
|
required this.success,
|
|
this.songs,
|
|
this.error,
|
|
this.code,
|
|
});
|
|
|
|
factory QQMusicSearchResult.fromMap(Map<String, dynamic> map) {
|
|
List<QQMusicSong>? songs;
|
|
if (map['songs'] != null) {
|
|
songs = (map['songs'] as List)
|
|
.map((song) => QQMusicSong.fromMap(Map<String, dynamic>.from(song)))
|
|
.toList();
|
|
}
|
|
|
|
return QQMusicSearchResult(
|
|
success: map['success'] ?? false,
|
|
songs: songs,
|
|
error: map['error'],
|
|
code: map['code'],
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 歌曲信息类
|
|
class QQMusicSong {
|
|
final String? mid;
|
|
final String? id;
|
|
final String? name;
|
|
final String? singer;
|
|
final String? album;
|
|
final int? duration;
|
|
final String? pic;
|
|
|
|
QQMusicSong({
|
|
this.mid,
|
|
this.id,
|
|
this.name,
|
|
this.singer,
|
|
this.album,
|
|
this.duration,
|
|
this.pic,
|
|
});
|
|
|
|
factory QQMusicSong.fromMap(Map<String, dynamic> map) {
|
|
return QQMusicSong(
|
|
mid: map['mid'],
|
|
id: map['id'],
|
|
name: map['name'],
|
|
singer: map['singer'],
|
|
album: map['album'],
|
|
duration: map['duration'],
|
|
pic: map['pic'],
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toMap() {
|
|
return {
|
|
'mid': mid,
|
|
'id': id,
|
|
'name': name,
|
|
'singer': singer,
|
|
'album': album,
|
|
'duration': duration,
|
|
'pic': pic,
|
|
};
|
|
}
|
|
}
|
|
|