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.
MTMusic/lib/common/download_manager.dart

213 lines
5.8 KiB

import 'dart:convert';
import 'dart:io';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../api/api_download.dart';
import '../common_widget/Song_widegt.dart';
import 'package:path/path.dart' as path;
class DownloadItem {
final Song song;
double progress;
bool isCompleted;
bool isDownloading;
DownloadItem({
required this.song,
this.progress = 0.0,
this.isCompleted = false,
this.isDownloading = false,
});
Map<String, dynamic> toJson() {
return {
'song': {
'pic': song.pic,
'artistPic': song.artistPic,
'title': song.title,
'artist': song.artist,
'musicurl': song.musicurl,
'id': song.id,
'likes': song.likes,
'collection': song.collection
},
'progress': progress,
'isCompleted': isCompleted,
'isDownloading': isDownloading,
};
}
// 从JSON创建DownloadItem
factory DownloadItem.fromJson(Map<String, dynamic> json) {
return DownloadItem(
song: Song(
pic: json['song']['pic'],
artistPic: json['song']['artistPic'],
title: json['song']['title'],
artist: json['song']['artist'],
musicurl: json['song']['musicurl'],
id: json['song']['id'],
likes: json['song']['likes'],
collection: json['song']['collection'],
),
progress: json['progress'],
isCompleted: json['isCompleted'],
isDownloading: json['isDownloading'],
);
}
}
class DownloadManager extends GetxController {
static const String PREFS_KEY = 'downloads_data';
final _downloads = <String, DownloadItem>{}.obs;
final downloadApi = DownloadApi();
late SharedPreferences _prefs;
@override
void onInit() async {
super.onInit();
await _initPrefs();
}
Future<void> _initPrefs() async {
_prefs = await SharedPreferences.getInstance();
await _loadDownloadsFromPrefs();
}
// 从SharedPreferences加载数据
Future<void> _loadDownloadsFromPrefs() async {
final String? downloadsJson = _prefs.getString(PREFS_KEY);
if (downloadsJson != null) {
final Map<String, dynamic> downloadsMap = json.decode(downloadsJson);
downloadsMap.forEach((key, value) {
_downloads[key] = DownloadItem.fromJson(value);
});
}
}
// 保存数据到SharedPreferences
Future<void> _saveDownloadsToPrefs() async {
final Map<String, dynamic> downloadsMap = {};
_downloads.forEach((key, value) {
downloadsMap[key] = value.toJson();
});
await _prefs.setString(PREFS_KEY, json.encode(downloadsMap));
}
List<Song> getLocalSongs() {
final localSongs = <Song>[];
_downloads.forEach((key, value) {
if (value.isCompleted) {
localSongs.add(value.song);
}
});
return localSongs;
}
Map<String, DownloadItem> get downloads => _downloads;
bool isDownloading(int id) => _downloads[id.toString()]?.isDownloading ?? false;
bool isCompleted(int id) => _downloads[id.toString()]?.isCompleted ?? false;
double getProgress(int id) => _downloads[id.toString()]?.progress ?? 0.0;
Song? getLocalSong(int id) {
final downloadItem = _downloads[id.toString()];
if (downloadItem?.isCompleted ?? false) {
return downloadItem!.song;
}
return null;
}
bool removeSong(int id) {
if (_downloads[id.toString()]?.isCompleted ?? false) {
File file = File.fromUri(Uri.parse(_downloads[id.toString()]!.song.musicurl!));
file.deleteSync();
_downloads.remove(id.toString());
_saveDownloadsToPrefs();
return true;
}
return false;
}
int completedNumber() {
int count = 0;
_downloads.forEach((key, value) {
if (value.isCompleted) {
count++;
}
});
return count;
}
Future<void> startDownload({
required Song song,
required context,
}) async {
if (_downloads[song.id.toString()]?.isDownloading ?? false) return;
final fileName = '${song.id}_${song.title}_${song.artist}';
final downloadItem = DownloadItem(
song: song,
isDownloading: true,
);
_downloads[song.id.toString()] = downloadItem;
try {
final filePath = await downloadApi.downloadMusic(
musicUrl: song.musicurl!,
name: fileName,
context: context,
onProgress: (progress) {
downloadItem.progress = progress;
_downloads[song.id.toString()] = downloadItem;
},
);
if (filePath != null) {
downloadItem.isCompleted = true;
downloadItem.isDownloading = false;
downloadItem.progress = 1.0;
song.musicurl = _getLocalAudioPath(fileName, song.musicurl!);
print(song.musicurl);
} else {
downloadItem.isDownloading = false;
downloadItem.progress = 0.0;
}
} catch (e) {
print('Download error: $e');
downloadItem.isDownloading = false;
downloadItem.progress = 0.0;
}
_downloads[song.id.toString()] = downloadItem;
await _saveDownloadsToPrefs();
}
bool updateSongInfo(int id, bool isCollected, bool isLiked) {
final downloadItem = _downloads[id.toString()];
if (downloadItem != null) {
downloadItem.song.collection = isCollected;
downloadItem.song.likes = isLiked;
_downloads[id.toString()] = downloadItem;
_saveDownloadsToPrefs();
return true;
}
return false;
}
String _getFileExtension(String url) {
// Remove query parameters
final urlWithoutQuery = url.split('?').first;
// Get the extension including the dot
final extension = path.extension(urlWithoutQuery);
return extension.isNotEmpty ? extension : '.mp3'; // Default to .mp3 if no extension found
}
String _getLocalAudioPath(String fileName, String url) {
final extension = _getFileExtension(url);
final fullFileName = '$fileName$extension';
return path.join('/storage/emulated/0/MTMusic', fullFileName);
}
}