在改造中添加标题参数

Posted

技术标签:

【中文标题】在改造中添加标题参数【英文标题】:Add Header Parameter in Retrofit 【发布时间】:2017-08-11 10:55:00 【问题描述】:

我正在尝试调用一个需要我传递 API 密钥的 API。

我使用HttpURLConnection 的服务调用运行良好。

url = new URL("https://developers.zomato.com/api/v2.1/search?entity_id=3&entity_type=city&q=" + params[0]);
urlConnection = (HttpURLConnection) url.openConnection();

urlConnection.setRequestProperty("user-key","9900a9720d31dfd5fdb4352700c");

if (urlConnection.getResponseCode() != 200) 
    Toast.makeText(con, "url connection response not 200 | " + urlConnection.getResponseCode(), Toast.LENGTH_SHORT).show();
    Log.d("jamian", "url connection response not 200 | " + urlConnection.getResponseCode());
    throw new RuntimeException("Failed : HTTP error code : " + urlConnection.getResponseCode());

但是,我不确定这如何与 Retrofit 一起工作,因为我一直在调用失败。 这是我用于同一服务调用的代码

@GET("search")
Call<String> getRestaurantsBySearch(@Query("entity_id") String entity_id, @Query("entity_type") String entity_type, @Query("q") String query,@Header("Accept") String accept, @Header("user-key") String userkey);

我用这个来称呼它

Call<String> call = endpoint.getRestaurantsBySearch("3","city","mumbai","application/json","9900a9720d31dfd5fdb4352700c");

所有这些调用都进入 RetroFit 中的 OnFailure 方法。 如果我在没有 HeaderParameters 的情况下发送它,它会以 403 进入 Success,因为我显然需要在某处传递 api 密钥,但我不知道如何。

@GET("search")
Call<String> getRestaurantsBySearch(@Query("entity_id") String entity_id, @Query("entity_type") String entity_type, @Query("q") String query);

我在 OnFailure 中遇到的错误是

java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 2 path $

【问题讨论】:

为您的改造实例添加一个logging interceptor,因为您的调用参数化错误 编译'com.squareup.okhttp3:logging-interceptor:3.0.0' 我使用了上面的依赖。任何想法我如何从那里去? @jamian 取决于 okhttp 的版本使用相同的版本 @jamian 你试过我的答案吗? 【参考方案1】:

在 Retrofit 1.9 和 2.0 中尝试这种类型的标头。对于 JSON 内容类型。

@Headers("Accept: application/json")
@POST("user/classes")
Call<playlist> addToPlaylist(@Body PlaylistParm parm);

您可以添加更多标题,即,

@Headers(
        "Accept: application/json",
        "User-Agent: Your-App-Name",
        "Cache-Control: max-age=640000"
    )

动态添加到标题:

@POST("user/classes")
Call<ResponseModel> addToPlaylist(@Header("Content-Type") String content_type, @Body RequestModel req);

调用你的方法,即

mAPI.addToPlayList("application/json", playListParam);

或者

每次都想通过,然后创建一个带有HTTP Interceptor的HttpClient对象:

OkHttpClient httpClient = new OkHttpClient();
        httpClient.networkInterceptors().add(new Interceptor() 
            @Override
            public com.squareup.okhttp.Response intercept(Chain chain) throws IOException 
                Request.Builder requestBuilder = chain.request().newBuilder();
                requestBuilder.header("Content-Type", "application/json");
                return chain.proceed(requestBuilder.build());
            
        );

然后添加到一个 Retrofit 对象

Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL).client(httpClient).build();

如果您使用的是 Kotlin,请删除 。否则将无法正常工作。

【讨论】:

如何动态添加值(例如,在您的示例中为 640000)?在运行时? 你必须在okhttp客户端中添加它。 我犯了在 Kotlin 中使用花括号的错误。感谢您的更新! 添加了更多方法。【参考方案2】:

你可以使用下面的

 @Headers("user-key: 9900a9720d31dfd5fdb4352700c")
 @GET("api/v2.1/search")
 Call<String> getRestaurantsBySearch(@Query("entity_id") String entity_id, @Query("entity_type") String entity_type, @Query("q") String query);

 Call<String> call = endpoint.getRestaurantsBySearch("3","city","cafes");

以上内容基于 zomato api,记录于

https://developers.zomato.com/documentation#!/restaurant/search

需要注意的是endpoint改变api/v2.1/search和Header@Headers("user-key: 9900a9720d31dfd5fdb4352700c")

还要检查您的基本网址.baseUrl("https://developers.zomato.com/")

我还用我生成的 api 密钥尝试了上述方法,它可以工作 根据 zomato 文档的建议,我的查询是 cafes

注意:我希望你有以下内容

 .addConverterFactory(ScalarsConverterFactory.create()) // for string conversion
 .build();

以及 build.gradle 文件中的以下内容

compile group: 'com.squareup.retrofit2', name: 'converter-scalars', version: '2.2.0'

编辑:

您还可以传递具有动态值的标题,如下所示

@GET("api/v2.1/search")
Call<String> getRestaurantsBySearch(@Query("entity_id") String entity_id, @Query("entity_type") String entity_type, @Query("q") String query,@Header("user-key") String userkey);

Call<String> call = endpoint.getRestaurantsBySearch("3","city","cafes","9900a9720d31dfd5fdb4352700c");

【讨论】:

【参考方案3】:

试了几次,终于找到答案了。

错误

java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 2 path $

由于解析 json 失败。

在方法调用中,我传递的是字符串而不是 POJO 类。

@Headers("user-key: 9900a9720d31dfd5fdb4352700c")
@GET("api/v2.1/search")
Call<String> getRestaurantsBySearch(@Query("entity_id") String entity_id, @Query("entity_type") String entity_type, @Query("q") String query);

我应该通过 CallString> 的类型而不是 CallData>

数据是 Pojo 类

类似的东西

@Headers("user-key: 9900a9720d31dfd5fdb4352700c")
@GET("api/v2.1/search")
Call<Data> getRestaurantsBySearch(@Query("entity_id") String entity_id, @Query("entity_type") String entity_type, @Query("q") String query);

【讨论】:

这取决于您使用的转换器类型。用于解析 json 的 Gson 转换器。或对字符串使用标量转换器。由于您没有提到其中任何一个,因此我在回答中添加了注释。调用 是可能的 使用 Kotlin,我得到错误“An Annotation argument must be a compile time constant”【参考方案4】:

据我所知,您以错误的方式传递数据。 您的方法getRestaurantsBySearch 接受最后两个参数作为标题字段,即acceptuser-key。但是在调用该方法时,您首先要传递标头。 传递您在getRestaurantsBySearch的方法签名中声明的数据

【讨论】:

你能把你在改变参数位置后尝试的代码贴出来【参考方案5】:

请看一下回复。它清楚地表明您提供的api密钥是错误的。首先,您获得了正确的 api 密钥。然后调用它会工作的请求 .

【讨论】:

以上是关于在改造中添加标题参数的主要内容,如果未能解决你的问题,请参考以下文章

KMM - 如何将改造添加到 :shared 模块 (commonMain)

在 android 中在哪里准确添加 Okhttp 和改造 proguard 规则? [复制]

JSF:向操作方法添加参数后导航规则停止工作

Android - 改造 2 - 身份验证器结果

基于mui.popover的支持多选的弹出列表组件改造以及mui.prompt添加自定义内容

sublime text 3插件改造之添加从模版新增文件到指定目录