ssseasonnn / RxDownload

A multi-threaded download tool written with RxJava and Kotlin
Apache License 2.0
4.14k stars 612 forks source link

Downloading files bigger than 15 mb doesn't seem to work on lower-end devices #352

Closed vanesca88 closed 2 years ago

Teemo100 commented 2 years ago

邮件已收到,三日内拜读

vanesca88 commented 2 years ago

Found the solution. Posting it here, in case anyone is interested. You can't link the project using any repo. Instead, you'll have to download it from Github and link it yourself, just so you can make a change to the source code.

It's this file, line 17 https://github.com/ssseasonnn/RxDownload/blob/master/rxdownload4/src/main/java/zlc/season/rxdownload4/request/Retrofiter.kt

Change it to this: (I also made the time-outs shorter, because they took too long) val okHttpClient: OkHttpClient = OkHttpClient().newBuilder() .connectTimeout(15, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .protocols(Collections.singletonList(Protocol.HTTP_1_1)) /// <----- MOST IMPORTANT LINE .build()

By adding protocol HTTP 1.1, RxDownload now also works on lower-end android devices (Android 10 or lower) It normally already works, but it stops downloading, if you either download too many files at once, or download bigger files than just a few MB's. With this tweak, it should always download any file.

You'll also need to add the missing dependencies to your build.gradle:

//implementation 'com.github.ssseasonnn:RxDownload:1.1.3' // (merged)
implementation 'com.squareup.retrofit2:retrofit:2.6.2'
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.1'
implementation "com.squareup.okhttp3:okhttp:3.12.12"
implementation "com.squareup.okio:okio:3.0.0-alpha.4"
implementation 'io.reactivex.rxjava2:rxjava:2.2.10'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation "io.reactivex.rxjava2:rxkotlin:2.4.0"
implementation 'com.github.ssseasonnn:ClarityPotion:1.0.2'
ssseasonnn commented 2 years ago

No need to be so troublesome, you just need to customize a RequestImpl.

//first custom your okhttp
val customOkHttp: OkHttpClient = OkHttpClient().newBuilder()
        .connectTimeout(15, TimeUnit.SECONDS)
        .readTimeout(120, TimeUnit.SECONDS)
        .writeTimeout(120, TimeUnit.SECONDS)
        .build()

fun <reified T> request(
        baseUrl: String = FAKE_BASE_URL,
        client: OkHttpClient = okHttpClient,
        callAdapterFactory: CallAdapter.Factory = RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()),
        converterFactory: Converter.Factory = GsonConverterFactory.create()
): T {
    val retrofit = Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(customOkHttp)
            .addCallAdapterFactory(callAdapterFactory)
            .addConverterFactory(converterFactory)
            .build()

    return retrofit.create(T::class.java)
}

//then create your request impl:
object YourRequestImpl: Request {
    private val api = request<Api>()

    override fun get(url: String, headers: Map<String, String>): Flowable<Response<ResponseBody>> {
        return api.get(url, headers)
    }

    interface Api {
        @GET
        @Streaming
        fun get(
                @Url url: String,
                @HeaderMap headers: Map<String, String>
        ): Flowable<Response<ResponseBody>>
    }
}

//and pass your requestImpl into download method:
"url".download(request = YourRequestImpl)