Giter Club home page Giter Club logo

fetch's Introduction

Build Status Download Android Arsenal License

ScreenShot

Overview

Fetch is a simple, powerful, customizable file download manager library for Android.

ScreenShot

Features

  • Simple and easy to use API.
  • Continuous downloading in the background.
  • Concurrent downloading support.
  • Ability to pause and resume downloads.
  • Set the priority of a download.
  • Network-specific downloading support.
  • Ability to retry failed downloads.
  • Ability to group downloads.
  • Easy progress and status tracking.
  • Download remaining time reporting (ETA).
  • Download speed reporting.
  • Save and Retrieve download information anytime.
  • Notification Support.
  • Storage Access Framework, Content Provider and URI support.
  • And more...

Prerequisites

If you are saving downloads outside of your application's sandbox, you will need to add the following storage permissions to your application's manifest. For Android SDK version 23(M) and above, you will also need to explicitly request these permissions from the user.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

Also, as you are going to use Internet to download files. We need to add the Internet access permissions in the Manifest.

<uses-permission android:name="android.permission.INTERNET"/>

How to use Fetch

Using Fetch is easy! Just add the Gradle dependency to your application's build.gradle file.

implementation "com.tonyodev.fetch2:fetch2:3.0.12"

Androidx use:

implementation "androidx.tonyodev.fetch2:xfetch2:3.1.6"

Next, get an instance of Fetch and request a download.

public class TestActivity extends AppCompatActivity {

    private Fetch fetch;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

 FetchConfiguration fetchConfiguration = new FetchConfiguration.Builder(this)
                .setDownloadConcurrentLimit(3)
                .build();

        fetch = Fetch.Impl.getInstance(fetchConfiguration);

        String url = "http:www.example.com/test.txt";
        String file = "/downloads/test.txt";
        
        final Request request = new Request(url, file);
        request.setPriority(Priority.HIGH);
        request.setNetworkType(NetworkType.ALL);
        request.addHeader("clientKey", "SD78DF93_3947&MVNGHE1WONG");
        
        fetch.enqueue(request, updatedRequest -> {
            //Request was successfully enqueued for download.
        }, error -> {
            //An error occurred enqueuing the request.
        });

    }
}

Tracking a download's progress and status is very easy with Fetch. Simply add a FetchListener to your Fetch instance, and the listener will be notified whenever a download's status or progress changes.

FetchListener fetchListener = new FetchListener() {
    @Override
    public void onQueued(@NotNull Download download, boolean waitingOnNetwork) {
        if (request.getId() == download.getId()) {
            showDownloadInList(download);
        }
    }

    @Override
    public void onCompleted(@NotNull Download download) {

    }

    @Override
    public void onError(@NotNull Download download) {
        Error error = download.getError();
    }

    @Override
    public void onProgress(@NotNull Download download, long etaInMilliSeconds, long downloadedBytesPerSecond) {
        if (request.getId() == download.getId()) {
            updateDownload(download, etaInMilliSeconds);
        }
        int progress = download.getProgress();
    }

    @Override
    public void onPaused(@NotNull Download download) {

    }

    @Override
    public void onResumed(@NotNull Download download) {

    }

    @Override
    public void onCancelled(@NotNull Download download) {

    }

    @Override
    public void onRemoved(@NotNull Download download) {

    }

    @Override
    public void onDeleted(@NotNull Download download) {

    }
};

fetch.addListener(fetchListener);

//Remove listener when done.
fetch.removeListener(fetchListener);

Fetch supports pausing and resuming downloads using the request's id. A request's id is a unique identifier that maps a request to a Fetch Download. A download returned by Fetch will have have an id that matches the request id that started the download.

Request request1 = new Request(url, file);
Request request2 = new Request(url2, file2);

fetch.pause(request1.getId());

...

fetch.resume(request2.getId());

You can query Fetch for download information in several ways.

//Query all downloads
fetch.getDownloads(new Func<List<? extends Download>>() {
    @Override
        public void call(List<? extends Download> downloads) {
            //Access all downloads here
        }
});

//Get all downloads with a status
fetch.getDownloadsWithStatus(Status.DOWNLOADING, new Func<List<? extends Download>>() {
    @Override
        public void call(List<? extends Download> downloads) {
            //Access downloads that are downloading
        }
});

// You can also access grouped downloads
int groupId = 52687447745;
fetch.getDownloadsInGroup(groupId, new Func<List<? extends Download>>() {
    @Override
      public void call(List<? extends Download> downloads) {
              //Access grouped downloads
      }
});

When you are done with an instance of Fetch, simply release it.

//do work

fetch.close();

//do more work

Downloaders

By default Fetch uses the HttpUrlConnection client via the HttpUrlConnectionDownloader to download requests. Add the following Gradle dependency to your application's build.gradle to use the OkHttp Downloader instead. You can create your custom downloaders if necessary. See the Java docs for details.

implementation "com.tonyodev.fetch2okhttp:fetch2okhttp:3.0.12"

Androidx use:

implementation "androidx.tonyodev.fetch2okhttp:xfetch2okhttp:3.1.6"

Set the OkHttp Downloader for Fetch to use.

OkHttpClient okHttpClient = new OkHttpClient.Builder().build();

FetchConfiguration fetchConfiguration = new FetchConfiguration.Builder(this)
    .setDownloadConcurrentLimit(10)
    .setHttpDownloader(new OkHttpDownloader(okHttpClient))
    .build();

Fetch fetch = Fetch.Impl.getInstance(fetchConfiguration);

RxFetch

If you would like to take advantage of RxJava2 features when using Fetch, add the following gradle dependency to your application's build.gradle file.

implementation "com.tonyodev.fetch2rx:fetch2rx:3.0.12"

Androidx use:

implementation "androidx.tonyodev.fetch2rx:xfetch2rx:3.1.6"

RxFetch makes it super easy to enqueue download requests and query downloads using rxJava2 functional methods.

FetchConfiguration fetchConfiguration = new FetchConfiguration.Builder(this).build();
Rxfetch rxFetch = RxFetch.Impl.getInstance(fetchConfiguration);

rxFetch.getDownloads()
        .asFlowable()
        .subscribe(new Consumer<List<Download>>() {
            @Override
            public void accept(List<Download> downloads) throws Exception {
                //Access results
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                //An error occurred
                final Error error = FetchErrorUtils.getErrorFromThrowable(throwable);
            }
        });

FetchFileServer

Introducing the FetchFileServer. The FetchFileServer is a lightweight TCP File Server that acts like an HTTP file server designed specifically to share files between Android devices. You can host file resources with the FetchFileServer on one device and have to Fetch download Files from the server on another device. See the sample app for more information. Wiki on FetchFileServer will be added in the coming days.

Start using FetchFileServer by adding the gradle dependency to your application's build.gradle file.

implementation "com.tonyodev.fetch2fileserver:fetch2fileserver:3.0.12"

Androidx use:

implementation "androidx.tonyodev.fetch2fileserver:xfetch2fileserver:3.1.6"

Start a FetchFileServer instance and add resource files that it can serve to connected clients.

public class TestActivity extends AppCompatActivity {

    FetchFileServer fetchFileServer;
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        fetchFileServer = new FetchFileServer.Builder(this)
                .build();
        
        fetchFileServer.start(); //listen for client connections

        File file = new File("/downloads/testfile.txt");
        FileResource fileResource = new FileResource();
        fileResource.setFile(file.getAbsolutePath());
        fileResource.setLength(file.length());
        fileResource.setName("testfile.txt");
        fileResource.setId(UUID.randomUUID().hashCode());
        
        fetchFileServer.addFileResource(fileResource);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        fetchFileServer.shutDown(false);
    }
}

Downloading a file from a FetchFileServer using the Fetch is easy.

public class TestActivity extends AppCompatActivity {

    Fetch fetch;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FetchConfiguration fetchConfiguration = new FetchConfiguration.Builder(this)
                .setFileServerDownloader(new FetchFileServerDownloader()) //have to set the file server downloader
                .build();
        fetch = Fetch.Impl.getInstance(fetchConfiguration);
        fetch.addListener(fetchListener);

        String file = "/downloads/sample.txt";
        String url = new FetchFileServerUrlBuilder()
                .setHostInetAddress("127.0.0.1", 6886) //file server ip and port
                .setFileResourceIdentifier("testfile.txt") //file resource name or id
                .create();
        Request request = new Request(url, file);
        fetch.enqueue(request, request1 -> {
            //Request enqueued for download
        }, error -> {
            //Error while enqueuing download
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        fetch.addListener(fetchListener);
    }

    @Override
    protected void onPause() {
        super.onPause();
        fetch.removeListener(fetchListener);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        fetch.close();
    }

    private FetchListener fetchListener = new AbstractFetchListener() {
        @Override
        public void onProgress(@NotNull Download download, long etaInMilliSeconds, long downloadedBytesPerSecond) {
            super.onProgress(download, etaInMilliSeconds, downloadedBytesPerSecond);
            Log.d("TestActivity", "Progress: " + download.getProgress());
        }

        @Override
        public void onError(@NotNull Download download) {
            super.onError(download);
            Log.d("TestActivity", "Error: " + download.getError().toString());
        }

        @Override
        public void onCompleted(@NotNull Download download) {
            super.onCompleted(download);
            Log.d("TestActivity", "Completed ");
        }
    };
}

Fetch1 Migration

Migrate downloads from Fetch1 to Fetch2 using the migration assistant. Add the following gradle dependency to your application's build.gradle file.

implementation "com.tonyodev.fetchmigrator:fetchmigrator:3.0.12"

Androidx use:

implementation "androidx.tonyodev.fetchmigrator:xfetchmigrator:3.1.6"

Then run the Migrator.

        if (!didMigrationRun()) {
            //Migration has to run on a background thread
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        final List<DownloadTransferPair> transferredDownloads = FetchMigrator.migrateFromV1toV2(getApplicationContext(), APP_FETCH_NAMESPACE);
                        //TODO: update external references of ids
                        for (DownloadTransferPair transferredDownload : transferredDownloads) {
                            Log.d("newDownload", transferredDownload.getNewDownload().toString());
                            Log.d("oldId in Fetch v1", transferredDownload.getOldID() + "");
                        }
                        FetchMigrator.deleteFetchV1Database(getApplicationContext());
                        setMigrationDidRun(true);
                        //Setup and Run Fetch2 after the migration
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        } else {
            //Setup and Run Fetch2  normally
        }

Contribute

Fetch can only get better if you make code contributions. Found a bug? Report it. Have a feature idea you'd love to see in Fetch? Contribute to the project!

License

Copyright (C) 2017 Tonyo Francis.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

fetch's People

Contributors

alexstarc avatar alvince avatar befora avatar dougkeen avatar ioltean avatar marcin-adamczewski avatar mikedawson avatar nitishgadangi avatar stustirling avatar thib-rdr avatar tonyofrancis 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  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

fetch's Issues

Configuration Problem

The build.gradle is configured and during rebuild gives the following errors:

/Users/shoaibrafa/AndroidStudioProjects/AppSaraaiV3/app/build/intermediates/res/merged/debug/values-v24/values-v24.xml
Error:(3) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Borderless.Colored'.
Error:(4) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Colored'.
Error:(3) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Borderless.Colored'.
Error:(4) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Colored'.
Error:Execution failed for task ':app:processDebugResources'.

com.android.ide.common.process.ProcessException: Failed to execute aapt

multi-task downloads

Start another file after it finishes downloading one. How do I start multiple file downloads at the same time?

Concurrent download limit problems

If you try to set the download limit to something that is above FetchConst.MAX_DOWNLOADS_LIMIT, the method silently sets the value to the default value, which is 1.

This is problematic partially because MAX_DOWNLOADS_LIMIT isn't public, so you're relying on the developer to use second hand knowledge to not call that method with a value greater than 7.

Why is there a hard coded limit to how many files can be downloaded concurrently? Is the number 7 chosen arbitrarily or based on some data? I would much prefer if you laid out a recommendation for the maximum number of downloads in the documentation but allow the developer to use whatever number they choose.

How to check if file already exists ?

Hey Tony !
You're very helpful so far,I want to check if the downloading file already exists or not ? Is there any method ? If exists do share with me .

Wrong progress when downloading big files (Tested with 4.2 GB file)

httpURLConnection.getContentLenght() is not working correct when the file is bigger than the Integer.MAX_VALUE. In this case it will return -1 and I guess that's why the progress you return will always be 0%.

An option to fix this issue would be to get the content length directly from the headers and convert it to long:

Long.valueOf(connection.getHeaderField("Content-Length"))

instead of:

private void setContentLength() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
fileSize = downloadedBytes + httpURLConnection.getContentLengthLong();
} else {
fileSize = downloadedBytes + httpURLConnection.getContentLength();
}
}

Get the List of all queued requests

Hi @tonyofrancis
This is one of the awesome library I have seen so far, very easy to user, very light weight and well documented.
I just have one question, how do I get the list of queued requests ?

Thanks for your help 😄

Need a "get" method that accepts several download IDs

It appears that Fetch is lacking a method that allows you to query for a list of download IDs. Would you be opposed to adding a method that looks like this:

public synchronized List<RequestInfo> get(long... ids)?

getProgress() and getDownloadedBytes() issues

Scenario 2:
The file is being downloaded.
https://archive.org/download/Mozart_347/05.mp3

D/fetchDebug: id:165363055600,status:901,progress:5,error:-1
I/fetchDebug: id: 165363055600 downloadedBytes: 1875132 / fileSize: 17487404
D/fetchDebug: id:165363055600,status:901,progress:6,error:-1
I/fetchDebug: id: 165363055600 downloadedBytes: 2207640 / fileSize: 17487404
D/fetchDebug: id:165363055600,status:901,progress:7,error:-1
I/fetchDebug: id: 165363055600 downloadedBytes: 2585160 / fileSize: 17487404

.......

Then I pause the download, progress and downloadedBytes values are set to 0.

D/fetchDebug: id:165363055600,status:902,progress:0, error:-1
I/fetchDebug: id: 165363055600 downloadedBytes: 0 / fileSize: 17487404

When I pause, I want to show the last updated values in the download.

update issue

I'm trying to download a video from a URL:
http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_2mb.mp4

progres and fileSize not updating while downloading a file.

D/fetchDebug: id:237955074420,status:901,progress:0,error:-1
I/fetchDebug: id: 237955074420 downloadedBytes: 444171 / fileSize: -1
D/fetchDebug: id:237955074420,status:901,progress:0,error:-1
I/fetchDebug: id: 237955074420 downloadedBytes: 744735 / fileSize: -1
D/fetchDebug: id:237955074420,status:901,progress:0,error:-1
I/fetchDebug: id: 237955074420 downloadedBytes: 1087407 / fileSize: -1
D/fetchDebug: id:237955074420,status:901,progress:0,error:-1
I/fetchDebug: id: 237955074420 downloadedBytes: 1637715 / fileSize: -1
......

`FetchConst` should probably be public

When you query the status of a download, you get a RequestInfo object that has a status value which is an integer that corresponds to the status codes in FetchConst. However, since FetchConst is not public, there is no way to to perform logic on the status unless the client app hard codes those values.

Not able to download redirected url in android version 4.4(Kitkat)

It is not downloading form redirected links, as I am using Vimeo video for download, As the first links which Vimeo provides is an "https url" and later it changes to "http url" . Here I am proving a vimeo link from which am trying to download a video,

https://player.vimeo.com/play/720138981?s=210197530_1494265285_b46e1ab154e0464a03760f8805892af8&loc=external&context=Vimeo%5CController%5CApi%5CResources%5CUser%5CVideoController.&download=1&filename=Untitledsource.mp4

You can use the link to download the file in browser and it is downloading fine. And if you check the downloading url, it is an http url.

So, what I have to do to download, this kind of files.

Scalability issues with a large amount of downloads

There are several issues I've encountered while trying to see if this library would scale for a large amount of downloads. I've tried enqueueing 500+ downloads at once and there are a few major issues. Doing this takes several seconds and causes noticeable lag in the UI.

  1. Even in a transaction, executing multiple queries is much more expensive than executing a single query. When inserting multiple rows, for example, it is much more efficient to do something like INSERT INTO TABLE VALUES (A, B, C), (D, E, F) than performing two insert statements in a transaction.
  2. containsFilePath is executed for each inserted row and it executes a query of its own. If the file path column was set to be UNIQUE you could catch SQLiteConstraintException and handle duplicate inserts much more efficiently.
  3. Cursors aren't closed correctly in some cases. Whenever you have cursor.close() in a try block, the cursor isnt closed if an exception happens. cursor.close() should always be in a finally block.

I've made a bunch of changes locally to remedy this situation but at this point the codebase has changed so much it would be difficult to port them back. I'm willing to do it, however, if you'd like help with these things.

fetch view is reducing it size with weight.

What I see is, When I use weight for height of fetch view. it is reducing its size,I will try to explain with the help of an example.
Please do visit this link .

As I have used the main views as "Linear layout" with "weight_sum=2", and two views one is video_view and the other is textview. I am using weight for making both views of equal height. but when I run the application, video_view(your fetch view) is reducing its size. For knowing it better I have set background color to green and textview color to blue.

Here is the below code what I have used in xml.

<fm.jiecao.jcvideoplayer_lib.JCVideoPlayerStandard
    android:id="@+id/MyVideoPlayer"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:keepScreenOn="true" />

<TextView
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:background="#4fa0ab"
    android:gravity="center"
    android:text="TextView Area" />

`getInstance` method name is a misnomer

The getInstance method with a context parameter implies there is a single instance of Fetch per context. If you support multiple instances per context (which you do), you may want to consider renaming the method to newInstance. See item 1 in Effective Java for the naming conventions for static factory methods.

Progress and filesize issues

Scenario:
The file is being downloaded:

D/ fetchDebug: id:30547713379280,status:901,progress:25,error:-1
I/ fetchDebug: id: 30547713379280 downloadedBytes: 7428602 / fileSize: 29189424

Then I pause the download and close the application.
Progress and filesize are calculated incorrectly when I reopen the application and resume it.

D/ fetchDebug: id:30547713379280,status:901,progress:100,error:-1
I/ fetchDebug: id: 30547713379280 downloadedBytes: 22283153 / fileSize: 13935572

Cofiguratin problem

The build.gradle is configured and during rebuild gives the following errors:

/Users/shoaibrafa/AndroidStudioProjects/MyApp/app/build/intermediates/res/merged/debug/values-v24/values-v24.xml
Error:(3) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Borderless.Colored'.
Error:(4) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Colored'.
Error:(3) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Borderless.Colored'.
Error:(4) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Colored'.
Error:Execution failed for task ':app:processDebugResources'.

com.android.ide.common.process.ProcessException: Failed to execute aapt

Design for supporting multiple downloads

Hi @tonyofrancis ,

I wanted help in designing the feature to support multiple downloads in my application.
How do I go about updating progress for each download in same notification ?

I have been thinking of showing something like 1 of 4 in progress in the notification and then when 1 completes update the notification as 2 of 4 in progress.

Any idea on this of what should be the efficient design for this feature and have good user experience ?

Progress

Great, thanks. I have a question:
How to display progress of number of bytes download and % of data download ?

Progress

Hi , I Keep logging the progress amount but it will not go up to 100 but the files is already downloaded

How to re download file?

Hi,

Nice fetcher by the way I have an error:
com.tonyodev.fetch.exception.EnqueueException: DatabaseHelper already containsFilePath a request with the filePath:

How can I re download file using this fetcher? thanks

DownloadId

My downloadId = -1 what is the reason please help me asap .

Fetch fetch = Fetch.getInstance(MainActivity.this);
Request request = new Request("http://androhub.com/demo/demo.mp4", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();

final long downloadId = fetch.enqueue(request);

fetch.addFetchListener(new FetchListener() {
            @Override
            public void onUpdate(long id, int status, int progress, int error) {
                if(downloadId== id){
                    progressDialog.setProgress(progress);
                    Log.d("TAG",String.valueOf(progress));
                    if(progress>=100){
                        progressDialog.dismiss();
                    }
                }

            }
});

//Log.d("TAG",fetch.getFilePath(downloadId).toString());
fetch.release();

FetchService is running always in backgound?

i have noticed that after calling fetch.release(); method on fetch instance the FetchService is not stop it is running forever even if not downloading anything. did i need to do anything else to stop this service.

Possibility to change the download URL when it expires

Hello, i would like to use this library into my project, but i have one problem.
I have download URL with expiration time, and when user pause download, expiration time is over, and user want to resume download, fetcher give me STATUS_ERROR, that is fine.
My ask is: is there any possibility to change download URL to continue download file with different download link?
Because for now i can't continue download, i need to remove request and starts again, losing proviously dowloaded part of the file.

How does Fetch notifty the app about file already present

Hi @tonyofrancis ,

I want that my app should be notified by fetch if the requested file already exists.
I tried in the listener to get it notified, but couldn't.

I used Fetch.ERROR_ENQUEUE_ERROR and Fetch.ERROR_FILE_ALREADY_CREATED but couldn't get any response from fetch.

Any idea ?

Thanks,

Exception download exception

com.tonyodev.fetch.exception.DownloadInterruptedException: DIE
at com.tonyodev.fetch.FetchRunnable.run(FetchRunnable.java:128)
at java.lang.Thread.run(Thread.java:856)

In sample when i am start single download getting this exception.

onupdate never called

i just simple implemented this lib as u suggested but on update never be called you can see below code ... and if u might wud say to fetch.release().. so i t also didn't work

`public void fetchMethod(String url, String fileName) {
        Toast.makeText(DownloadService.this, "downloading started", Toast.LENGTH_SHORT).show();
        File file = new File(Environment.getExternalStorageDirectory(), File.separator + getString(R.string.app_name));
        if (!file.exists()) {
            file.mkdirs();
        }
        new Fetch.Settings(getApplicationContext())
                .setAllowedNetwork(Fetch.NETWORK_ALL)
                .enableLogging(true)
                .setConcurrentDownloadsLimit(3)
                .apply();
        Fetch fetch = Fetch.getInstance(this);
        Log.e("check", file.getAbsolutePath() + " " + fileName);
        Request request = new Request(url, file.getAbsolutePath(), File.separator + fileName);
        final long downloadId = fetch.enqueue(request);
        fetch.addFetchListener(new FetchListener() {

            @Override
            public void onUpdate(long id, int status, int progress, long downloadedBytes, long fileSize, int error) {

                if (downloadId == id && status == Fetch.STATUS_DOWNLOADING) {
                    Toast.makeText(DownloadService.this, "downloading   " + progress, Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(DownloadService.this, "no file" + progress, Toast.LENGTH_SHORT).show();
                }
            }
        });
    }`

error in verbose

com.tonyodev.fetch.exception.EnqueueException: DatabaseHelper already containsFilePath a request with the filePath:

How to remove task, but remain file downloaded

I count number of files currently downloading and if 1 of them is done, i call fetch.get().size() to update count. But that size remains the same and fetch.remove(id) deletes downloaded file eather. Something like removeTask(id) possible?

On devices lower than Android 6.0

Hello,

Marshmallow does not download on low-end devices

Status = 905 in log output

`public class SingleDownloadActivity extends AppCompatActivity implements FetchListener {

private static final int STORAGE_PERMISSION_CODE = 100;

private View rootView;
private TextView progressTextView;
private TextView titleTextView;

private long downloadId = -1;
private Fetch fetch;
private  String url,path,fname;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_single_download);

    rootView = findViewById(R.id.activity_single_download);
    progressTextView = (TextView) findViewById(R.id.progressTextView);
    titleTextView = (TextView) findViewById(R.id.titleTextView);


    Bundle extras = getIntent().getExtras();
    url = extras.getString("url");
    path = extras.getString("path");
    fname = extras.getString("name");
    fetch = Fetch.getInstance(this);
    clearAllDownloads();
}

@Override
protected void onResume() {
    super.onResume();

    if(downloadId != -1) {

        RequestInfo info = fetch.get(downloadId);

        if (info != null) {
            setProgressView(info.getStatus(),info.getProgress());
        }

        fetch.addFetchListener(this);
    }
}

@Override
protected void onPause() {
    super.onPause();
    fetch.removeFetchListener(this);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    fetch.release();
}

/*Removes all downloads managed by Fetch*/
private void clearAllDownloads() {

    fetch.removeAll();
    createRequest();
}

private void createRequest() {

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
    {

        requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}
                ,STORAGE_PERMISSION_CODE);
    }else
    {
        enqueueDownload();
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    if(requestCode == STORAGE_PERMISSION_CODE || grantResults.length > 0
            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

        enqueueDownload();

    }else {
        Snackbar.make(rootView,R.string.permission_not_enabled,Snackbar.LENGTH_LONG).show();
    }
}

private void enqueueDownload() {

    Request request = new Request(url,path,fname);

    downloadId = fetch.enqueue(request);

    setTitleView(request.getFilePath());
    setProgressView(Fetch.STATUS_QUEUED,0);
}

@Override
public void onUpdate(long id, int status, int progress, long downloadedBytes, long fileSize, int error) {

    if(id == downloadId) {

        if(status == Fetch.STATUS_ERROR) {

            showDownloadErrorSnackBar(error);

        }else {

            setProgressView(status,progress);
        }
    }
}

private void setTitleView(String fileName) {

    Uri uri = Uri.parse(fileName);
    titleTextView.setText("yükleniyor");
}

private void setProgressView(int status,int progress) {


    switch (status) {

        case Fetch.STATUS_QUEUED : {
            progressTextView.setText(R.string.queued);
            break;
        }
        case Fetch.STATUS_DOWNLOADING :
        case Fetch.STATUS_DONE : {

            if(progress == -1) {

                progressTextView.setText(R.string.downloading);
            }else {

                String progressString = getResources()
                        .getString(R.string.percent_progress,progress);

                progressTextView.setText(progressString);
            }
            finish();
            break;
        }
        default: {
            Log.d("SingleDownloadActivity",status + "asd");
            progressTextView.setText(R.string.status_unknown);
            break;
        }
    }
}

private void showDownloadErrorSnackBar(int error) {

    final Snackbar snackbar = Snackbar.make(rootView,"Download Failed: ErrorCode: "
            + error,Snackbar.LENGTH_INDEFINITE);

    snackbar.setAction(R.string.retry, new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            fetch.retry(downloadId);
            snackbar.dismiss();
        }
    });

    snackbar.show();
}`

How can I download a file that has already been downloaded?

For example, the user downloaded a file and then deleted it from the sdcard. In the future, he wants to download the file again, but Fetch throws the exception:
EnqueueException: DatabaseHelper already containsFilePath a request with the filePath: [...]

Is there a way to force the download?

Thanks for lib!

When kill App. Downloading stop.

Hi,

I have download long file it is download but when app kill in background download stoped. and it is not a store in database.

Thanks

Onupdate() method is not calling in fetch.addListner

Fetch fetch = Fetch.getInstance(MainActivity.this);
String dateString = new Date().toString();
       
Request request = new Request("http://androhub.com/demo/demo.mp4",Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString()+"/"+dateString+"_demo.mp4");
        
final long downloadId = fetch.enqueue(request);
        
fetch.addFetchListener(new FetchListener() {
            @Override
            public void onUpdate(long id, int status, int progress, int error) {

               //This log is not visible in android monitor 
               
               Log.d("fetchDebug","id:" + id + ",status:" + status + ",download percentage:" + progress
                        + ",error:" + error);
            }
 });

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.