Search code examples
android-annotations

Better way to handle common headers and root?


Is there a better way to set bearer like a global config rather than setting it each time like this:

restClient.setBearerAuth(TokenStore.getInstance().getLocalToken());              

The same for root url, is there a global config rather than setting it like this:

String root= Application.getInstance().getApplicationContext().getResources().getString(R.string.whiteLabelApiBaseHost)
restClient.setRootUrl(root);            

In retrofit, there is something like this:

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Application.getInstance().getApplicationContext()
                            .getResources().getString(R.string.whiteLabelApiBaseHost))

Any idea?


Solution

  • To set root url you can use this method, substituting the string with a constant

    @Rest(rootUrl = "http://company.com/ajax/services", converters = { MappingJackson2HttpMessageConverter.class }, interceptors = MyAuthInterceptor.class)
    public interface MyRestClient {
        @Get("/events")
        EventList getEvents();
    }
    

    Note that we set an interceptor in the arguments of the @Rest annotation. So create a class like this:

    @EBean(scope = Scope.Singleton)
    public class MyAuthInterceptor implements ClientHttpRequestInterceptor {
    
    @Bean
    MyAuthStore authStore;
    
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        HttpHeaders headers = request.getHeaders();
        HttpAuthentication auth = new HttpBasicAuthentication(authStore.getUsername(), authStore.getPassword());
        headers.setAuthorization(auth);
        return execution.execute(request, body);
        }
    }
    

    Now before executing request MyAuthInterceptor.intercept() is called and you can set your authentication data as you prefer

    In your main build.gradle file you can add inside android element

    productFlavors {
    
        development {
            buildConfigField "String", "SERVICE_URL_BASE", "\"dev.xxx.com/rest\""
        }
    
        test {
            buildConfigField "String", "SERVICE_URL_BASE", "\"test.xxx.com/rest\""
        }
    
        production {
            buildConfigField "String", "SERVICE_URL_BASE", "\"production.xxx.com/rest\""
        }
    }
    

    Then in your @Rest annotation you can use this code to get current flavor value:

    @Rest(rootUrl = "https://" + BuildConfig.SERVICE_URL_BASE)
    

    Now you can select what build variant to use (variant = flavor + buildType) to use desired value. To select variant you can use corresponding view, it should be present on the left of android studio.

    This technique is useful to avoid creating flavor's package tree only to use different variabiles