Skip to content

Instantly share code, notes, and snippets.

@diefferson
Created June 1, 2018 18:07
Show Gist options
  • Save diefferson/1d4b7d9d77f406dd9b629f604ad480f2 to your computer and use it in GitHub Desktop.
Save diefferson/1d4b7d9d77f406dd9b629f604ad480f2 to your computer and use it in GitHub Desktop.
Retrofit Download Progress
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import javax.net.ssl.HostnameVerifier
object DownloadClient{
fun getRetrofitDownloadClient(progressListener: DownloadProgressListener): RestApi {
val okHttp = OkHttpClient.Builder()
.hostnameVerifier(getHostnameVerifier())
.addInterceptor(DownloadProgressInterceptor(progressListener))
.retryOnConnectionFailure(true)
return Retrofit.Builder()
.baseUrl("URL")
.client(okHttp.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.build().create(RestApi::class.java)
}
private class DownloadProgressInterceptor(private val listener: DownloadProgressListener) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val originalResponse = chain.proceed(chain.request())
return originalResponse.newBuilder()
.body(DownloadProgressResponseBody(originalResponse.body()!!, listener))
.build()
}
}
private fun getHostnameVerifier(): HostnameVerifier {
return HostnameVerifier { _, _ ->
true
}
}
}
interface DownloadProgressListener{
fun onAttachmentDownloadUpdate(percent: Int)
}
import okhttp3.MediaType
import okhttp3.ResponseBody
import okio.*
import java.io.IOException
class DownloadProgressResponseBody(private val responseBody: ResponseBody?,
private val progressListener: DownloadProgressListener?) : ResponseBody() {
private var bufferedSource: BufferedSource? = null
override fun contentType(): MediaType? {
return responseBody?.contentType()
}
override fun contentLength(): Long {
return responseBody?.contentLength()?:0
}
override fun source(): BufferedSource {
if (bufferedSource == null) {
bufferedSource = Okio.buffer(source(responseBody?.source()!!))
}
return bufferedSource!!
}
private fun source(source: Source): Source {
return object : ForwardingSource(source) {
internal var totalBytesRead :Float = 0f
@Throws(IOException::class)
override fun read(sink: Buffer, byteCount: Long): Long {
val bytesRead = super.read(sink, byteCount)
// read() returns the number of bytes read, or -1 if this source is exhausted.
totalBytesRead += if (bytesRead != -1L) bytesRead else 0
val percent: Float = if(bytesRead == -1L) 100f else ((totalBytesRead/contentLength()) * 100)
progressListener?.onAttachmentDownloadUpdate(percent = percent.toInt())
return bytesRead
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment