我正在使用Dagger2 + Retrofit + RxAndroid + OkHttp3 + New Architecture组件开发一个Android应用程序。 最低sdk = 16 。
问题:在API 16上运行应用程序时,网址生成不正确。网址缺少我通过改造传递的@QueryMap参数。当我在21级以上的api级别上测试应用程序时,同样可以正常工作。
正确的网址- 在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>
Retrofit Builder-
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上失败。
答案 0 :(得分:1)
很明显,您的 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)
}
参考:
答案 1 :(得分:1)
伙计,请阅读OkHttp要求部分:https://github.com/square/okhttp#requirements从字面上仅提及3.12.x分支支持Android 2.3+(API级别9+)和Java 7+。缺乏对设备
答案 2 :(得分:0)
最后!我解决了这个问题。 解决方案-欺骗是使用拦截器。通过检查正确的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 +的网址。对于SDK <21,我使用如上所述的拦截器来构建URL。
我感谢大家在此问题上的帮助。我相信外面有人会觉得有帮助的!