tonyofrancis / fetch Goto Github PK
View Code? Open in Web Editor NEWThe best file downloader library for Android
Home Page: https://www.meta.stackoverflow.com/tags/fetch2
License: Apache License 2.0
The best file downloader library for Android
Home Page: https://www.meta.stackoverflow.com/tags/fetch2
License: Apache License 2.0
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,
Hello, I want to add to a single download queue from different activities and have single listener, is it possible?
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!
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)
?
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.
INSERT INTO TABLE VALUES (A, B, C), (D, E, F)
than performing two insert statements in a transaction.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.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.
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" />
Great, thanks. I have a question:
How to display progress of number of bytes download and % of data download ?
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
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 .
Is there a way to clear the database to allow re-downloads?
Also is there a way to stop and clear all downloads in progress?
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();
}`
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,
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.
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();
}
}
});
}`
Is there a way to get Human Readable error messages?
Hello!
I am using fetch on the intent service. on the intent service I am calling startForeground method. The problem is when I close my app the download also stops. As I expect it should continue the download.
Thanks
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.
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?
Thanks
download not allowed in parallel only one download at a time.
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.
I want to have my files be private
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
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.
Can someone tell me the methodCount for this library?
Thanks
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
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
Is there any notification?
It seems that -1 is a magic const that means there is no error. If this is the case, should it be defined in FetchConst?
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.
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 ?
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.
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
......
com.tonyodev.fetch.exception.EnqueueException: DatabaseHelper already containsFilePath a request with the filePath:
Start another file after it finishes downloading one. How do I start multiple file downloads at the same time?
As title, is there a way to query/get all request saved in Fetch's database (when user turn off the app and open it next time to resume download)
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);
}
});
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.
Assume that user downloaded a file and move that file to other folder or delete it, they cannot download that file again because it save into Fetch's database. Is there a way to let user re-download?
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 😄
project links removed code snippet commented
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();
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
Hi , I Keep logging the progress amount but it will not go up to 100 but the files is already downloaded
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();
}
}
android.database.sqlite.SQLiteException: near "text": syntax error (code 1): , while compiling: INSERT INTO requests VALUES ( 5800091702000, 'http://ex.com/some'text.txt', '/storage/emulated/0/Download/id.txt', 900, '{}', 0, 0, -1, 600 )
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.