Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On android: progress and begin didn't return any progress #33

Open
daniyalrathore14 opened this issue Nov 25, 2024 · 5 comments
Open

On android: progress and begin didn't return any progress #33

daniyalrathore14 opened this issue Nov 25, 2024 · 5 comments

Comments

@daniyalrathore14
Copy link

daniyalrathore14 commented Nov 25, 2024

@kesha-antonov
In Android: im getting the issue that im unable to get the progress of download.

download({
id: jobId,
url: fileUrl,
destination: saveToPath,
metadata: {},
})
.begin(({ expectedBytes, headers }) => {
console.log(Starting download of ${expectedBytes} bytes, headers);
})
.progress(({ bytesDownloaded, bytesTotal }) => {
console.log(Download progress: ${bytesDownloaded}% ${bytesTotal});

    const progress = (bytesDownloaded / bytesTotal) * 100;
    onProgress(progress);
  })
  .done(({ bytesDownloaded, bytesTotal }) => {
    console.log(bytesDownloaded, bytesTotal, "errorCodeerrorCode");

    completeHandler(jobId);
    resolve(true);
  })
  .error(({ error, errorCode }) => {
    console.log(error, "errorCodeerrorCode");

    reject(error);
  });
@vokhuyetOz
Copy link
Contributor

it seems to be you got as same as my problem. when downloading, it got error but not send error event to JS side.

could you test this MR? #32

@daniyalrathore14
Copy link
Author

but in my case the progress and begin method is not even working once

but in my case the progress and begin method is not even working once

@kerrilija
Copy link

but in my case the progress and begin method is not even working once

I think that DownloadTaskState is stuck in 'PENDING'. For some reason the state is not updating, so the methods (.begin, .done, .progress) never reach the state needed to trigger them.

@kesha-antonov

Is this related to introduction of JSI and ditching the Asynchronous bridge?

I was experimenting, trying to log state changes in this Objective-C file - RNBackgroundDownloader.m, and it seemed like the native side is ok.

@nhanders
Copy link

nhanders commented Jan 16, 2025

The issue for me appears to be that an exception is being thrown when the onBeginCallable is called, resulting in the on begin and progress callbacks not being instantiated.

The exception is occurring when trying to estimate the file size which is to be downloaded. This is done with a HEAD request which is returning a 403, causing the exception to be raised.

Here are the logs from the captured exception in resumeTasks:

 E  resumeTasks: java.util.concurrent.ExecutionException: java.lang.Exception: java.lang.Exception: HTTP response not valid: 403
              	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
              	at java.util.concurrent.FutureTask.get(FutureTask.java:191)
              	at com.eko.RNBackgroundDownloaderModule.lambda$resumeTasks$0(RNBackgroundDownloaderModule.java:223)
              	at com.eko.RNBackgroundDownloaderModule.$r8$lambda$ANcENe0578xTT5bqy8vRgYIxWk4(Unknown Source:0)
              	at com.eko.RNBackgroundDownloaderModule$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
              	at java.lang.Thread.run(Thread.java:1012)
              Caused by: java.lang.Exception: java.lang.Exception: HTTP response not valid: 403
              	at com.eko.handlers.OnBegin.call(OnBegin.java:39)
              	at com.eko.handlers.OnBegin.call(OnBegin.java:17)
              	at java.util.concurrent.FutureTask.run(FutureTask.java:264)
              	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
              	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
              	at java.lang.Thread.run(Thread.java:1012) 
              Caused by: java.lang.Exception: HTTP response not valid: 403
              	at com.eko.handlers.OnBegin.getConnection(OnBegin.java:57)
              	at com.eko.handlers.OnBegin.call(OnBegin.java:30)
              	at com.eko.handlers.OnBegin.call(OnBegin.java:17) 
              	at java.util.concurrent.FutureTask.run(FutureTask.java:264) 
              	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
              	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644) 
              	at java.lang.Thread.run(Thread.java:1012) 

@nwilmet-vivlio
Copy link

In my case, this head request is returning a 401 because the server only respond to authorized requests (even HEAD). In the module entry file, by passing the headers from the download, resumeTasks and to the OnBegin constructor, then to the urlConnection in getConnection, it fixes the issue.

Something like

public OnBegin(RNBGDTaskConfig config, BeginCallback callback, ReadableMap headers) {
    this.config = config;
    this.callback = callback;
    this.headers = headers;
  }

  @Override
  public OnBeginState call() throws Exception {
    HttpURLConnection urlConnection = null;
    try {
      urlConnection = getConnection(config.url, headers);
      Map<String, List<String>> urlHeaders = urlConnection.getHeaderFields();
      WritableMap headers = getHeaders(urlConnection, urlHeaders);
      urlConnection.getInputStream().close();

      long bytesExpected = getContentLength(headers);
      callback.onBegin(config.id, headers, bytesExpected);
      return new OnBeginState(config.id, headers, bytesExpected);
    } catch (Exception e) {
      throw new Exception(e);
    } finally {
      if (urlConnection != null) {
        urlConnection.disconnect();
      }
    }
  }

And the getConnection method

private HttpURLConnection getConnection(String urlString, ReadableMap headers) throws Exception {
    URL url = new URL(urlString);
    HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
    // Requests only headers from the server.
    // Prevents memory leaks for invalid connections.
    urlConnection.setRequestMethod("HEAD");
    if (headers != null) {
      ReadableMapKeySetIterator iterator = headers.keySetIterator();
      while (iterator.hasNextKey()) {
        String headerKey = iterator.nextKey();
        String headerValue = headers.getString(headerKey);
        urlConnection.setRequestProperty(headerKey, headerValue);
      }
    }

    // 200 and 206 codes are successful http codes.
    int httpStatusCode = urlConnection.getResponseCode();
    if (httpStatusCode != HttpURLConnection.HTTP_OK && httpStatusCode != HttpURLConnection.HTTP_PARTIAL) {
      throw new Exception("HTTP response not valid: " + httpStatusCode);
    }

    return urlConnection;
  }

Passing the headers can be the solution (progress is fixed in my case) but there is maybe another solution to calculate the progress without a HEAD request ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants