我正在构建一个Android应用程序,并且正在使用Retrofit从API检索数据。在这个程序中,我必须打3个电话。第一个工作正常。第一个的代码如下。我上一堂课
public class APIClient {
private static Retrofit retrofit = null;
static Retrofit getClient(){
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
retrofit = new Retrofit.Builder()
.baseUrl("https://api_app.com")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit;
}
}
我也有这个界面
@Headers({
"AppId: 3a97b932a9d449c981b595",
"Content-Type: application/json",
"appVersion: 5.10.0",
"apiVersion: 3.0.0"
})
@POST("/users/login")
Call<MainUserLogin> logInUser(@Body LoginBody loginBody);
活动的代码是这个
call.enqueue(object : Callback<MainUserLogin> {
override fun onResponse(call: Call<MainUserLogin>, response: Response<MainUserLogin>) {
if (response.code().toString().equals("200")){
val resource = response.body()
bearerToken = resource.session.bearerToken
if (bearerToken.isNotEmpty() && bearerToken.isNotBlank()){
val sharedPreferences = getSharedPreferences("Settings", Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
editor.putString("bearerToken", bearerToken)
editor.commit()
BearerToken.bearerToken = bearerToken
val i = Intent(this@LoginActivity, UserAccountsActivity::class.java)
i.putExtra("bearerToken", bearerToken)
startActivity(i)
}else{
Toast.makeText(applicationContext, "Please try again.", Toast.LENGTH_LONG).show()
}
}else{
println("edwedw "+response.errorBody().string())
Toast.makeText(applicationContext, "Incorrect email address or password. Please check and try again.", Toast.LENGTH_LONG).show()
}
}
override fun onFailure(call: Call<MainUserLogin>, t: Throwable) {
call.cancel()
}
})
此通话正常。 通过这个电话,我得到了一个令牌。问题是我必须将此令牌作为标头传递才能进行第二次调用。因此,第二个呼叫将是这样。
@Headers({
"AppId: 3a97b932a9d449c981b595",
"Content-Type: application/json",
"appVersion: 5.10.0",
"apiVersion: 3.0.0",
"Authorization: "+***Token***
})
@GET("/products")
Call<MainUserLogin> getUseraccounts ();
是否可以将变量从Activity传递到接口以发出Api请求?
非常感谢您。
答案 0 :(得分:1)
使用Retrofit
可以如下调用具有多个headers
的API
@GET("/products")
Call<MainUserLogin> getUseraccounts(@Header("AppId") String appId, @Header("Content-Type") String contentType, @Header("appVersion") String appVersion, @Header("apiVersion") String apiVersion, @Header("Authorization") String token);
代替
@Headers({
"AppId: 3a97b932a9d449c981b595",
"Content-Type: application/json",
"appVersion: 5.10.0",
"apiVersion: 3.0.0",
"Authorization: "+***Token***
})
@GET("/products")
Call<MainUserLogin> getUseraccounts ();
这个。调用getUseraccounts
方法时,可以解析从上一个endpoint
创建的令牌。
尝试一下,让我知道您的反馈。谢谢!
答案 1 :(得分:1)
收到令牌后,您应将此令牌保存在global repository中,因为身份验证令牌是应用程序进行进一步身份验证的api调用所必需的。
然后,定义一个AuthorizationHeaderInterceptor
,它将扩展okhttp3.Interceptor
。覆盖此拦截器的intercept
方法,将身份验证令牌添加到您的请求中。
@Override
public Response intercept(@NonNull Chain chain) {
return completeRequest(chain);
}
private Response completeRequest(@NonNull Interceptor.Chain chain) {
AuthToken authToken = authTokenRepository.get();
Request.Builder requestBuilder = chain.request().newBuilder();
if (authToken != null && chain.request().header(Authorization.NAME) == null) {
requestBuilder.addHeader(Authorization.NAME, Authorization.getValue(authToken.getIdToken()));
}
Request request = requestBuilder.build();
try {
return chain.proceed(request);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
构建okhttpClient时可以添加拦截器。
okHttpClientBuilder.addInterceptor(new AuthorizationHeaderInterceptor(authTokenRepository))
请注意,Authorization
类是简单的便捷类,它封装了授权标头名称和值格式。
public class Authorization {
public static final String NAME = "Authorization";
@NonNull
public static String getValue(@NonNull String accessToken) {
return String.format("Bearer %s", accessToken);
}
}