Android - 改造 - Base Url 中缺少查询参数
Android - retrofit - Query parameters missing from Base Url
我正在使用 Dagger2 + Retrofit + RxAndroid + OkHttp3 + 新架构组件开发 android 应用程序。 最小 sdk = 16.
问题:运行 API 16 上的应用程序时,Url 生成不正确。 Url 缺少我通过 Retrofit 传递的 @QueryMap 参数。当我在 api 级别 21+ 上测试应用程序时,同样工作正常。
正确url -
在 api 21+ - “http://api.apixu.com/v1/forecast.json?q=IDR&days=10&key=apikey”
url 生成于 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 上失败。
很明显您的 URL 没有编码,为此您需要确保它在使用 @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)
}
参考文献:
- Question mark in the middle of a url variable?
- https://github.com/square/retrofit/issues/1199
伙计,请阅读 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 日。
终于!!我解决了这个问题。
解决方案 - 技巧是使用拦截器。通过检查正确的 SDK 版本和拦截器,我终于得到了我的东西 运行。
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.
感谢大家对此事的帮助。我相信有人会觉得这很有帮助!!
我正在使用 Dagger2 + Retrofit + RxAndroid + OkHttp3 + 新架构组件开发 android 应用程序。 最小 sdk = 16.
问题:运行 API 16 上的应用程序时,Url 生成不正确。 Url 缺少我通过 Retrofit 传递的 @QueryMap 参数。当我在 api 级别 21+ 上测试应用程序时,同样工作正常。
正确url - 在 api 21+ - “http://api.apixu.com/v1/forecast.json?q=IDR&days=10&key=apikey”
url 生成于 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 上失败。
很明显您的 URL 没有编码,为此您需要确保它在使用 @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)
}
参考文献:
- Question mark in the middle of a url variable?
- https://github.com/square/retrofit/issues/1199
伙计,请阅读 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 日。
终于!!我解决了这个问题。 解决方案 - 技巧是使用拦截器。通过检查正确的 SDK 版本和拦截器,我终于得到了我的东西 运行。
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.
感谢大家对此事的帮助。我相信有人会觉得这很有帮助!!