Search code examples
androidokhttpandroid-networking

Is it possible to throttle bandwidth when using OkHttp?


Is it possible when using OkHttp to throttle the bandwidth? (possibly using a network interceptor).


Solution

  • You can make it work in two ways:

    1. Send request and read stream manually, and throttle while reading there.
    2. Add an Interceptor.

    Using OkHttp the best way is Interceptor. There are also a few simple steps:

    1. To inherit the Interceptor interface.
    2. To inherit the ResponseBody class.
    3. In custom ResponceBody override fun source(): BufferedSource needs to return the BandwidthSource's buffer.

    Example of BandwidthSource:

    class BandwidthSource(
        source: Source,
        private val bandwidthLimit: Int
    ) : ForwardingSource(source) {
    
        private var time = getSeconds()
    
        override fun read(sink: Buffer, byteCount: Long): Long {
            val read = super.read(sink, byteCount)
            throttle(read)
            return read
        }
    
        private fun throttle(byteCount: Long) {
            val bitsCount = byteCount * BITS_IN_BYTE
            val currentTime = getSeconds()
            val timeDiff = currentTime - time
            if (timeDiff == 0L) {
                return
            }
            val kbps = bitsCount / timeDiff
            if (kbps > bandwidthLimit) {
                val times = (kbps / bandwidthLimit)
                if (times > 0) {
                    runBlocking { delay(TimeUnit.SECONDS.toMillis(times)) }
                }
            }
            time = currentTime
        }
    
        private fun getSeconds(): Long {
            return TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())
        }
    }