{"id":14979929,"url":"https://github.com/tonyofrancis/fetch","last_synced_at":"2025-05-13T19:03:05.481Z","repository":{"id":37663825,"uuid":"80573984","full_name":"tonyofrancis/Fetch","owner":"tonyofrancis","description":"The best file downloader library for Android","archived":false,"fork":false,"pushed_at":"2024-12-03T12:51:00.000Z","size":3449,"stargazers_count":1729,"open_issues_count":115,"forks_count":350,"subscribers_count":36,"default_branch":"v3.0x","last_synced_at":"2025-04-28T00:14:29.938Z","etag":null,"topics":["android","android-development","android-library","android-tv","app","application","downloader","downloadmanager","fast-networking","filedownloader","filemanager","gradle","http","httpurlconnection","internet","internet-of-things","mobile","networking","okhttp","retrofit"],"latest_commit_sha":null,"homepage":"https://www.meta.stackoverflow.com/tags/fetch2","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tonyofrancis.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-01-31T23:45:43.000Z","updated_at":"2025-04-26T09:50:31.000Z","dependencies_parsed_at":"2022-07-14T04:00:30.765Z","dependency_job_id":"0f1833e0-96e3-4fdd-9cc9-d7351868d180","html_url":"https://github.com/tonyofrancis/Fetch","commit_stats":{"total_commits":841,"total_committers":20,"mean_commits":42.05,"dds":"0.33055885850178357","last_synced_commit":"141e77f3035d3ed4d44799c796d361c7b6628494"},"previous_names":[],"tags_count":93,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tonyofrancis%2FFetch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tonyofrancis%2FFetch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tonyofrancis%2FFetch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tonyofrancis%2FFetch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tonyofrancis","download_url":"https://codeload.github.com/tonyofrancis/Fetch/tar.gz/refs/heads/v3.0x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254010793,"owners_count":21998993,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","android-development","android-library","android-tv","app","application","downloader","downloadmanager","fast-networking","filedownloader","filemanager","gradle","http","httpurlconnection","internet","internet-of-things","mobile","networking","okhttp","retrofit"],"created_at":"2024-09-24T14:00:56.804Z","updated_at":"2025-05-13T19:03:05.435Z","avatar_url":"https://github.com/tonyofrancis.png","language":"Kotlin","readme":"[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Android%20Networking-blue.svg?style=flat)](https://android-arsenal.com/details/1/5196)\n[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/tonyofrancis/Fetch/blob/master/LICENSE)\n\n![ScreenShot](https://github.com/tonyofrancis/Fetch/blob/v2/full_logo.png)\n\nOverview\n--------\n\nFetch is a simple, powerful, customizable file download manager library for Android.\n\n![ScreenShot](https://github.com/tonyofrancis/Fetch/blob/v2/screenshot.png)\n\nFeatures\n--------\n\n* Simple and easy to use API.\n* Continuous downloading in the background.\n* Concurrent downloading support.\n* Ability to pause and resume downloads.\n* Set the priority of a download.\n* Network-specific downloading support.\n* Ability to retry failed downloads.\n* Ability to group downloads.\n* Easy progress and status tracking.\n* Download remaining time reporting (ETA).\n* Download speed reporting.\n* Save and Retrieve download information anytime.\n* Notification Support.\n* Storage Access Framework, Content Provider and URI support.\n* And more...\n\nPrerequisites\n-------------\n\nIf you are saving downloads outside of your application's sandbox, you will need to\nadd the following storage permissions to your application's manifest. For Android SDK version\n23(M) and above, you will also need to explicitly request these permissions from the user.\n\n```xml\n\u003cuses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/\u003e\n\u003cuses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/\u003e\n```\nAlso, as you are going to use Internet to download files. We need to add the Internet access permissions\nin the Manifest.\n\n```xml\n\u003cuses-permission android:name=\"android.permission.INTERNET\"/\u003e\n```\n\nHow to use Fetch\n----------------\n\nUsing Fetch is easy! Just add the following to your project's `build.gradle` file. In newer Android\nStudio projects add this to `settings.gradle`\n```groovy\nallprojects {\n    repositories {\n        maven { url 'https://jitpack.io' }\n    }\n}\n```\n\nAdd the Gradle dependency to your application's build.gradle file.\n```groovy\nimplementation \"com.github.tonyofrancis.Fetch:fetch2:3.4.1\"\n```\n\nNext, get an instance of Fetch and request a download.\n\n```java\npublic class TestActivity extends AppCompatActivity {\n\n    private Fetch fetch;\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\n FetchConfiguration fetchConfiguration = new FetchConfiguration.Builder(this)\n                .setDownloadConcurrentLimit(3)\n                .build();\n\n        fetch = Fetch.Impl.getInstance(fetchConfiguration);\n\n        String url = \"http:www.example.com/test.txt\";\n        String file = \"/downloads/test.txt\";\n        \n        final Request request = new Request(url, file);\n        request.setPriority(Priority.HIGH);\n        request.setNetworkType(NetworkType.ALL);\n        request.addHeader(\"clientKey\", \"SD78DF93_3947\u0026MVNGHE1WONG\");\n        \n        fetch.enqueue(request, updatedRequest -\u003e {\n            //Request was successfully enqueued for download.\n        }, error -\u003e {\n            //An error occurred enqueuing the request.\n        });\n\n    }\n}\n```\n\nTracking a download's progress and status is very easy with Fetch. \nSimply add a FetchListener to your Fetch instance, and the listener will be notified whenever a download's\nstatus or progress changes.\n\n```java\nFetchListener fetchListener = new FetchListener() {\n    @Override\n    public void onQueued(@NotNull Download download, boolean waitingOnNetwork) {\n        if (request.getId() == download.getId()) {\n            showDownloadInList(download);\n        }\n    }\n\n    @Override\n    public void onCompleted(@NotNull Download download) {\n\n    }\n\n    @Override\n    public void onError(@NotNull Download download) {\n        Error error = download.getError();\n    }\n\n    @Override\n    public void onProgress(@NotNull Download download, long etaInMilliSeconds, long downloadedBytesPerSecond) {\n        if (request.getId() == download.getId()) {\n            updateDownload(download, etaInMilliSeconds);\n        }\n        int progress = download.getProgress();\n    }\n\n    @Override\n    public void onPaused(@NotNull Download download) {\n\n    }\n\n    @Override\n    public void onResumed(@NotNull Download download) {\n\n    }\n\n    @Override\n    public void onCancelled(@NotNull Download download) {\n\n    }\n\n    @Override\n    public void onRemoved(@NotNull Download download) {\n\n    }\n\n    @Override\n    public void onDeleted(@NotNull Download download) {\n\n    }\n};\n\nfetch.addListener(fetchListener);\n\n//Remove listener when done.\nfetch.removeListener(fetchListener);\n```\n\nFetch supports pausing and resuming downloads using the request's id.\nA request's id is a unique identifier that maps a request to a Fetch Download.\nA download returned by Fetch will have have an id that matches the request id that\nstarted the download.\n\n```java\nRequest request1 = new Request(url, file);\nRequest request2 = new Request(url2, file2);\n\nfetch.pause(request1.getId());\n\n...\n\nfetch.resume(request2.getId());\n\n```\n\nYou can query Fetch for download information in several ways.\n\n```java\n//Query all downloads\nfetch.getDownloads(new Func\u003cList\u003c? extends Download\u003e\u003e() {\n    @Override\n        public void call(List\u003c? extends Download\u003e downloads) {\n            //Access all downloads here\n        }\n});\n\n//Get all downloads with a status\nfetch.getDownloadsWithStatus(Status.DOWNLOADING, new Func\u003cList\u003c? extends Download\u003e\u003e() {\n    @Override\n        public void call(List\u003c? extends Download\u003e downloads) {\n            //Access downloads that are downloading\n        }\n});\n\n// You can also access grouped downloads\nint groupId = 52687447745;\nfetch.getDownloadsInGroup(groupId, new Func\u003cList\u003c? extends Download\u003e\u003e() {\n    @Override\n      public void call(List\u003c? extends Download\u003e downloads) {\n              //Access grouped downloads\n      }\n});\n```\n\nWhen you are done with an instance of Fetch, simply release it.\n\n```java\n//do work\n\nfetch.close();\n\n//do more work\n```\n\nDownloaders\n----------------\n\nBy default Fetch uses the HttpUrlConnection client via the HttpUrlConnectionDownloader\nto download requests. Add the following Gradle dependency to your application's build.gradle\nto use the OkHttp Downloader instead. You can create your custom downloaders\nif necessary. See the Java docs for details.\n\n```groovy\nimplementation \"com.github.tonyofrancis.Fetch:fetch2okhttp:3.4.1\"\n```\n\nSet the OkHttp Downloader for Fetch to use.\n```java\nOkHttpClient okHttpClient = new OkHttpClient.Builder().build();\n\nFetchConfiguration fetchConfiguration = new FetchConfiguration.Builder(this)\n    .setDownloadConcurrentLimit(10)\n    .setHttpDownloader(new OkHttpDownloader(okHttpClient))\n    .build();\n\nFetch fetch = Fetch.Impl.getInstance(fetchConfiguration);\n```\n\nRxFetch\n----------------\n\nIf you would like to take advantage of RxJava2 features when using Fetch,\nadd the following gradle dependency to your application's build.gradle file.\n\n```groovy\nimplementation \"com.github.tonyofrancis.Fetch:fetch2rx:3.4.1\"\n```\n\nRxFetch makes it super easy to enqueue download requests and query downloads using rxJava2 functional methods.\n\n```java\nFetchConfiguration fetchConfiguration = new FetchConfiguration.Builder(this).build();\nRxfetch rxFetch = RxFetch.Impl.getInstance(fetchConfiguration);\n\nrxFetch.getDownloads()\n        .asFlowable()\n        .subscribe(new Consumer\u003cList\u003cDownload\u003e\u003e() {\n            @Override\n            public void accept(List\u003cDownload\u003e downloads) throws Exception {\n                //Access results\n            }\n        }, new Consumer\u003cThrowable\u003e() {\n            @Override\n            public void accept(Throwable throwable) throws Exception {\n                //An error occurred\n                final Error error = FetchErrorUtils.getErrorFromThrowable(throwable);\n            }\n        });\n```\n\nFetchFileServer\n----------------\n\nIntroducing the FetchFileServer. The FetchFileServer is a lightweight TCP File Server that acts like\nan HTTP file server designed specifically to share files between Android devices. You can host file resources\nwith the FetchFileServer on one device and have to Fetch download Files from the server\non another device. See the sample app for more information. Wiki on FetchFileServer will be\nadded in the coming days.\n\nStart using FetchFileServer by adding the gradle dependency to your application's build.gradle file.\n \n```groovy\nimplementation \"com.github.tonyofrancis.Fetch:fetch2fileserver:3.4.1\"\n```\n\nStart a FetchFileServer instance and add resource files that it can serve to connected clients.\n```java\npublic class TestActivity extends AppCompatActivity {\n\n    FetchFileServer fetchFileServer;\n    \n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        fetchFileServer = new FetchFileServer.Builder(this)\n                .build();\n        \n        fetchFileServer.start(); //listen for client connections\n\n        File file = new File(\"/downloads/testfile.txt\");\n        FileResource fileResource = new FileResource();\n        fileResource.setFile(file.getAbsolutePath());\n        fileResource.setLength(file.length());\n        fileResource.setName(\"testfile.txt\");\n        fileResource.setId(UUID.randomUUID().hashCode());\n        \n        fetchFileServer.addFileResource(fileResource);\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        fetchFileServer.shutDown(false);\n    }\n}\n```\n\nDownloading a file from a FetchFileServer using the Fetch is easy.\n\n```java\npublic class TestActivity extends AppCompatActivity {\n\n    Fetch fetch;\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        FetchConfiguration fetchConfiguration = new FetchConfiguration.Builder(this)\n                .setFileServerDownloader(new FetchFileServerDownloader()) //have to set the file server downloader\n                .build();\n        fetch = Fetch.Impl.getInstance(fetchConfiguration);\n        fetch.addListener(fetchListener);\n\n        String file = \"/downloads/sample.txt\";\n        String url = new FetchFileServerUrlBuilder()\n                .setHostInetAddress(\"127.0.0.1\", 6886) //file server ip and port\n                .setFileResourceIdentifier(\"testfile.txt\") //file resource name or id\n                .create();\n        Request request = new Request(url, file);\n        fetch.enqueue(request, request1 -\u003e {\n            //Request enqueued for download\n        }, error -\u003e {\n            //Error while enqueuing download\n        });\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        fetch.addListener(fetchListener);\n    }\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        fetch.removeListener(fetchListener);\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        fetch.close();\n    }\n\n    private FetchListener fetchListener = new AbstractFetchListener() {\n        @Override\n        public void onProgress(@NotNull Download download, long etaInMilliSeconds, long downloadedBytesPerSecond) {\n            super.onProgress(download, etaInMilliSeconds, downloadedBytesPerSecond);\n            Log.d(\"TestActivity\", \"Progress: \" + download.getProgress());\n        }\n\n        @Override\n        public void onError(@NotNull Download download) {\n            super.onError(download);\n            Log.d(\"TestActivity\", \"Error: \" + download.getError().toString());\n        }\n\n        @Override\n        public void onCompleted(@NotNull Download download) {\n            super.onCompleted(download);\n            Log.d(\"TestActivity\", \"Completed \");\n        }\n    };\n}\n```\n\nFetch1 Migration\n----------------\n\nMigrate downloads from Fetch1 to Fetch2 using the migration assistant. Add the following gradle dependency to your application's build.gradle file.\n\n```groovy\nimplementation \"com.github.tonyofrancis.Fetch:fetchmigrator:3.4.1\"\n```\n\nThen run the Migrator.\n\n```java\n        if (!didMigrationRun()) {\n            //Migration has to run on a background thread\n            new Thread(new Runnable() {\n                @Override\n                public void run() {\n                    try {\n                        final List\u003cDownloadTransferPair\u003e transferredDownloads = FetchMigrator.migrateFromV1toV2(getApplicationContext(), APP_FETCH_NAMESPACE);\n                        //TODO: update external references of ids\n                        for (DownloadTransferPair transferredDownload : transferredDownloads) {\n                            Log.d(\"newDownload\", transferredDownload.getNewDownload().toString());\n                            Log.d(\"oldId in Fetch v1\", transferredDownload.getOldID() + \"\");\n                        }\n                        FetchMigrator.deleteFetchV1Database(getApplicationContext());\n                        setMigrationDidRun(true);\n                        //Setup and Run Fetch2 after the migration\n                    } catch (SQLException e) {\n                        e.printStackTrace();\n                    }\n                }\n            }).start();\n        } else {\n            //Setup and Run Fetch2  normally\n        }\n```\n\nContribute\n----------\n\nFetch can only get better if you make code contributions. Found a bug? Report it.\nHave a feature idea you'd love to see in Fetch? Contribute to the project!\n\nLicense\n-------\n\n```\nCopyright (C) 2017 Tonyo Francis.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftonyofrancis%2Ffetch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftonyofrancis%2Ffetch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftonyofrancis%2Ffetch/lists"}