Я создаю приложение для 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 ();
Есть ли способ передать переменную из действия в интерфейс, чтобы сделать запрос API?
Спасибо большое.
Используя Retrofit
, вы можете вызывать API с несколькими headers
следующим образом.
@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
.
Попробуйте это и дайте мне знать ваши отзывы. Спасибо!
Как только вы получите токен, вы должны сохранить его в глобальный репозиторий, так как токен аутентификации понадобится вашему приложению для дальнейших аутентифицированных вызовов 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);
}
}