feat: add download multi tracks support for mobile platform

This commit is contained in:
Kingkor Roy Tirtho 2022-08-14 15:44:54 +06:00
parent 9edcf537f8
commit 0476bf7cee
6 changed files with 78 additions and 35 deletions

4
.fvm/fvm_config.json Normal file
View File

@ -0,0 +1,4 @@
{
"flutterSdkVersion": "3.0.5",
"flavors": {}
}

1
.gitignore vendored
View File

@ -75,3 +75,4 @@ dist
appimage-build
android/key.properties
.fvm/flutter_sdk

View File

@ -50,7 +50,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "oss.krtirtho.spotube"
minSdkVersion flutter.minSdkVersion
minSdkVersion 19
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName

View File

@ -28,6 +28,10 @@
</activity>
<provider android:name="vn.hunghd.flutterdownloader.DownloadedFileProvider" android:authorities="${applicationId}.flutter_downloader.provider" android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" />
</provider>
<service android:name="com.ryanheise.audioservice.AudioService" android:exported="false">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />

View File

@ -2,7 +2,9 @@ import 'dart:convert';
import 'package:audio_service/audio_service.dart';
import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hive_flutter/hive_flutter.dart';
@ -26,8 +28,8 @@ void main() async {
Hive.registerAdapter(CacheTrackAdapter());
Hive.registerAdapter(CacheTrackEngagementAdapter());
Hive.registerAdapter(CacheTrackSkipSegmentAdapter());
if (kIsDesktop) {
WidgetsFlutterBinding.ensureInitialized();
if (kIsDesktop) {
doWhenWindowReady(() async {
final localStorage = await SharedPreferences.getInstance();
final rawSize = localStorage.getString(LocalStorageKeys.windowSizeInfo);
@ -44,6 +46,11 @@ void main() async {
}
appWindow.show();
});
} else {
await FlutterDownloader.initialize(
debug: kDebugMode,
ignoreSsl: true,
);
}
MobileAudioService? audioServiceHandler;
runApp(ProviderScope(
@ -102,8 +109,13 @@ class _SpotubeState extends ConsumerState<Spotube> with WidgetsBindingObserver {
super.initState();
SharedPreferences.getInstance().then(((value) => localStorage = value));
WidgetsBinding.instance.addObserver(this);
FlutterDownloader.registerCallback(downloadCallback);
}
@pragma('vm:entry-point')
static void downloadCallback(
String id, DownloadTaskStatus status, int progress) {}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);

View File

@ -2,12 +2,14 @@ import 'dart:async';
import 'dart:io';
import 'package:flutter/widgets.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:queue/queue.dart';
import 'package:path/path.dart' as path;
import 'package:spotube/models/SpotubeTrack.dart';
import 'package:spotube/provider/UserPreferences.dart';
import 'package:spotube/provider/YouTube.dart';
import 'package:spotube/utils/platform.dart';
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
Queue _queueInstance = Queue(delay: const Duration(seconds: 5));
@ -27,15 +29,30 @@ class Downloader with ChangeNotifier {
int currentlyRunning = 0;
Set<String> inQueue = {};
void addToQueue(SpotubeTrack track) {
if (inQueue.contains(track.id!)) return;
void addToQueue(SpotubeTrack track) async {
currentlyRunning++;
inQueue.add(track.id!);
notifyListeners();
final filename = '${track.ytTrack.title}.mp3';
if (kIsMobile) {
final url =
((await yt.videos.streamsClient.getManifest(track.ytTrack.url)))
.audioOnly
.where((audio) => audio.codec.mimeType == "audio/mp4")
.withHighestBitrate()
.url;
await FlutterDownloader.enqueue(
savedDir: downloadPath,
url: url.toString(),
fileName: filename,
openFileFromNotification: true,
showNotification: true,
);
} else {
if (inQueue.contains(track.id!)) return;
_queue.add(() async {
try {
final file =
File(path.join(downloadPath, '${track.ytTrack.title}.mp3'));
final file = File(path.join(downloadPath, filename));
if (file.existsSync() && await onFileExists?.call(track) != true) {
return;
}
@ -60,13 +77,18 @@ class Downloader with ChangeNotifier {
}
});
}
}
cancel() {
cancelAll() {
if (kIsMobile) {
FlutterDownloader.cancelAll();
} else {
_queue.cancel();
_queueInstance = Queue();
_queue = _queueInstance;
}
}
}
final downloaderProvider = ChangeNotifierProvider(
(ref) {