Android - retrofit - Base Url中缺少查询参数

问题描述 投票:1回答:3

我正在使用Dagger2 + Retrofit + RxAndroid + OkHttp3 +新架构组件开发Android应用程序。 Min sdk = 16。

问题:在API 16上运行应用程序时,Url生成不正确。 Url缺少我通过Retrofit传递的@QueryMap参数。当我在api级别21+上测试应用程序时,工作正常。

正确的网址 - 关于api 21+ - “http://api.apixu.com/v1/forecast.json?q=IDR&days=10&key=apikey

网址在api 16/19上生成 - “http://api.apixu.com/v1/forecast.json

改造界面 -

@GET("forecast.json")
fun fetchWeatherDetails(
    @QueryMap hashMap: @NotNull HashMap<String, String>
): @NotNull Observable<ApiResponse>

改造生成器 -

val httpClient = getOkHttpClient()
    return Retrofit.Builder()
        .baseUrl(apiBaseUrl)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .client(httpClient)
        .build()

OkHttpClient -

val builder = OkHttpClient.Builder()
    builder
        .cache(cache)
        .connectTimeout(60, TimeUnit.SECONDS)
        .readTimeout(60, TimeUnit.SECONDS)
        .followRedirects(true)
        .followSslRedirects(true)

    val httpLoggingInterceptor = HttpLoggingInterceptor()

    if (BuildConfig.DEBUG) {
        httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
    } else {
        httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.NONE
    }

    builder.addInterceptor(HeaderInterceptor())
        .addInterceptor(httpLoggingInterceptor)
    return builder.build()

我被困在这个问题上已经超过2天了。任何帮助,将不胜感激。

更新:Api查询代码在API 21+上正常运行。

API-16和API-19失败。

android retrofit rx-java okhttp3 okhttpclient
3个回答
1
投票

很明显,您的网址没有编码,为此,您需要确保使用@QueryMap(encoded = true)在所有平台上对其进行编码。

如果它没有成功,我担心你需要手动使用自定义拦截器来编码像?这样的字符,这些字符等于%3F,例如:

@Override
    Response intercept(Interceptor.Chain chain) throws IOException {
        Request request = chain.request()
        def string = request.url().toString()
        string = string.replace("%26", "&")
        string = string.replace("%3D", "=")
        string = string.replace("%3F", "?")

        Request newRequest = new Request.Builder()
            .url(string)
            .build()

        return chain.proceed(newRequest)
    }

参考文献:


1
投票

男人,阅读OkHttp要求部分:https://github.com/square/okhttp#requirements它字面上只提到3.12.x分支支持Android 2.3+(API级别9+)和Java 7+。对于设备<API 21缺乏对TLS 1.2的支持是二重奏。如果你真的想支持API 21下的任何内容,那么将你的OkHttp版本更新到3.12.x,直到2020年12月31日仍然可用。


0
投票

最后!!我解决了这个问题。解决方案 - Trick是使用拦截器。通过检查正确的SDK VERSION和拦截器,终于让我的东西运行了。

internal class HeaderInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {    
var request = chain.request()    
val url = request.url().newBuilder()
            .addQueryParameter("key", API_KEY)
            .addQueryParameter("q", QUERY_PARAMETER)
            .addQueryParameter("days", DAYS)
            .build()
request = request.newBuilder().url(url).build()
return chain.proceed(request)
  }
}

OkHttpClient需要SDK_VERSION检查 -

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
   builder.addInterceptor(HeaderInterceptor())
}

所以赶紧给我看 - @QueryMap(在改造中)很好地构建了SDK-21 +的url。对于SDK <21,我使用上面提到的拦截器来构建url。

我感谢大家对此事的帮助。我相信有人会觉得这很有帮助!!

© www.soinside.com 2019 - 2024. All rights reserved.