Giter Site home page Giter Site logo

781flyingdutchman / background_downloader Goto Github PK

View Code? Open in Web Editor NEW
143.0 143.0 68.0 7.21 MB

Flutter plugin for file downloads and uploads

License: Other

Kotlin 24.09% Ruby 0.45% Swift 17.40% Objective-C 0.08% Dart 53.77% CMake 1.85% C++ 2.23% C 0.14%

background_downloader's People

Contributors

781flyingdutchman avatar aulig avatar kslr avatar rebaz94 avatar slaci avatar snipd-mikel avatar wreppun avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

background_downloader's Issues

moveToSharedStorage does fail on iOS

First of all, thanks for the nice new plugin which i happily replaced the outdated flutter_downloader with!

An issue came up:

final task = DownloadTask(url: finalUrl, filename: fileName);
var downloadResult = await FileDownloader().download(task);
if (downloadResult == TaskStatus.complete) {
      final newFilePath = await FileDownloader().moveToSharedStorage(task, SharedStorage.downloads);
      if (newFilePath == null) {
        ERROR Msg
      } else {
        FileService().openFile(newFilePath);
      }
    }

Moving the file to the shared storage works fine on Android and my iOS simulator, but fails on some customer iPhones, returning null.
Feels like some permission issue..
Any idea what I could be missing? Thanks!

ad:
Or is there an option to open a file (e.g. pdf) direct after download from the app's document folder? I guess, i have to move it to the shared storage to allow an associated pdf viewer app to open it..

Download progress as notification

I still want to have the download progress on Android and iOS. On Windows you could also use the taskbar.

That should be optional of cause but for my usecase I would need it. I know that here kicks in localization problems, but I guess that would be not the frist plugin which runs into that issue.

NullPointerException when calling FileDownloader().allTasks()

First off, many thanks for this library @781flyingdutchman , I am really loving it so far! It's very convenient to use, much simpler than flutter_downloader ever was!

I get the following NullPointerException from time to time when calling await FileDownloader().allTasks() in my taskStatusCallback method of the FileDownloader().registerCallbacks() method. It seems to stem from the "native_downloader.dart" file in the library (see screenshot).

nullerror

Am I doing something wrong by calling allTasks() in the callback? Or is there a small bug in the library itself?

The full error message is this:

java.lang.NullPointerException: null cannot be cast to non-null type kotlin.String
	at com.bbflight.background_downloader.BackgroundDownloaderPlugin.methodAllTasks(BackgroundDownloaderPlugin.kt:380)
	at com.bbflight.background_downloader.BackgroundDownloaderPlugin.access$methodAllTasks(BackgroundDownloaderPlugin.kt:51)
	at com.bbflight.background_downloader.BackgroundDownloaderPlugin$onMethodCall$1.invokeSuspend(BackgroundDownloaderPlugin.kt:291)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:284)
	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
	at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source:1)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
	at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source:1)
	at com.bbflight.background_downloader.BackgroundDownloaderPlugin.onMethodCall(BackgroundDownloaderPlugin.kt:287)
	at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:258)
	at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295)
	at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:322)
	at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12)
	at android.os.Handler.handleCallback(Handler.java:958)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:205)
	at android.os.Looper.loop(Looper.java:294)
	at android.app.ActivityThread.main(ActivityThread.java:8128)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:578)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:946)

This leads me to a feature suggestion:
Basically what I am using allTasks() for is to find out if any downloads are still in progress and change the UI accordingly. It's not that hard to do, I just check if the returned List is empty or not, but I would appreciate a "isDownloadInProgress" call, or something along the lines.

Not Getting latest version in my project. flutter_test depends on collection 1.16.0.

Because every version of flutter_test from sdk depends on collection 1.16.0 and background_downloader >=5.0.0 depends on collection ^1.17.0, flutter_test from sdk is incompatible with background_downloader >=5.0.0.
So, because vectortiles_to_rastertiles depends on both background_downloader ^5.2.0 and flutter_test from sdk, version solving failed.
pub get failed (1; So, because vectortiles_to_rastertiles depends on both background_downloader ^5.2.0 and flutter_test from sdk, version solving failed.)
exit code 1

How i change or increase flutter_test dependency.

Receiving updates question

Hello,

I've tried to listen to the updates stream, but as it is a normal stream, I can listen it to only once. I mean, if I called listen() once and after cancelled the subscribtion, then I can't call listen again on it, cause dart throws bad state error (streams can be only listened once). The use case is this: there is a screen where I start to listen to the stream, then navigate away, then back and I receive the error, because it was listened to on the first navigation. If the updates stream was a broadcast stream, that would solve this problem, but then it would lose the buffering feature (by default) which I don't know how important here. (Edit: Just to make sure: I don't want/trying to listen to the stream multiple times at once).

The second option is registerCallbacks() which would be a good alternative (I prefer stream though), but how do I unregister them? Only destroy clears them in base_downloader.dart as far as I see 🤔 I would like to unregister them when I navigate away.

Edit2: Maybe calling destroy would be the proper way when navigating away? As I see now it recreates the stream controller. Will try it later.

Fatal error: Unexpectedly found nil while unwrapping an Optional value | iOS

Hi I revisited my application after a while (last used version 1.6.0) and I encountered an error which I did not recognise happened ever before. Somehow it's crashing the app on both package versions.

The code used to download the content:

    await FileDownloader().download(DownloadTask(
      url: contentUrl,
      filename: fileName,
      baseDirectory: BaseDirectory.applicationDocuments,
      directory: 'courses/${course.courseId}/${step.stepId}',
    ));

Migrated from await FileDownloader.download(BackgroundDownloadTask).
The error that appears in the console:

[Downloader] Starting task with id 158596712
[Downloader] Starting task with id 635268047
[Downloader] Fnished task with id 158596712
[Downloader] Starting task with id 1908250544
2
background_downloader/Downloader.swift:124: Fatal error: Unexpectedly found nil while unwrapping an Optional value
* thread #1, queue = 'com.apple.main-thread', stop reason = Fatal error: Unexpectedly found nil while unwrapping an Optional value
    frame #0: 0x00000001c3dad0f8 libswiftCore.dylib`_swift_runtime_on_report
libswiftCore.dylib`:
->  0x1c3dad0f8 <+0>: ret
libswiftCore.dylib`:
    0x1c3dad0fc <+0>: b      0x1c3dad0f8               ; _swift_runtime_on_report
libswiftCore.dylib`:
    0x1c3dad100 <+0>: adrp   x8, 365860
    0x1c3dad104 <+4>: ldrb   w0, [x8, #0xabc]
Target 0: (Runner) stopped.
Lost connection to device.

This was taken from launch on physical device, but simulator is crashing as well. I've tried this in both release and debug same results. I'm willing to continue providing more detailed information about content and app via pm, can't do it directly here from obvious reasons.

File can't be downloaded on android but works well on ios

import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:prime_layer_flutter/utils/common.dart';
import 'package:sn_progress_dialog/sn_progress_dialog.dart';
import 'package:background_downloader/background_downloader.dart';
import 'package:flutter_gen/gen_l10n/century_localizations.dart';

InAppWebViewSettings options = InAppWebViewSettings(
  mediaPlaybackRequiresUserGesture: false,
  // disallowOverScroll: true,
  alwaysBounceHorizontal: false,
  alwaysBounceVertical: false,
  useOnLoadResource: true,
  // clearCache: true,
);

class Browser extends StatefulWidget {
  const Browser(this.url, this.title, {super.key});

  final String url;
  final String title;

  @override
  BrowserState createState() => BrowserState();
}

class BrowserState extends State<Browser> {
  final GlobalKey webViewKey = GlobalKey();
  bool _isLoading = true;
  double? _htmlHeight;
  ProgressDialog? pd;

  double downloadProgress = 0;

  String currentTaskId = '';

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    InAppWebViewController webViewController;
    final localizations = AppLocalizations.of(context)!;
    // pd = ProgressDialog(context: context);
    return SafeArea(
      child: Stack(
        children: [
          SizedBox(
            height: MediaQuery.of(context).size.height,
            child: InAppWebView(
              // gestureRecognizers: gestureRecognizers,
              onDownloadStartRequest: (controller, downloadStartRequest) async {
                final task = DownloadTask(
                    url: downloadStartRequest.url.toString(),
                    filename: downloadStartRequest
                            .url.queryParameters['fullFileName'] ??
                        '附件'); // define your task

                pd ??= ProgressDialog(context: context);

                pd!.show(
                  max: 100,
                  msg: localizations.downloadStatusRunning,
                  progressType: ProgressType.valuable,
                  progressBgColor: Colors.transparent,
                  hideValue: true,
                  closeWithDelay: 1000,
                  cancel: Cancel(
                    cancelClicked: () {
                      FileDownloader().cancelTaskWithId(task.taskId);
                    },
                  ),
                  completed: Completed(
                      completedMsg: localizations.downloadStatusComplete),
                  // onStatusChanged:
                );

                FileDownloader().download(
                  task,
                  onProgress: (progress) {
                    // setState(() {
                    //   downloadProgress = progress;
                    // });
                    print('---Progress update: $progress');

                    pd!.update(
                      value: progress.toInt(),
                    );

                    if (progress == 1) {
                      pd!.close();
                      FileDownloader().openFile(task: task);
                    }
                  },
                  onStatus: (status) => print('Status update: $status'),
                );
              },
              // onLoadResource: (controller, resource) {
              // },
              key: webViewKey,
              initialUrlRequest: URLRequest(url: WebUri(widget.url)),
              initialSettings: options,
              onWebViewCreated: (InAppWebViewController controller) {
                setState(() {
                  _isLoading = true;
                });
                webViewController = controller;
                webViewController.addJavaScriptHandler(
                  handlerName: 'goback',
                  callback: (args) {
                    Navigator.of(context).pop();
                  },
                );

                webViewController.addJavaScriptHandler(
                  handlerName: 'backToWorkBench',
                  callback: (args) {
                    Navigator.of(context).pop();
                  },
                );
                webViewController.addJavaScriptHandler(
                  handlerName: 'getToken',
                  callback: (_) async {
                    return await CommonUtils().getToken();
                  },
                );
              },
              onLoadStop: (InAppWebViewController controller, _) async {
                int contentHeight = (await controller.getContentHeight())!;
                double zoomScale = (await controller.getZoomScale())!;
                double? htmlHeight = contentHeight.toDouble() * zoomScale;
                double htmlHeightFixed =
                    double.parse(htmlHeight.toStringAsFixed(2));
                if (htmlHeightFixed == 0.0) {
                  return;
                }
                setState(() {
                  _htmlHeight = htmlHeightFixed + 0.1;
                  _isLoading = false;
                });
              },
            ),
          ),
          Offstage(
            offstage: !_isLoading,
            child: Container(
              width: MediaQuery.of(context).size.width,
              height: MediaQuery.of(context).size.height,
              color: Colors.white,
              child: const Center(
                child: CircularProgressIndicator(
                  strokeWidth: 2,
                ),
              ),
            ),
          )
        ],
      ),
    );
  }
}

class ItemHolder {
  ItemHolder({this.name, this.task});

  final String? name;
  final TaskInfo? task;
}

class TaskInfo {
  TaskInfo({this.name, this.link});

  final String? name;
  final String? link;

  String? taskId;
  int? progress = 0;
}

downloadStatusCallback not being called on android

Hey

thanks for the awesome plugin!

Everything works flawlessly on ios. On android on the other hand the downloadStatusCallback or downloadProgressCallback is not being called after at all. The native logs appear in the logcat indicating a successful download.

During my small debugging, everything seemed to work on the native side, but in the flutter the _backgroundChannel MethodCallHandler never gets called.

Thanks in advance

Execution failed for task ':app:checkLaunchDebugDuplicateClasses'.

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ':app:checkLaunchDebugDuplicateClasses'.

A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable
Duplicate class kotlin.collections.jdk8.CollectionsJDK8Kt found in modules jetified-kotlin-stdlib-1.8.0 (org.jetbrains.kotlin:kotlin-stdlib:1.8.0) and jetified-kotlin-stdlib-jdk8-1.7.20 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20)
Duplicate class kotlin.internal.jdk8.JDK8PlatformImplementations found in modules jetified-kotlin-stdlib-1.8.0 (org.jetbrains.kotlin:kotlin-stdlib:1.8.0) and jetified-kotlin-stdlib-jdk8-1.7.20 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20)
Duplicate class kotlin.internal.jdk8.JDK8PlatformImplementations$ReflectSdkVersion found in modules jetified-kotlin-stdlib-1.8.0 (org.jetbrains.kotlin:kotlin-stdlib:1.8.0) and jetified-kotlin-stdlib-jdk8-1.7.20 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20)
Duplicate class kotlin.jvm.jdk8.JvmRepeatableKt found in modules jetified-kotlin-stdlib-1.8.0 (org.jetbrains.kotlin:kotlin-stdlib:1.8.0) and jetified-kotlin-stdlib-jdk8-1.7.20 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20)
Duplicate class kotlin.jvm.optionals.OptionalsKt found in modules jetified-kotlin-stdlib-1.8.0 (org.jetbrains.kotlin:kotlin-stdlib:1.8.0) and jetified-kotlin-stdlib-jdk8-1.7.20 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20)
Duplicate class kotlin.random.jdk8.PlatformThreadLocalRandom found in modules jetified-kotlin-stdlib-1.8.0 (org.jetbrains.kotlin:kotlin-stdlib:1.8.0) and jetified-kotlin-stdlib-jdk8-1.7.20 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20)
Duplicate class kotlin.streams.jdk8.StreamsKt found in modules jetified-kotlin-stdlib-1.8.0 (org.jetbrains.kotlin:kotlin-stdlib:1.8.0) and jetified-kotlin-stdlib-jdk8-1.7.20 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20)
Duplicate class kotlin.streams.jdk8.StreamsKt$asSequence$$inlined$Sequence$1 found in modules jetified-kotlin-stdlib-1.8.0 (org.jetbrains.kotlin:kotlin-stdlib:1.8.0) and jetified-kotlin-stdlib-jdk8-1.7.20 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20)
Duplicate class kotlin.streams.jdk8.StreamsKt$asSequence$$inlined$Sequence$2 found in modules jetified-kotlin-stdlib-1.8.0 (org.jetbrains.kotlin:kotlin-stdlib:1.8.0) and jetified-kotlin-stdlib-jdk8-1.7.20 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20)
Duplicate class kotlin.streams.jdk8.StreamsKt$asSequence$$inlined$Sequence$3 found in modules jetified-kotlin-stdlib-1.8.0 (org.jetbrains.kotlin:kotlin-stdlib:1.8.0) and jetified-kotlin-stdlib-jdk8-1.7.20 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20)
Duplicate class kotlin.streams.jdk8.StreamsKt$asSequence$$inlined$Sequence$4 found in modules jetified-kotlin-stdlib-1.8.0 (org.jetbrains.kotlin:kotlin-stdlib:1.8.0) and jetified-kotlin-stdlib-jdk8-1.7.20 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20)
Duplicate class kotlin.text.jdk8.RegexExtensionsJDK8Kt found in modules jetified-kotlin-stdlib-1.8.0 (org.jetbrains.kotlin:kotlin-stdlib:1.8.0) and jetified-kotlin-stdlib-jdk8-1.7.20 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20)
Duplicate class kotlin.time.jdk8.DurationConversionsJDK8Kt found in modules jetified-kotlin-stdlib-1.8.0 (org.jetbrains.kotlin:kotlin-stdlib:1.8.0) and jetified-kotlin-stdlib-jdk8-1.7.20 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20)
Go to the documentation to learn how to Fix dependency resolution errors.

  • Try:

Run with --stacktrace option to get the stack trace.
Run with --info or --debug option to get more log output.
Run with --scan to get full insights.

BUILD FAILED in 1m 13s
Exception: Gradle task assembleLaunchDebug failed with exit code 1
Exited (sigterm)

Feedback

I'm trying to understand how you build your library. I noticed that you are using httpConnection.contentLengthLong in DownloadWorker:260, this requires API level 24, but you can replace it with this one liner:

val contentLength = httpConnection.getHeaderField("content-length").toLongOrNull() ?: -1

You should also limit your response code handling to 200 to download the file. A 206 for "Partial Content" is currently not supported by your code.

Disable notifications

Hi,

I'm using await FileDownloader().downloadBatch(...) and I couldn't find a way to disable notification (for a specific batch download or in general).
Is it possible? I'm on background_downloader: ^5.4.5

Thanks :)

Resume does not resume onStatus and onProgress callbacks

Hello,
I have tried out your package and it seems to be very superior to the flutter_downloader, so thank you!

But when playing with pause/resume I'm struggling a bit. I cannot resume a DownloadTask which has allowPause: true and FileDownloader().taskCanResume(task) also says its resumable. Well, it is resumed, just the original onStatus and onProgress callbacks are not triggered anymore. Is it intended? As I see I cannot reatach callbacks when resuming.

I tried this only on android (10 on a real device, 12-13 in emulator).

Steps:

  • Create a new flutter project flutter create projname. I'm using 3.7.12 (most recent stable).
  • Replace lib/main.dart's content by this gist: https://gist.github.com/slaci/ec1bae0a6648a84848f5d16e477eb540
  • Bump minSdkVersion to 24 in android/app/build.gradle
  • Bump ext.kotlin_version to 1.8.20 in android/build.gradle (stable flutter uses only 1.7)
  • Need to find a big enought PDF file online which is accessible through https and resumable (sorry cannot provide one, working with a private one) and put the link into the code. DownloadBtn(fileUrl: 'https://...').
  • Press download, then pause it with the pause icon (it works). Then try to resume with the play icon. The icon will animate to pause, because resume returns true, but status and progress won't update anymore. Download will eventually complete as you can see in the logs and the file will be there.

Downloads don't complete at all when I trigger lots of downloads (about 120) at the same time

I am using this library to download small video files (120 videos in total, size ranging between 19-50 MBs). I want users to be able to download them individually or, if they choose to do so, all at once.

Whenever I try to download all videos at once on my test device on Android, all tasks do get enqueued, but they never start downloading or finish, not even one of them. Also, the tasks that are enqueued aren't cancelled unless I trigger a cancel via a button.

If I trigger a download of a smaller number of files, say 20, they do all get downloaded completely.

I created a very similar app about 2 years ago with the flutter_downloader package with no issues, so I doubt that this is an operating system issue (the app still works today on my phone).

Can you help me out? Is this something this library isn't intended to do, am I doing something wrong or is there a bug?

Add Widget to show download progress

There is an example in the example app, but it may be helpful to add a widget to the package itself that developers can use to show download progress in a standardized way, as it's a common use case. Should not rely on Provider or similar package (as the example does) to reduce dependency conflict risk.

MicroSD card support on Android

In the case of background download, there are many downloads of large files.

Many Android users often expand their capacity with a microSD card.

I want to set the download path to the micro sd card path, but there is no such method in the current plug-in.

You can think of moving files after downloading by implementing them separately, but since MircroSD Card is a separate physical storage device, the cost is higher than moving files internally.

https://pub.dev/packages/sdcard_path_manager

can pause/resume/delete the task ?

I would like to pause a running task and then continue downloading, or delete a task completely, Can this plugin be implemented? thank you

Final classes vs mocking

Hello,

When writing tests which uses Filedownloader I always want to use mocks instead of the real class, as I don't want to download anything. But now on 7.0+ you marked many classes with final and mockito cannot generate mocks from them anymore sadly:

Error: The class 'FileDownloader' can't be implemented outside of its library because it's a final class.
class MockFileDownloader extends _i1.Mock implements _i14.FileDownloader

Are you sure those finals are really required?

Build runner complaining for these currently:

  • Database
  • TaskStatusUpdate
  • Batch

I created an issue for mockito about this: dart-lang/mockito#635

Multiple callback for a single group?

Perhaps I need to adjust my implementation.

I have multiple widgets which I wish to observe download status/progress.

One such example is comparing the task.taskId and updating the widget state:

@override
void initState() {
  super.initState();

  FileDownloader.registerCallbacks(downloadStatusCallback: (task, status) {
    if (task.taskId == _taskId) {
      setState(() {
        _downloadStatus = status;
      });
    }
  }, downloadProgressCallback: (task, progress) {
    if (task.taskId == _taskId) {
      setState(() {
        _progress = progress;
      });
    }
  });
}

Ability to use FileDownloader on a child isolate

Hi, I tried using the package on a child isolate and got an error because platform channels cannot be used on child isolates. After doing some research I came across this article Background Isolate channels so it seems with Flutter 3.7 it is possible to use platform channel methods on other isolates and tried doing the same thing as in the sample code.

void _isolateMain(RootIsolateToken rootIsolateToken) async {
  BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken);

  FileDownloader();
}

but received an error at runtime.

[VERBOSE-2:dart_isolate.cc(1098)] Unhandled exception:
UI actions are only available on root isolate.
#0      FfiTrampoline____nativeSetNeedsReportTimings$Method$FfiNative$Ptr (dart:ffi)
#1      PlatformDispatcher.__nativeSetNeedsReportTimings (dart:ui/platform_dispatcher.dart:524:24)
#2      PlatformDispatcher._nativeSetNeedsReportTimings (dart:ui/platform_dispatcher.dart:521:52)
#3      PlatformDispatcher.onReportTimings= (dart:ui/platform_dispatcher.dart:513:29)
#4      SchedulerBinding.addTimingsCallback
binding.dart:308
#5      SchedulerBinding.initInstances
binding.dart:240
#6      ServicesBinding.initInstances
binding.dart:37
#7      PaintingBinding.initInstances
binding.dart:20
#8      SemanticsBinding.initInstances
binding.dart:18
#9      RendererBinding.initInstances
binding.dart:30
#10 <…>

maybe I'm missing something ?

How do resume download fill when I restart the app.

hello:
Now. The background_downloader resume download file when call resume method.

The file not download completed when user exit the app. so I need continue download when start the app.
What should I do?

Notification not showing in IOS

I'm using this package to download mp3 files. In iphone 12 (iOS version 16.5) everything is working perfect. But no notification is showing when I'm testing in iphone X (iOs version: 16.5) and iphone 7 (iOS version: 15.7). But task is downloading in directory. Foloowing is the code.

final task = bd.DownloadTask(
url: url,
filename: '$name.mp3',
); // define your task
bd.FileDownloader().configureNotification(
running: bd.TaskNotification('Downloading', 'file: "$name.mp3"'),
progressBar: true,
tapOpensFile: true,
complete: bd.TaskNotification('Download Complete', 'file: $name.mp3'),
error: bd.TaskNotification('Download Failed', 'file: $name.mp3'),
);
final result = await bd.FileDownloader()
.download(task);
print(result.status);

Ignore SSL

Hello dear!
I want to download file from a server but before start downloading, show an exception for me...

Chain validation failed javax.net.ssl.SSLHandshakeException: Chain validation failed Chain

my SSL is expired but i don't want to occur any error for users.
How can I activate "SSL Ignore"?

Thanks.

Redirects are not being followed but throw an error instead

According to the documentation, redirects should be followed by the downloader, but when I try to download a file from a URL which redirects to a S3 bucket address, I get the following exception:

I/TaskWorker( 8604): Response code 302 for download from  <url>
I/TaskWorker( 8604): Could not read response content from httpResponseCode 302: java.lang.NullPointerException: connection.errorStream must not be null

Using version 6.1.2 on Android with flutter 3.7.3 and Dart 2.

Scoped storage support on Android

I am planning to add this support to my 2.0 fork, but why not also in your plugin. I'm just thinking if we could combine our resources. I wrote such code already in the past and for Android 14 I need to maintain it anyway.

I still need to evaluate your interface to understand better how you do it and what would be the best way to integrate that.

HTTP headers

It would be helpful to add HTTP headers to BackgroundDownloadTask since some URLs may require the Authorization header (or others) in order to download them.

Add Uint8List upload support

I'd like to use this package in my project as a replacement for dio.put().
Currently I have to pass a filename to upload(), but it would be nice to add a way to pass a Uint8List directly instead.

Windows: reports canceled after app restart

I am experiencing a problem in my implementation of the background_downloader.

My setup:
I have implemented my own queue database with queued files for download. Once an item is added to the queue, a worker (that subscribes to queue changes) will initiate a download (if no other downloads are active).
The same worker will on initialisation start a download (if no other downloads are active).

A queue item will have an ID, and this id is used as taskId for the background_downloader download task.

My problem
Below is the steps used to produce the issue:

  1. Start a download with taskId = x (not literarily x, but for the sake of simplicity x is used here)
  2. Close the app
  3. Restart the app
  4. Start new (the same url) download with taskId = x (same id as in step 1)

In the debug console, the following information is printed:
2 flutter: TaskStatus.enqueued 2 flutter: TaskStatus.running flutter: FileDownloader>FINE: 2023-04-04 15:18:51.204115: Could not delete temp file C:\Users\FLUTTE~1\AppData\Local\Temp\com.bbflight.background_downloader3078630720 flutter: TaskStatus.canceled

The downloader reports that the task is cancelled, and does not emit running status even though the download progress is clearly working. Finally it emits complete status when the download is complete and the file is successfully downloaded.

Is this a bug, or is the problem that I am not using a unique id for every download?
And do you have an idea why Windows is not able to delete the temp file?

Add to documentation

After adding background_downloader and trying to run the app I got

> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable
   > Duplicate class androidx.lifecycle.ViewModelLazy found in modules jetified-lifecycle-viewmodel-ktx-2.3.1-runtime (androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1) and lifecycle-viewmodel-2.5.0-runtime (androidx.lifecycle:lifecycle-viewmodel:2.5.0)
     Duplicate class androidx.lifecycle.ViewTreeViewModelKt found in modules jetified-lifecycle-viewmodel-ktx-2.3.1-runtime (androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1) and lifecycle-viewmodel-2.5.0-runtime (androidx.lifecycle:lifecycle-viewmodel:2.5.0)

     Go to the documentation to learn how to <a href="d.android.com/r/tools/classpath-sync-errors">Fix dependency resolution errors</a>.

There was probably a conflict with some other dependency I was using. So, I followed the suggestion from https://stackoverflow.com/a/69832319 and added following code inside dependencies{...} in build.gradle (app level) file

def lifecycle_version = "2.4.0"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"

I was thinking it would be cool to add this info in Readme.md of this package (maybe between Initial setup section and Limitations section). It could save a lot of time and hassle for others like me.

Clarification docs: Max 8 minutes on Android

Shoutout to the author for an amazing plugin and great documentation!
Just one thing that I think is unclear in the documentation:

On Android, once started (i.e. TaskStatus.running), a task must complete within 8 minutes

Does this mean that a download MUST complete within 8 minutes on Android, regardless of whether the app is in the foreground or the background?

We are developing an app where the user must be able to download video files for offline use (as many of our customers do not have regular access to WiFi). These video files can easily be 800-1000 MB. Does this mean that their internet speed must be minimum 16,67 Mbps to theoretically complete a 1GB download on Android?

1000MB / 8 min / 60 sek = 2,08 MB/s Internet speed: 2,08 * 8 bits = 16,67 Mbps

CocoaPod issue

I am giving a try to this package from inside FlutterInAppWebView package,

When I add the package to my pub_spec.yaml, I cant run my project anymore.
When I remove the package, my app is running properly.

Any idea please?

 LoadError - dlopen(/Library/Ruby/Gems/2.6.0/gems/ffi-1.15.4/lib/ffi_c.bundle, 0x0009): tried: '/Library/Ruby/Gems/2.6.0/gems/ffi-1.15.4/lib/ffi_c.bundle' (mach-o file, but is an incompatible architecture (have (x86_64), need (arm64e))) - /Library/Ruby/Gems/2.6.0/gems/ffi-1.15.4/lib/ffi_c.bundle

Incorrect MIME type when moving files to shared storage

Hi,

I've noticed that sometimes the getMimeType function in Android returns an incorrect MIME type, which can cause issues when trying to insert media files into a specified destination. I've modified the code to correctly get the MIME type from the file name, and added an optional mimeType parameter that can be set when moving files to ensure that the correct mime type is used even if not determined easily.

Allow form data to be attached to each task when uploading

I have a use case, where I need to be able to add form data to the multipart/form-data upload request.

We have a lot of images that will be uploaded and each has associated data that needs to be sent with it.

It would be great if the UploadTask object could have a Map<String, String> property for adding this.

Cancelling failing tasks

On desktop, cancelling a task that will fail (eg invalid url) right after it is enqueued and before the download isolate has been created will not cancel the task, as it never gets to transferBytes, where cancellation is tested

Whether timeoutIntervalForResource parameters can be exposed to developers, used for custom timeout?

I am downloading a 10M file, but the file server may be far away from the user. For example, the file server is in China, but the user may be in England. Users are waiting for the file download is complete, if timeoutIntervalForResource is very large, the user may have been waiting for the download page. At this time, we may set the timeout time to 60 seconds. After 60 seconds, if the file server does not respond, it indicates that the request time out is requested. We need to inform the user that the network is abnormal and need to re-download. I think timeoutIntervalForResource this parameter should be exposed to developers, by a business to determine how much the value should be

Query all Completed Download

Hi thanks for this awesome alternative package.🙏
I am thinking to switch from flutter downloader, as this package meets all of my requirements.

I have a question though which bits confuses me. Our app is complete offline app after file downloads and mostly used images and audio and very less video file.

In the app we have the list of task to be downloaded and hence it's exact length. I just want to Query if all the task has been downloaded (don't need progress for individual task) , but check for all file download completes.

So that later I can test the list of original download task and the completed Task have <= length of original list.l, that confirm that although some task failed but 90% of task are completed and I want to route to another page.

Thank-you and hope to get your response

Support Library directory on iOS

It would be a valuable addition to include support for the Library directory, which is typically used to store persistent files on iOS.

defining new enum libraryDirectory

...
case BaseDirectory.libraryDirectory:
        baseDir = await getLibraryDirectory();
        break;

Allow uploads to specify HTTP method

The plugin defaults to using a POST. My backend requires these uploads to be a PUT, though.

So it would be nice to be able to switch these over. The post field on the UploadTask is used to differentiate between binary and multi-part uploads. On the DownloadTask the field is used to trigger a POST instead of a GET and contains the post body data.

Maybe this could be cleaned up a bit?

downloaded filename for Android issue

On Android, the filename is always the same downloadfile followed by its suffix.
As for iOS, the filename is correctly deducted from the \filestream sent from the server.

[iOS] Notifications permission is requested on enqueue even if I don't use notifications config

On iOS when I call enqueue notification permission is requested regardless the config. The problem is in Downloader.swift#94 the notificiationConfigJsonString variable holds "null" for me, then it is checked againts nil after, so I get into the permission requesting if.

The origin of the problem is in native_downloader.dart because that arg is json encoded even if its null, so that's why the null is passed as string. Real dart null is converted to NsNull on Swift side correctly.

On android its not noticable because not much happens based on the config. Shouldn't permission be requested from Android 13 though? 🤔

Created a PR for it.

Is there a way to not await completion of a batch?

Basically, similar to how I can enqueue a single task and handle progress and status updates centrally via the listeners, can I do the same with a batch?

My use case requires me to track the single files individually anyway. But enqueuing them as a batch would make this a bit easier.

Specify direct path for upload, instead of using BaseDirectory

Currently, files have to be copied to a local directory (BaseDirectory) for uploading, which seems very inefficient for uploading large files. Being able to specify a direct path for uploading seems essential, especially for desktop apps. It would be nice to be able to specify the path directly in the directory parameter by setting BaseDirectory to none. (or any better way than this, if possible)

The current way works well for downloads, but seems very inefficient for uploads.

A version upgrade of the http package is required.

The Http package is now updated to the 1.0.0 stable version.

Because background_downloader 7.1.0 depends on http ^0.13.0 and no versions of background_downloader match >7.1.0 <8.0.0, background_downloader ^7.1.0 requires http ^0.13.0.
So, because filecast_mobile_flutter depends on both http ^1.0.0 and background_downloader ^7.1.0, version solving failed.

Where are the downloaded files?

I supposed that the downloaded files would be present in the Files app and downloads folder for iOS but this it not the case. How can I downloaded them in that folder please?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.