An OkHttp interceptor which monitors download progress of HTTP response data.
Downloadprogress Interceptor is available on Jitpack
add the JitPack repository in your project build.gradle (in top level dir):
repositories {
jcenter()
maven { url "https://jitpack.io" }
}
and the dependency in the build.gradle of the module:
dependencies {
compile 'com.github.jobinlawrance:okhttp3-downloadprogress-interceptor:1.0.1'
}
The progress monitoring won't work if the reponse doesn't have a content-length
in it's header.
We use a simple event bus ProgressEventBus
to track the progress of all the download requests.
Since OkHttpClient
and Retrofit
is instantiated as application wise singletons, the same should be done with ProgressEventBus
and it should be injected to the classes that requires the progress monitoring.
val progressEventBus: ProgressEventBus = ProgressEventBus()
val downloadInterceptor: DownloadProgressInterceptor = DownloadProgressInterceptor(progressEventBus)
val okHttpClient = OkHttpClient.Builder()
.addNetworkInterceptor(downloadInterceptor)
.build()
val retrofit = Retrofit.Builder()
... // base url, adapter factory etc
.client(okHttpClient)
.build();
Since OkHttp
client is used for all Http requests, in order to differentiate the request we are interested in, we add a custom header to it.
Our retrofit interface will look like this -
interface PhotoService {
@GET
@Streaming
fun downloadPhoto(@Url url: String, @Header(DOWNLOAD_IDENTIFIER_HEADER) identifier: String) : Observable<ResponseBody>
}
To receive download progress updates, we subsribe to ProgressEventBus
. Whenever a download is started by retrofit all the subscibers receives a ProgressEvent
which has the progress
(in percent) and downloadIdentifier
data among others.
Since ProgressEventBus
monitors all the download requests with the custom header we set above, we check the ProgressEvent.dowloadIdentfier
to filter out the ProgressEvent
we are interested in.
Here's an example -
// Inject retrofit and progressEventBus
@Inject lateinit val retrofit
@Inject lateinit val progressEventBus
val imageUrl = "https://upload.wikimedia.org/wikipedia/commons/2/24/Junonia_orithya-Thekkady-2016-12-03-001.jpg"
val imageIdentifier = "my-wiki-image"
val disposable = // handle unsubscription
progressEventBus.observable()
.subscribe({
if(it.downloadIdentifier == imageIdentifier) {
// Display the progress here
Log.d("Download Progress - ${it.progress}")
}
},{
Log.d("ProgressEvent Error",it)
})
retrofit.create(PhotoService::class.java)
.downloadPhoto(imageUrl, imageIdentifier)
.subscribe({
// onNext(resonseBody)
// Download start,
// code to save the responseBody to file in storage
},{
// onError()
// Error in dowloading
},{
// Download complete
if (!disposable.isDisposed) {
disposable.dispose()
}
})