Skip to content

Commit fb88cb8

Browse files
committed
Merge branch 'v3-develop' into v3.0
2 parents 61e5b53 + edfac86 commit fb88cb8

File tree

26 files changed

+412
-199
lines changed

26 files changed

+412
-199
lines changed

CHANGELOG

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
Version 3.0.11/ Androidx version 3.1.5
2+
2. Notification sound fixes.
3+
3. RxJava fixes.
4+
4. Content Length fixes
5+
5. Added NetworkType.UNMETERED
6+
6. Lots of bug fixes.
7+
8+
Thanks to everyone who contributed!
9+
110
Version 3.0.10/ Androidx version 3.1.4
211
1. Improvements/Bug fixes to getting a download's content-length
312
2. FetchDatabaseManager interface improvements. It is now easier to create custom fetch databases.

README.md

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
[![Build Status](https://travis-ci.org/tonyofrancis/Fetch.svg?branch=v2)](https://travis-ci.org/tonyofrancis/Fetch)
3-
[ ![Download](https://api.bintray.com/packages/tonyofrancis/maven/fetch2/images/download.svg?version=3.0.10) ](https://bintray.com/tonyofrancis/maven/fetch2/3.0.10/link)
3+
[ ![Download](https://api.bintray.com/packages/tonyofrancis/maven/fetch2/images/download.svg?version=3.0.11) ](https://bintray.com/tonyofrancis/maven/fetch2/3.0.11/link)
44
[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Android%20Networking-blue.svg?style=flat)](https://android-arsenal.com/details/1/5196)
55
[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/tonyofrancis/Fetch/blob/master/LICENSE)
66

@@ -21,7 +21,7 @@ Features
2121
* Concurrent downloading support.
2222
* Ability to pause and resume downloads.
2323
* Set the priority of a download.
24-
* Network specific downloading support.
24+
* Network-specific downloading support.
2525
* Ability to retry failed downloads.
2626
* Ability to group downloads.
2727
* Easy progress and status tracking.
@@ -43,18 +43,24 @@ add the following storage permissions to your application's manifest. For Androi
4343
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
4444
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
4545
```
46+
Also, as you are going to use Internet to download files. We need to add the Internet access permissions
47+
in the Manifest.
48+
49+
```xml
50+
<uses-permission android:name="android.permission.INTERNET"/>
51+
```
4652

4753
How to use Fetch
4854
----------------
4955

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

5258
```java
53-
implementation "com.tonyodev.fetch2:fetch2:3.0.10"
59+
implementation "com.tonyodev.fetch2:fetch2:3.0.11"
5460
```
5561
Androidx use:
5662
```java
57-
implementation "androidx.tonyodev.fetch2:xfetch2:3.1.4"
63+
implementation "androidx.tonyodev.fetch2:xfetch2:3.1.5"
5864
```
5965

6066
Next, get an instance of Fetch and request a download.
@@ -177,27 +183,27 @@ You can query Fetch for download information in several ways.
177183
```java
178184
//Query all downloads
179185
fetch.getDownloads(new Func<List<? extends Download>>() {
180-
@Override
186+
@Override
181187
public void call(List<? extends Download> downloads) {
182-
//Access all downloads here
188+
//Access all downloads here
183189
}
184190
});
185191

186192
//Get all downloads with a status
187193
fetch.getDownloadsWithStatus(Status.DOWNLOADING, new Func<List<? extends Download>>() {
188-
@Override
194+
@Override
189195
public void call(List<? extends Download> downloads) {
190-
//Access downloads that are downloading
196+
//Access downloads that are downloading
191197
}
192198
});
193199

194200
// You can also access grouped downloads
195201
int groupId = 52687447745;
196202
fetch.getDownloadsInGroup(groupId, new Func<List<? extends Download>>() {
197-
@Override
198-
public void call(List<? extends Download> downloads) {
199-
//Access grouped downloads
200-
}
203+
@Override
204+
public void call(List<? extends Download> downloads) {
205+
//Access grouped downloads
206+
}
201207
});
202208
```
203209

@@ -216,25 +222,25 @@ Downloaders
216222

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

222228
```java
223-
implementation "com.tonyodev.fetch2okhttp:fetch2okhttp:3.0.10"
229+
implementation "com.tonyodev.fetch2okhttp:fetch2okhttp:3.0.11"
224230
```
225231
Androidx use:
226232
```java
227-
implementation "androidx.tonyodev.fetch2okhttp:xfetch2okhttp:3.1.4"
233+
implementation "androidx.tonyodev.fetch2okhttp:xfetch2okhttp:3.1.5"
228234
```
229235

230236
Set the OkHttp Downloader for Fetch to use.
231237
```java
232238
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
233239

234240
FetchConfiguration fetchConfiguration = new FetchConfiguration.Builder(this)
235-
.setDownloadConcurrentLimit(10)
236-
.setHttpDownloader(new OkHttpDownloader(okHttpClient))
237-
.build();
241+
.setDownloadConcurrentLimit(10)
242+
.setHttpDownloader(new OkHttpDownloader(okHttpClient))
243+
.build();
238244

239245
Fetch fetch = Fetch.Impl.getInstance(fetchConfiguration);
240246
```
@@ -246,11 +252,11 @@ If you would like to take advantage of RxJava2 features when using Fetch,
246252
add the following gradle dependency to your application's build.gradle file.
247253

248254
```java
249-
implementation "com.tonyodev.fetch2rx:fetch2rx:3.0.10"
255+
implementation "com.tonyodev.fetch2rx:fetch2rx:3.0.11"
250256
```
251257
Androidx use:
252258
```java
253-
implementation "androidx.tonyodev.fetch2rx:xfetch2rx:3.1.4"
259+
implementation "androidx.tonyodev.fetch2rx:xfetch2rx:3.1.5"
254260
```
255261

256262
RxFetch makes it super easy to enqueue download requests and query downloads using rxJava2 functional methods.
@@ -280,20 +286,20 @@ FetchFileServer
280286

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

287293
Start using FetchFileServer by adding the gradle dependency to your application's build.gradle file.
288294
```java
289-
implementation "com.tonyodev.fetch2fileserver:fetch2fileserver:3.0.10"
295+
implementation "com.tonyodev.fetch2fileserver:fetch2fileserver:3.0.11"
290296
```
291297
Androidx use:
292298
```java
293-
implementation "androidx.tonyodev.fetch2fileserver:xfetch2fileserver:3.1.4"
299+
implementation "androidx.tonyodev.fetch2fileserver:xfetch2fileserver:3.1.5"
294300
```
295301

296-
Start a FetchFileServer instance and add resource files that it can server to connected clients.
302+
Start a FetchFileServer instance and add resource files that it can serve to connected clients.
297303
```java
298304
public class TestActivity extends AppCompatActivity {
299305

@@ -399,11 +405,11 @@ Fetch1 Migration
399405

400406
Migrate downloads from Fetch1 to Fetch2 using the migration assistant. Add the following gradle dependency to your application's build.gradle file.
401407
```java
402-
implementation "com.tonyodev.fetchmigrator:fetchmigrator:3.0.10"
408+
implementation "com.tonyodev.fetchmigrator:fetchmigrator:3.0.11"
403409
```
404410
Androidx use:
405411
```java
406-
implementation "androidx.tonyodev.fetchmigrator:xfetchmigrator:3.1.4"
412+
implementation "androidx.tonyodev.fetchmigrator:xfetchmigrator:3.1.5"
407413
```
408414

409415
Then run the Migrator.
@@ -450,7 +456,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
450456
you may not use this file except in compliance with the License.
451457
You may obtain a copy of the License at
452458
453-
http://www.apache.org/licenses/LICENSE-2.0
459+
http://www.apache.org/licenses/LICENSE-2.0
454460
455461
Unless required by applicable law or agreed to in writing, software
456462
distributed under the License is distributed on an "AS IS" BASIS,

fetch2/src/main/java/com/tonyodev/fetch2/DefaultFetchNotificationManager.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ abstract class DefaultFetchNotificationManager(context: Context) : FetchNotifica
9090
.setContentTitle(context.getString(R.string.fetch_notification_default_channel_name))
9191
.setContentText("")
9292
.setStyle(style)
93+
.setOnlyAlertOnce(true)
9394
.setGroup(groupId.toString())
9495
.setGroupSummary(true)
9596
return false
@@ -303,6 +304,7 @@ abstract class DefaultFetchNotificationManager(context: Context) : FetchNotifica
303304
.setTimeoutAfter(DEFAULT_NOTIFICATION_TIMEOUT_AFTER_RESET)
304305
.setOngoing(false)
305306
.setGroup(groupId.toString())
307+
.setOnlyAlertOnce(true)
306308
.setSmallIcon(android.R.drawable.stat_sys_download_done)
307309
.mActions.clear()
308310
return notificationBuilder

fetch2/src/main/java/com/tonyodev/fetch2/Error.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,14 @@ enum class Error constructor(
128128
FAILED_TO_RENAME_FILE(29),
129129

130130
/**
131-
* Indicates that an error occured when pre allocating the needed space on the storage system for the download.
131+
* Indicates that an error occurred when pre allocating the needed space on the storage system for the download.
132132
* */
133-
FILE_ALLOCATION_FAILED(30);
133+
FILE_ALLOCATION_FAILED(30),
134+
135+
/**
136+
* Indicates that connection to "http" is not allowed by the OS and "https" is required.
137+
* */
138+
HTTP_CONNECTION_NOT_ALLOWED(31);
134139

135140
companion object {
136141

@@ -166,6 +171,7 @@ enum class Error constructor(
166171
28 -> FAILED_TO_RENAME_INCOMPLETE_DOWNLOAD_FILE
167172
29 -> FAILED_TO_RENAME_FILE
168173
30 -> FILE_ALLOCATION_FAILED
174+
31 -> HTTP_CONNECTION_NOT_ALLOWED
169175
else -> UNKNOWN
170176
}
171177
}

fetch2/src/main/java/com/tonyodev/fetch2/FetchErrorUtils.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ fun getErrorFromMessage(message: String?): Error {
8383
Error.FAILED_TO_RENAME_FILE
8484
} else if(message.contains(FILE_ALLOCATION_ERROR, true)) {
8585
Error.FILE_ALLOCATION_FAILED
86+
} else if(message.contains(CLEAR_TEXT_NETWORK_VIOLATION, true)) {
87+
Error.HTTP_CONNECTION_NOT_ALLOWED
8688
} else {
8789
Error.UNKNOWN
8890
}

fetch2/src/main/java/com/tonyodev/fetch2/HttpUrlConnectionDownloader.kt

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,17 @@ open class HttpUrlConnectionDownloader @JvmOverloads constructor(
4646
return null
4747
}
4848

49+
private fun getCleanedHeaders(responseHeaders: MutableMap<String?, List<String>?>): MutableMap<String, List<String>> {
50+
val headers = mutableMapOf<String, List<String>>()
51+
for (responseHeader in responseHeaders) {
52+
val key = responseHeader.key
53+
if (key != null) {
54+
headers[key] = responseHeader.value ?: emptyList()
55+
}
56+
}
57+
return headers
58+
}
59+
4960
override fun execute(request: Downloader.ServerRequest, interruptMonitor: InterruptMonitor): Downloader.Response? {
5061
CookieHandler.setDefault(cookieManager)
5162
var httpUrl = URL(request.url)
@@ -56,20 +67,20 @@ open class HttpUrlConnectionDownloader @JvmOverloads constructor(
5667
client.addRequestProperty("Referer", referer)
5768
}
5869
client.connect()
59-
var responseHeaders = getResponseHeaders(client.headerFields)
70+
var responseHeaders = getCleanedHeaders(client.headerFields)
6071
var code = client.responseCode
6172
if ((code == HttpURLConnection.HTTP_MOVED_TEMP
62-
|| code == HttpURLConnection.HTTP_MOVED_PERM
63-
|| code == HttpURLConnection.HTTP_SEE_OTHER) && responseHeaders.containsKey("location")) {
64-
httpUrl = URL(responseHeaders["location"]?.firstOrNull() ?: "")
73+
|| code == HttpURLConnection.HTTP_MOVED_PERM
74+
|| code == HttpURLConnection.HTTP_SEE_OTHER) && getHeaderValue(responseHeaders, "Location") != null) {
75+
httpUrl = URL(getHeaderValue(responseHeaders, "Location") ?: "")
6576
client = httpUrl.openConnection() as HttpURLConnection
6677
onPreClientExecute(client, request)
6778
if (client.getRequestProperty("Referer") == null) {
6879
val referer = getRefererFromUrl(request.url)
6980
client.addRequestProperty("Referer", referer)
7081
}
7182
client.connect()
72-
responseHeaders = getResponseHeaders(client.headerFields)
83+
responseHeaders = getCleanedHeaders(client.headerFields)
7384
code = client.responseCode
7485
}
7586
var success = false
@@ -86,8 +97,7 @@ open class HttpUrlConnectionDownloader @JvmOverloads constructor(
8697
errorResponseString = copyStreamToString(client.errorStream, false)
8798
}
8899

89-
val acceptsRanges = code == HttpURLConnection.HTTP_PARTIAL ||
90-
responseHeaders["accept-ranges"]?.firstOrNull() == "bytes"
100+
val acceptsRanges = acceptRanges(code, responseHeaders)
91101

92102
onServerResponse(request, Downloader.Response(
93103
code = code,
@@ -96,7 +106,7 @@ open class HttpUrlConnectionDownloader @JvmOverloads constructor(
96106
byteStream = null,
97107
request = request,
98108
hash = hash,
99-
responseHeaders = responseHeaders,
109+
responseHeaders = client.headerFields,
100110
acceptsRanges = acceptsRanges,
101111
errorResponse = errorResponseString))
102112

@@ -128,7 +138,7 @@ open class HttpUrlConnectionDownloader @JvmOverloads constructor(
128138
}
129139

130140
override fun getContentHash(responseHeaders: MutableMap<String, List<String>>): String {
131-
return responseHeaders["content-md5"]?.firstOrNull() ?: ""
141+
return getHeaderValue(responseHeaders, "Content-MD5") ?: ""
132142
}
133143

134144
override fun close() {
@@ -146,20 +156,6 @@ open class HttpUrlConnectionDownloader @JvmOverloads constructor(
146156
}
147157
}
148158

149-
private fun getResponseHeaders(responseHeaders: MutableMap<String, List<String>>): MutableMap<String, List<String>> {
150-
val headers = mutableMapOf<String, List<String>>()
151-
val iterator = responseHeaders.iterator()
152-
var entry: Map.Entry<String, List<String>>
153-
while (iterator.hasNext()) {
154-
entry = iterator.next()
155-
@Suppress("SENSELESS_COMPARISON")
156-
if (entry.key != null) {
157-
headers[entry.key.toLowerCase()] = entry.value
158-
}
159-
}
160-
return headers
161-
}
162-
163159
override fun getFileSlicingCount(request: Downloader.ServerRequest, contentLength: Long): Int? {
164160
return null
165161
}
@@ -193,6 +189,9 @@ open class HttpUrlConnectionDownloader @JvmOverloads constructor(
193189
}
194190

195191
override fun getRequestSupportedFileDownloaderTypes(request: Downloader.ServerRequest): Set<Downloader.FileDownloaderType> {
192+
if (fileDownloaderType == Downloader.FileDownloaderType.SEQUENTIAL) {
193+
return mutableSetOf(fileDownloaderType)
194+
}
196195
return try {
197196
getRequestSupportedFileDownloaderTypes(request, this)
198197
} catch (e: Exception) {
@@ -212,4 +211,4 @@ open class HttpUrlConnectionDownloader @JvmOverloads constructor(
212211
var followsRedirect = true
213212
}
214213

215-
}
214+
}

fetch2/src/main/java/com/tonyodev/fetch2/NetworkType.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ enum class NetworkType(val value: Int) {
1515
ALL(0),
1616

1717
/** Indicates that a download can be downloaded only on wifi networks.*/
18-
WIFI_ONLY(1);
18+
WIFI_ONLY(1),
19+
20+
/** Indicates that a download can be downloaded only on an unmetered connection.*/
21+
UNMETERED(2);
1922

2023
companion object {
2124

@@ -25,6 +28,7 @@ enum class NetworkType(val value: Int) {
2528
-1 -> GLOBAL_OFF
2629
0 -> ALL
2730
1 -> WIFI_ONLY
31+
2 -> UNMETERED
2832
else -> ALL
2933
}
3034
}

fetch2/src/main/java/com/tonyodev/fetch2/downloader/DownloadManagerImpl.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ class DownloadManagerImpl(private val httpDownloader: Downloader<*, *>,
109109
} finally {
110110
removeDownloadMappings(download)
111111
val intent = Intent(ACTION_QUEUE_BACKOFF_RESET)
112+
intent.setPackage(context.packageName)
112113
intent.putExtra(EXTRA_NAMESPACE, namespace)
113114
context.sendBroadcast(intent)
114115
}
@@ -257,7 +258,12 @@ class DownloadManagerImpl(private val httpDownloader: Downloader<*, *>,
257258
}
258259

259260
private fun getFileDownloader(download: Download, downloader: Downloader<*, *>): FileDownloader {
260-
val request = getRequestForDownload(download)
261+
val originalRequest = getRequestForDownload(download)
262+
val request = if (downloader.getHeadRequestMethodSupported(originalRequest)) {
263+
getRequestForDownload(download, HEAD_REQUEST_METHOD)
264+
} else {
265+
originalRequest
266+
}
261267
val supportedDownloadTypes = downloader.getRequestSupportedFileDownloaderTypes(request)
262268
return if (downloader.getRequestFileDownloaderType(request, supportedDownloadTypes) == Downloader.FileDownloaderType.SEQUENTIAL) {
263269
SequentialFileDownloaderImpl(

0 commit comments

Comments
 (0)