Java-将变量传递到接口

时间:2019-04-08 01:00:01

标签: android interface retrofit

我正在构建一个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请求?

非常感谢您。

2 个答案:

答案 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);
    }
}