Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing API Key in Retrofit 2 - Android Studio

I am developing an android APP where I am using Retrofit 2 and The Movie Database API 3. I am unsure on how to pass the API key correctly, I tried to use @Header annotation and tried to add new Interceptor to the httpClient and still nothing.

I researched as much as I could, but nothing helped. Here is what I have for the API interface:

public interface MoviesAPIService {
@GET("discover/movie?api_key={api_key}")
Call<List<MoviesResponse>> movieList(@Header("api_key") String api_key);}

Here is what I have in my activity (its a fragment in a ViewPager btw):

    @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.movies_fragment, container, false);

    movieListView = (ListView) rootView.findViewById(R.id.movieListView);

    final OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

    OkHttpClient client = httpClient.build();

    final Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(client)
            .build();


    MoviesAPIService moviesAPIService = retrofit.create(MoviesAPIService.class);
    Call<List<MoviesResponse>> call = moviesAPIService.movieList(apiKey);
    call.enqueue(new Callback<List<MoviesResponse>>() {
        @Override
        public void onResponse(Call<List<MoviesResponse>> call, retrofit2.Response<List<MoviesResponse>> response) {
            Log.d(TAG, "onResponse: " + response.body());
        }

        @Override
        public void onFailure(Call<List<MoviesResponse>> call, Throwable t) {

        }
    });
    return rootView;
}

I got many different errors, depending on what I am testing, and with this code, i am currently getting this:

URL query string "api_key={api_key}" must not have replace block. For dynamic query parameters use @Query.

I am quite a beginner when it comes to APIs so maybe I am missing something. Thank you for any help!

like image 723
user6828332 Avatar asked Feb 27 '17 17:02

user6828332


2 Answers

All the above approaches are right but if the query param is the api key then you have to add that in your each endPoint manually that sound's bad ... we can do it in single time and no need to add api key in your query param every time. You can do that by adding a new request interceptor to the OkHttpClient. Intercept the actual request and get the HttpUrl. The http url is required to add query parameters since it will change the previously generated request url by appending the query parameter name and its value.

override fun getOkHttpClientBuilder(): OkHttpClient.Builder {
        val okHttpBuilder = super.getOkHttpClientBuilder()
        okHttpBuilder.addInterceptor { chain ->
            val request = chain.request().newBuilder()
                val originalHttpUrl = chain.request().url
                val url = originalHttpUrl.newBuilder().addQueryParameter("api_key", "your api key value").build()
                request.url(url)
            val response = chain.proceed(request.build())
            return@addInterceptor response
        }
        return okHttpBuilder
    }
like image 144
VishalJha Avatar answered Sep 19 '22 16:09

VishalJha


Extending @VishalJha answer:

fun create(): MyApiInterface {
    val client = OkHttpClient.Builder()
        .addInterceptor { chain -> return@addInterceptor addApiKeyToRequests(chain) }
        .build()
    return Retrofit.Builder()
        .baseUrl("your_url")
        .client(client)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(MyApiInterface::class.java)
}

private fun addApiKeyToRequests(chain: Interceptor.Chain): Response {
    val request = chain.request().newBuilder()
    val originalHttpUrl = chain.request().url
    val newUrl = originalHttpUrl.newBuilder()
        .addQueryParameter("api_key", "my_api_key").build()
    request.url(newUrl)
    return chain.proceed(request.build())
}
like image 25
gustavoknz Avatar answered Sep 18 '22 16:09

gustavoknz