Set dynamic base url using Retrofit 2.0 and Dagger 2
HostSelectionInterceptor
made by swankjesse
import java.io.IOException;import okhttp3.HttpUrl;import okhttp3.Interceptor;import okhttp3.OkHttpClient;import okhttp3.Request;/** An interceptor that allows runtime changes to the URL hostname. */public final class HostSelectionInterceptor implements Interceptor { private volatile String host; public void setHost(String host) { this.host = host; } @Override public okhttp3.Response intercept(Chain chain) throws IOException { Request request = chain.request(); String host = this.host; if (host != null) { //HttpUrl newUrl = request.url().newBuilder() // .host(host) // .build(); HttpUrl newUrl = HttpUrl.parse(host); request = request.newBuilder() .url(newUrl) .build(); } return chain.proceed(request); } public static void main(String[] args) throws Exception { HostSelectionInterceptor interceptor = new HostSelectionInterceptor(); OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(interceptor) .build(); Request request = new Request.Builder() .url("http://www.coca-cola.com/robots.txt") .build(); okhttp3.Call call1 = okHttpClient.newCall(request); okhttp3.Response response1 = call1.execute(); System.out.println("RESPONSE FROM: " + response1.request().url()); System.out.println(response1.body().string()); interceptor.setHost("www.pepsi.com"); okhttp3.Call call2 = okHttpClient.newCall(request); okhttp3.Response response2 = call2.execute(); System.out.println("RESPONSE FROM: " + response2.request().url()); System.out.println(response2.body().string()); }}
Or you can either replace your Retrofit instance (and possibly store the instance in a RetrofitHolder
in which you can modify the instance itself, and provide the holder through Dagger)...
public class RetrofitHolder { Retrofit retrofit; //getter, setter}
Or re-use your current Retrofit instance and hack the new URL in with reflection, because screw the rules. Retrofit has a baseUrl
parameter which is private final
, therefore you can access it only with reflection.
Field field = Retrofit.class.getDeclaredField("baseUrl");field.setAccessible(true);okhttp3.HttpUrl newHttpUrl = HttpUrl.parse(newUrl);field.set(retrofit, newHttpUrl);
Retrofit2 library comes with a @Url
annotation. You can override baseUrl
like this:
API interface:
public interface UserService { @GET public Call<ResponseBody> profilePicture(@Url String url);}
And call the API like this:
Retrofit retrofit = Retrofit.Builder() .baseUrl("https://your.api.url/"); .build();UserService service = retrofit.create(UserService.class); service.profilePicture("https://s3.amazon.com/profile-picture/path");
For more details refer to this link: https://futurestud.io/tutorials/retrofit-2-how-to-use-dynamic-urls-for-requests
This worked for me in Kotlin
class HostSelectionInterceptor: Interceptor { override fun intercept(chain: Interceptor.Chain): Response { var request = chain.request() val host: String = SharedPreferencesManager.getServeIpAddress() val newUrl = request.url().newBuilder() .host(host) .build() request = request.newBuilder() .url(newUrl) .build() return chain.proceed(request) }}
Add the interceptor to OkHttpClient builder
val okHttpClient = OkHttpClient.Builder() .addInterceptor(HostSelectionInterceptor()) .cache(null) .build()