Step 1. Add the JitPack repository to your build file
Add it in your root settings.gradle at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
Add it in your settings.gradle.kts at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}
Add to pom.xml
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
Add it in your build.sbt at the end of resolvers:
resolvers += "jitpack" at "https://jitpack.io"
Add it in your project.clj at the end of repositories:
:repositories [["jitpack" "https://jitpack.io"]]
Step 2. Add the dependency
dependencies {
implementation 'com.github.jobinlawrance:okhttp3-downloadprogress-interceptor:1.0.1'
}
dependencies {
implementation("com.github.jobinlawrance:okhttp3-downloadprogress-interceptor:1.0.1")
}
<dependency>
<groupId>com.github.jobinlawrance</groupId>
<artifactId>okhttp3-downloadprogress-interceptor</artifactId>
<version>1.0.1</version>
</dependency>
libraryDependencies += "com.github.jobinlawrance" % "okhttp3-downloadprogress-interceptor" % "1.0.1"
:dependencies [[com.github.jobinlawrance/okhttp3-downloadprogress-interceptor "1.0.1"]]
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()
}
})