2021-09-19 12:59:45 +02:00
|
|
|
import 'dart:async';
|
|
|
|
|
|
|
|
import 'package:flutter/services.dart';
|
|
|
|
import 'package:logging/logging.dart';
|
|
|
|
import 'package:nc_photos/exception.dart';
|
|
|
|
import 'package:nc_photos/mobile/android/download.dart';
|
|
|
|
import 'package:nc_photos/mobile/android/media_store.dart';
|
|
|
|
import 'package:nc_photos/platform/file_downloader.dart' as itf;
|
|
|
|
import 'package:nc_photos/platform/k.dart' as platform_k;
|
|
|
|
|
|
|
|
class FileDownloader extends itf.FileDownloader {
|
|
|
|
@override
|
|
|
|
downloadUrl({
|
|
|
|
required String url,
|
|
|
|
Map<String, String>? headers,
|
|
|
|
String? mimeType,
|
|
|
|
required String filename,
|
2021-09-29 16:34:56 +02:00
|
|
|
String? parentDir,
|
2021-09-19 12:59:45 +02:00
|
|
|
bool? shouldNotify,
|
|
|
|
}) {
|
|
|
|
if (platform_k.isAndroid) {
|
|
|
|
return _downloadUrlAndroid(
|
|
|
|
url: url,
|
|
|
|
headers: headers,
|
|
|
|
mimeType: mimeType,
|
|
|
|
filename: filename,
|
2021-09-29 16:34:56 +02:00
|
|
|
parentDir: parentDir,
|
2021-09-19 12:59:45 +02:00
|
|
|
shouldNotify: shouldNotify,
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
throw UnimplementedError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<String> _downloadUrlAndroid({
|
|
|
|
required String url,
|
|
|
|
Map<String, String>? headers,
|
|
|
|
String? mimeType,
|
|
|
|
required String filename,
|
2021-09-29 16:34:56 +02:00
|
|
|
String? parentDir,
|
2021-09-19 12:59:45 +02:00
|
|
|
bool? shouldNotify,
|
|
|
|
}) async {
|
2021-09-29 16:34:56 +02:00
|
|
|
final String path;
|
|
|
|
if (parentDir?.isNotEmpty == true) {
|
|
|
|
path = "$parentDir/$filename";
|
|
|
|
} else {
|
|
|
|
path = filename;
|
|
|
|
}
|
|
|
|
|
2021-09-19 12:59:45 +02:00
|
|
|
try {
|
|
|
|
_log.info("[_downloadUrlAndroid] Start downloading '$url'");
|
|
|
|
final id = await Download.downloadUrl(
|
|
|
|
url: url,
|
|
|
|
headers: headers,
|
|
|
|
mimeType: mimeType,
|
2021-09-29 16:34:56 +02:00
|
|
|
filename: path,
|
2021-09-19 12:59:45 +02:00
|
|
|
shouldNotify: shouldNotify,
|
|
|
|
);
|
|
|
|
late final String uri;
|
|
|
|
final completer = Completer();
|
|
|
|
onDownloadComplete(DownloadCompleteEvent ev) {
|
|
|
|
if (ev.downloadId == id) {
|
|
|
|
_log.info(
|
|
|
|
"[_downloadUrlAndroid] Finished downloading '$url' to '${ev.uri}'");
|
|
|
|
uri = ev.uri;
|
|
|
|
completer.complete();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-28 20:43:50 +02:00
|
|
|
StreamSubscription<DownloadCompleteEvent>? subscription;
|
|
|
|
try {
|
|
|
|
subscription = DownloadEvent.listenDownloadComplete()
|
|
|
|
..onData(onDownloadComplete)
|
|
|
|
..onError((e, stackTrace) {
|
2021-09-28 21:06:46 +02:00
|
|
|
if (e is AndroidDownloadError) {
|
|
|
|
if (e.downloadId != id) {
|
|
|
|
// not us, ignore
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
completer.completeError(e.error, e.stackTrace);
|
|
|
|
} else {
|
|
|
|
completer.completeError(e, stackTrace);
|
|
|
|
}
|
2021-09-28 20:43:50 +02:00
|
|
|
});
|
|
|
|
await completer.future;
|
|
|
|
} finally {
|
|
|
|
subscription?.cancel();
|
|
|
|
}
|
2021-09-19 12:59:45 +02:00
|
|
|
return uri;
|
|
|
|
} on PlatformException catch (e) {
|
|
|
|
switch (e.code) {
|
|
|
|
case MediaStore.exceptionCodePermissionError:
|
|
|
|
throw PermissionException();
|
|
|
|
|
|
|
|
case Download.exceptionCodeDownloadError:
|
|
|
|
throw DownloadException(e.message);
|
|
|
|
|
|
|
|
case DownloadEvent.exceptionCodeUserCanceled:
|
|
|
|
throw JobCanceledException(e.message);
|
|
|
|
|
|
|
|
default:
|
|
|
|
rethrow;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static final _log = Logger("mobile.file_downloader.FileDownloader");
|
|
|
|
}
|