Skip to content

Commit b2509ae

Browse files
committed
fix!: ignored progress interval parameter (#172)
* fix: ignored progress interval parameter on Android * chore: bump minSdkVersion from 19 to 21 to support mockk 1.12.1+ BREAKING CHANGE: change required Android version to 21+
1 parent fe74402 commit b2509ae

File tree

14 files changed

+158
-75
lines changed

14 files changed

+158
-75
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg)](https://opensource.org/licenses/MPL-2.0)
44
[![Build](https://github.com/edeckers/react-native-blob-courier/workflows/Build%20Android%20and%20iOS/badge.svg)](https://github.com/edeckers/react-native-blob-courier/actions)
55

6-
Use this library to efficiently _download_ and _upload_ blobs in React Native. The library was inspired by [rn-fetch-blob](https://github.com/joltup/rn-fetch-blob), and aims to focus strictly on blob transfers.
6+
Use this library to efficiently download and upload data in React Native. The library was inspired by [rn-fetch-blob](https://github.com/joltup/rn-fetch-blob), and is focused strictly on http file transfers.
77

88
## Installation
99

@@ -35,7 +35,7 @@ cd ios && pod install
3535

3636
## Requirements
3737

38-
- Android >= 19
38+
- Android >= 21
3939
- iOS >= 10
4040
- Kotlin >= 1.4.x
4141

@@ -496,7 +496,7 @@ You can find an example of how to use the library in the [example](example) dire
496496

497497
### Permissions
498498

499-
### Android 5.0 and below (API level < 23)
499+
### Android 5.1 and below (API level < 23)
500500

501501
Add the following line to `AndroidManifest.xml`.
502502

android/build.gradle

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ repositories {
149149
}
150150

151151
def kotlin_version = getExtOrDefault('kotlinVersion')
152+
def mockk_version = '1.12.1'
152153

153154
dependencies {
154155
// noinspection GradleDynamicVersion
@@ -159,13 +160,13 @@ dependencies {
159160
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
160161
testImplementation 'androidx.test:core:1.3.0'
161162
testImplementation 'junit:junit:4.13.1'
162-
testImplementation "io.mockk:mockk:1.10.2"
163-
testImplementation "io.mockk:mockk-agent-api:1.10.2"
164-
testImplementation "io.mockk:mockk-agent-jvm:1.10.2"
163+
testImplementation "io.mockk:mockk:$mockk_version"
164+
testImplementation "io.mockk:mockk-agent-api:$mockk_version"
165+
testImplementation "io.mockk:mockk-agent-jvm:$mockk_version"
165166
testImplementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
166167
testImplementation 'org.robolectric:robolectric:4.4'
167168
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2"
168-
androidTestImplementation "io.mockk:mockk-android:1.10.2"
169+
androidTestImplementation "io.mockk:mockk-android:$mockk_version"
169170
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
170171
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
171172
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2"

android/gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
BlobCourier_kotlinVersion = 1.4.21
22
BlobCourier_compileSdkVersion = 30
33
BlobCourier_buildToolsVersion = 30.0.0
4-
BlobCourier_targetSdkVersion = 29
5-
BlobCourier_minSdkVersion = 19
4+
BlobCourier_targetSdkVersion = 30
5+
BlobCourier_minSdkVersion = 21
66

77
ADB_COMMAND_TIMEOUT_MILLISECONDS = 10000L
88
PROMISE_TIMEOUT_MILLISECONDS = 60000L

android/src/androidTest/java/io/deckers/blob_courier/BlobCourierInstrumentedModuleTests.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import io.deckers.blob_courier.Fixtures.runFetchBlobSuspend
2323
import io.deckers.blob_courier.TestUtils
2424
import io.deckers.blob_courier.TestUtils.assertRequestFalse
2525
import io.deckers.blob_courier.TestUtils.assertRequestTrue
26-
import io.deckers.blob_courier.TestUtils.circumventHiddenApiExemptionsForMockk
2726
import io.deckers.blob_courier.TestUtils.runInstrumentedRequestToBoolean
2827
import io.deckers.blob_courier.common.DOWNLOAD_TYPE_MANAGED
2928
import io.deckers.blob_courier.common.ERROR_CANCELED_EXCEPTION
@@ -148,8 +147,6 @@ class BlobCourierInstrumentedModuleTests {
148147
fun mockSomeNativeOnlyMethods() {
149148
li("Restore method mocks")
150149

151-
circumventHiddenApiExemptionsForMockk()
152-
153150
mockkStatic(Arguments::class)
154151

155152
every { Arguments.createMap() } answers { JavaOnlyMap() }
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2-
package="io.deckers.blob_courier"
3-
xmlns:tools="http://schemas.android.com/tools">
2+
xmlns:tools="http://schemas.android.com/tools"
3+
package="io.deckers.blob_courier">
44

55
<uses-permission android:name="android.permission.INTERNET" />
66
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
77

88
<uses-sdk tools:overrideLibrary="com.facebook.react" />
99

10-
<application android:usesCleartextTraffic="true" />
10+
<application
11+
android:usesCleartextTraffic="true"
12+
tools:targetApi="m" />
1113

1214
</manifest>

android/src/main/java/io/deckers/blob_courier/BlobCourierModule.kt

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,13 @@ import java.net.UnknownHostException
3737
import kotlin.concurrent.thread
3838

3939
private fun createHttpClient() = OkHttpClientProvider.getOkHttpClient()
40-
private fun createProgressFactory(reactContext: ReactApplicationContext) =
40+
private fun createProgressFactory(
41+
reactContext: ReactApplicationContext,
42+
progressTimeoutMilliseconds: Int = DEFAULT_PROGRESS_TIMEOUT_MILLISECONDS
43+
) =
4144
CongestionAvoidingProgressNotifierFactory(
4245
reactContext,
43-
DEFAULT_PROGRESS_TIMEOUT_MILLISECONDS
46+
progressTimeoutMilliseconds
4447
)
4548

4649
private val TAG = BlobCourierModule::class.java.name
@@ -49,7 +52,7 @@ private fun le(m: String, e: Throwable? = null) = logger.e(m, e)
4952
private fun li(m: String) = logger.i(m)
5053
private fun lv(m: String, e: Throwable? = null) = logger.v(m, e)
5154

52-
@ReactModule(name=LIBRARY_NAME)
55+
@ReactModule(name = LIBRARY_NAME)
5356
class BlobCourierModule(private val reactContext: ReactApplicationContext) :
5457
ReactContextBaseJavaModule(reactContext) {
5558

@@ -74,7 +77,8 @@ class BlobCourierModule(private val reactContext: ReactApplicationContext) :
7477
lv("Something went wrong during cancellation (code=${e.code},message=${e.message})")
7578
promise.reject(e.code, e.message)
7679
},
77-
promise::resolve)
80+
promise::resolve
81+
)
7882
} catch (e: Exception) {
7983
le("Unexpected exception", e)
8084
promise.reject(ERROR_UNEXPECTED_EXCEPTION, processUnexpectedException(e).message)
@@ -96,13 +100,16 @@ class BlobCourierModule(private val reactContext: ReactApplicationContext) :
96100
DownloaderParameterFactory()
97101
.fromInput(input)
98102
.fold(::Failure, ::Success)
99-
.fmap(
103+
.fmap { pxs ->
100104
BlobDownloader(
101105
reactContext,
102106
createHttpClient(),
103-
createProgressFactory(reactContext),
104-
)::download
105-
)
107+
createProgressFactory(
108+
reactContext,
109+
pxs.progressInterval
110+
),
111+
).download(pxs)
112+
}
106113

107114
errorOrDownloadResult
108115
.fmap { Success(it.toReactMap()) }
@@ -135,13 +142,16 @@ class BlobCourierModule(private val reactContext: ReactApplicationContext) :
135142
UploaderParameterFactory()
136143
.fromInput(input)
137144
.fold(::Failure, ::Success)
138-
.fmap(
145+
.fmap { pxs ->
139146
BlobUploader(
140147
reactContext,
141148
createHttpClient(),
142-
createProgressFactory(reactContext)
143-
)::upload
144-
)
149+
createProgressFactory(
150+
reactContext,
151+
pxs.progressInterval
152+
)
153+
).upload(pxs)
154+
}
145155
.map { it.toReactMap() }
146156
.`do`(
147157
{ f ->

android/src/main/java/io/deckers/blob_courier/fetch/DownloaderParameterFactory.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import io.deckers.blob_courier.common.isNotNull
3131
import io.deckers.blob_courier.common.maybe
3232
import io.deckers.blob_courier.common.testKeep
3333
import io.deckers.blob_courier.common.validationContext
34-
import java.util.Locale
3534

3635
private const val PARAMETER_ANDROID_SETTINGS = "android"
3736
private const val PARAMETER_DOWNLOAD_MANAGER_SETTINGS = "downloadManager"
@@ -91,8 +90,7 @@ private fun validateParameters(
9190
BlobDownloader.TargetDirectoryEnum
9291
.values()
9392
.firstOrNull { t ->
94-
t.name.toLowerCase(Locale.getDefault()) ==
95-
targetDirectoryOrFallback.toLowerCase(Locale.getDefault())
93+
t.name.equals(targetDirectoryOrFallback, ignoreCase = true)
9694
}
9795

9896
val downloadManagerSettings =

android/src/main/java/io/deckers/blob_courier/fetch/ManagedDownloadReceiver.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,13 @@ class ManagedDownloadReceiver(
8787
lv("Received status (status=$status, isStatusSuccessful=$isStatusSuccessful)")
8888

8989
if (isStatusSuccessful) {
90-
val localFileUri =
91-
Uri.parse(cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)))
90+
val columnLocalUri = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)
91+
val isExistingColumn = columnLocalUri > 0
92+
if (!isExistingColumn) {
93+
return
94+
}
95+
96+
val localFileUri = Uri.parse(cursor.getString(columnLocalUri))
9297

9398
onDownloadDone(context, localFileUri)
9499

android/src/main/java/io/deckers/blob_courier/progress/ManagedProgressUpdater.kt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,17 @@ class ManagedProgressUpdater(
5454
return
5555
}
5656

57-
val numberOfBytes =
58-
cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
59-
val totalSizeBytes =
60-
cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
57+
val columnBytesDownloadedSoFar =
58+
cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)
59+
val columnTotalSizeBytes = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)
60+
61+
val areExistingColumns = columnBytesDownloadedSoFar > 0 && columnTotalSizeBytes > 0
62+
if (!areExistingColumns) {
63+
return
64+
}
65+
66+
val numberOfBytes = cursor.getLong(columnBytesDownloadedSoFar)
67+
val totalSizeBytes = cursor.getLong(columnTotalSizeBytes)
6168

6269
progressNotifier.notify(numberOfBytes, totalSizeBytes)
6370
}

android/src/main/java/io/deckers/blob_courier/react/Utils.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ fun Map<*, *>.toReactMap(): WritableMap {
7070
(v is Boolean) -> {
7171
putBoolean(k.toString(), v)
7272
}
73+
(v is Int) ->
74+
putInt(k.toString(), v)
7375
(v is String) ->
7476
putString(k.toString(), v)
7577
(v is Map<*, *>) -> {

0 commit comments

Comments
 (0)