I have a scenario where I have to call an API with the same base URL, e.g. www.myAPI.com but with a different baseUrl.
I have an instance of Retrofit 2 which is built via a Builder:
return new Retrofit.Builder()
.baseUrl(FlavourConstants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(okHttpClient)
.build();
The FlavourConstants.BASE_URL looks like this:
public static final String BASE_URL = "http://myApi.development:5000/api/v1/";
For some WebRequests, I must call the same API but on others, I must call it from a completely different BaseUrl. How do I change the Retrofit instance to therefore point to a different URL during runtime?
The Retrofit instance doesn't have a .setBaseUrl or setter or anything similar as it's built via a Builder.
Any ideas?
Lucky for you Retrofit have a simple solution for that:
public interface UserManager {
#GET
public Call<ResponseBody> userName(#Url String url);
}
The url String should specify the full Url you wish to use.
Retrofit 2.4, MAY 2019
Two simple solution for this hassle are:
Hardcode the new URL, while leaving the base URL as it is:
#GET("http://example.com/api/")
Call<JSONObject> callMethodName();
Pass the new URL as an argument, while leaving the base URL as it is:
#GET
Call<JSONObject> callMethodName(#Url String url);
N.B: These methods work for GET or POST. However, this solution is only efficient if you just need to use an exception of one or two different URLs than your base URL. Otherwise, things can get a little messy in terms of code neatness.
If your project demands fully dynamically generated base URLs then you can start reading this.
Also there is a such hack in Kotlin while defining base url
e.g.
#FormUrlEncoded
#Headers("Accept: application/json")
#POST
suspend fun login(
baseUrl: String,
#Field("login") login: String,
#Field("password") password: String
#Url url: String = "$baseUrl/auth"
): ResponseAuth
It's not working. Throws:
java.lang.IllegalArgumentException: No Retrofit annotation found. (parameter #1)
The only way is suggested by Jake Wharton https://github.com/square/retrofit/issues/2161#issuecomment-274204152
Retrofit.Builder()
.baseUrl("https://localhost/")
.create(ServerApi::class.java)
class DomainInterceptor : Interceptor {
#Throws(Exception::class)
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
return chain.proceed(
request.newBuilder()
.url(
request.url.toString()
.replace("localhost", "yourdomain.com:443")
.toHttpUrlOrNull() ?: request.url
)
// OR
//.url(HttpUrl.parse(request.url().toString().replace("localhost", "yourdomain.com:443")) ?: request.url())
.build()
)
}
}
The easiest (but not the most performant) way to change the Retrofit2 base URL at runtime is to rebuild the retrofit instance with the new url:
private Retrofit retrofitInstance = Retrofit.Builder().baseUrl(FlavourConstants.BASE_URL).addConverterFactory(GsonConverterFactory.create(gson)).client(okHttpClient).build();
public void setNewBaseUrl(String url) {
retrofitInstance = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(okHttpClient).build();
}
...
retrofitInstance.create(ApiService.class);
Alternatively, if you are using OkHttp with Retrofit, you can add an OkHttp interceptor like this one when building your OkHttp client:
HostSelectionInterceptor hostInterceptor = new HostSelectionInterceptor();
hostInterceptor.setHost(newBaseUrl);
return new OkHttpClient.Builder()
.addInterceptor(hostInterceptor)
.build();
I just used the below function when i faced this problem. but i was on hurry and i believe that i have to use another and i was using "retrofit2:retrofit:2.0.2"
public static Retrofit getClient(String baseURL) {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseURL)
.addConverterFactory(GsonConverterFactory.create())
.build();
} else {
if (!retrofit.baseUrl().equals(baseURL)) {
retrofit = new Retrofit.Builder()
.baseUrl(baseURL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
}
return retrofit;
}
[Update]
I have found this link that explain the #Url that can be sent as a parameter and i believe it is more professional than my old solution.
Please find below the scenario:
interface APIService{
#POST
Call<AuthenticationResponse> login(#Url String loginUrl,[other parameters])
}
And below is the method in the class that provide the retrofit object
public static Retrofit getClient() {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl("http://baseurl.com") // example url
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
Then you can call the method as below:
APIInterface apiInterface = ApiClient.getClient2().create(ApiInterface.class);
apiInterface.login("http://tempURL.com").enqueue(......);
You should use interceptor like this:
class HostSelectionInterceptor: Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
apiHost?.let { host ->
val request = chain.request()
val newUrl = request.url.newBuilder().host(host).build()
val newRequest = request.newBuilder().url(newUrl).build()
return chain.proceed(newRequest)
}
throw IOException("Unknown Server")
}
}
You just need to change at runtime the apiHost variable (var apiHost = "example.com"). Then add this interceptor to OkHttpClient builder:
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(HostSelectionInterceptor())
.build()
Ok , if I dont remember wrong the docs of Retrofit says you can point to another URL if you just simply add in your interface servicse the full url of the ws, that is different fomr the BASE_URL in Retrofit Builder. One example...
public interface UserManager {
#GET("put here ur entire url of the service")
public Call<ResponseBody> getSomeStuff();
}
A solution is to have two distinct instance of retrofit, one for your FLAVOURED base URL and another for the other base URL.
So just define two functions :
public Retrofit getFlavouredInstance() {
return new Retrofit.Builder().baseUrl(FlavourConstants.BASE_URL).addConverterFactory(GsonConverterFactory.create(gson)).client(okHttpClient).build();
}
public Retrofit getOtherBaseUrl() {
return Retrofit.Builder().baseUrl(OTHER_BASE_URL).addConverterFactory(GsonConverterFactory.create(gson)).client(okHttpClient).build();
}
and after you just have to use the right one.
Please try the following code:
private void modify(String url) throws Exception {
Class mClass = retrofit.getClass();
Field privateField = mClass.getDeclaredField("baseUrl");
if (privateField != null) {
privateField.setAccessible(true);
System.out.println("Before Modify:MSG = " + retrofit.baseUrl().url().getHost());
privateField.set(retrofit, HttpUrl.parse(url));
System.out.println("After Modify:MSG = " + retrofit.baseUrl().url().getHost());
}
}
You can regenerate the DaggerAppComponent after changing your apiUrl it will generate a new instance of providerRetrofit with the new url
DaggerAppComponent.builder() .application(this) .build() Log.init( LogConfiguration .Builder() .tag("...") .logLevel(LogLevel.NONE) .build() )
Related
I need change the URL base in retrofit, i'm using koin to create a retrofit module on app startup and i want change this url in runtime.
I already tried change the baseUrl("http://192.168.192.168/") to baseUrl("http://")and change the url on retrofit call but my app crashs and return illegal URL error.
This is my fun to create the builder
fun createRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl("http://192.168.192.168/")//i need change this at runtime
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
}
create a bean to my module
val retrofitModule: Module = applicationContext {
bean { createRetrofit(get()) }
}
and start the koin:
startKoin(application = this,
modules = listOf(retrofitModule, ...)
)
someone can i help me with this?
you must have to add these lines in your code:
First Step:
Add the new CallAdapter RxJavaCallAdapterFactory.create() when building a Retrofit instance.
public static final String BASE_URL = "http://google.com/";
public static Retrofit getClient(String baseUrl) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
Next step:
Update the APIService for example:-> savePost(String title, String body, String userId) method to become an Observable.
public interface APIService {
#GET
Call<ResponseBody> list(#Url String url);
//or
#POST("/posts")
#FormUrlEncoded
Observable<Post> savePost(#Field("title") String title,
#Field("body") String body,
#Field("userId") long userId);
}
Final step:
When making the requests, our anonymous subscriber responds to the observable's stream which emits event.
public void sendPost(String title, String body) {
// RxJava
mAPIService.savePost(title, body, 1).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Post>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(Post post) {
showResponse(post.toString());
}
});
}
this is way you build your dynamic urls: want to learn more details full description link: Sending Data With Retrofit 2 HTTP Client for Android
and See base URL for details of how the value will be resolved against a base URL to create the full endpoint URL.
if you are doing using kotlin: follow this link. dynamic urls at Runtime with Retrofit 2
I already tried change the baseUrl("http://192.168.192.168/") to baseUrl("http://")and change the url on retrofit call but my app crashs and return illegal URL error.
You can leave it as a baseUrl if you use #URL it will overwrite the one on yout Retrofit.Builder()
You can use #URL parameter to change the endpoint dynamically.
#GET
fun getUsers(#Url String url) : Observable<UserResponse>
Hi i am trying to overide the baseUrl from one specific api call and it doesnt seem to work when using #Url as a paraemter to the api method.
Below is my Api class method
#POST
fun getUserDetails(#Body body: request, #Url authUrl : String): Single<Response<ResponseData>>
code that cals and make the request
private fun getApi(): Api {
val gson = GsonBuilder().setLenient().create()
val httpClient = myNetworkHelper.createHttpClient()
val retrofit = Retrofit.Builder()
.baseUrl("http://defaultBaseUrl")
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
return retrofit.create(Api::class.java)
}
override fun getUserDetails(someRequestData, "http://dynamic/getuserDetails): Single<Response<ResponseData>> {
return getApi().getUserDetails(body, url)
}
The above results in making a request to this url
http://defaultBaseUrl/http://dynamic/getuserDetails
Instead of:
http://dynamic/getuserDetails
I did a test in local and actually I've been able to override the base URL set in the Retrofit instance.
Here's the API:
public interface Api {
#POST
Call<Void> fakeService(#Url String url);
}
And here's the "client":
public class Main {
public static void main(String[] args) throws IOException {
// Use the HttpLogginInterceptor to check what's the real call
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(interceptor)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.foo.com/")
.client(client)
.build();
Api api = retrofit.create(Api.class);
Call<Void> call = api.fakeService("http://www.example.com");
call.execute();
}
}
The result is:
Jul 18, 2018 12:28:54 PM okhttp3.internal.platform.Platform log
INFO: --> POST http://www.example.com/ (0-byte body)
Jul 18, 2018 12:28:55 PM okhttp3.internal.platform.Platform log
INFO: <-- 200 OK http://www.example.com/ (366ms, unknown-length body)
This is the document from Retrofit #GET annotation:
#Documented
#Target(METHOD)
#Retention(RUNTIME)
public #interface GET {
/**
* A relative or absolute path, or full URL of the endpoint. This value is optional if the first
* parameter of the method is annotated with {#link Url #Url}.
* <p>
* See {#linkplain retrofit2.Retrofit.Builder#baseUrl(HttpUrl) base URL} for details of how
* this is resolved against a base URL to create the full endpoint URL.
*/
String value() default "";
}
So #Url should be placed as the first parameter, so I think this will work:
#POST
fun getUserDetails(#Url authUrl: String, #Body body: request): Single<Response<ResponseData>>
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!
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
}
Late answer but I hope it's helpful if anyone comes across this problem.
You need to add #Path notation when you want to add a variable to the api path. In your case would be:
#GET("discover/movie?api_key={api_key}")
Call<List<MoviesResponse>> movieList(#Path("api_key") String api_key);}
You should remove
?api_key={api_key}
and change from
#Header to #Query
like the following code
#GET ("discover/movie")
Call<List<MoviesResponse>> movieList(#Query("api_key") String api_key);
This works for me.
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())
}
I'm trying to perform a login action using Retrofit 2.0 using Dagger 2
Here's how I set up Retrofit dependency
#Provides
#Singleton
Retrofit provideRetrofit(Gson gson, OkHttpClient client) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson)
.client(client)
.baseUrl(application.getUrl())
.build();
return retrofit;
}
Here's the API interface.
interface LoginAPI {
#GET(relative_path)
Call<Boolean> logMe();
}
I have three different base urls users can log into. So I can't set a static url while setting up Retrofit dependency. I created a setUrl() and getUrl() methods on Application class. Upon user login, I set the url onto Application before invoking the API call.
I use lazy injection for retrofit like this
Lazy<Retrofit> retrofit
That way, Dagger injects dependency only when I can call
retrofit.get()
This part works well. I got the url set to retrofit dependency. However, the problem arises when the user types in a wrong base url (say, mywifi.domain.com), understands it's the wrong one and changes it(say to mydata.domain.com). Since Dagger already created the dependency for retrofit, it won't do again.
So I have to reopen the app and type in the correct url.
I read different posts for setting up dynamic urls on Retrofit using Dagger. Nothing really worked out well in my case. Do I miss anything?
Support for this use-case was removed in Retrofit2. The recommendation is to use an OkHttp interceptor instead.
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()
This might be late but Retrofit allows you to use dynamic URLs while making the network call itself using #Url annotation.
I am also using Dagger2 to inject the Retrofit instance in my repositories and this solution is working fine for me.
This will use the base url
provided by you while creating the instance of Retrofit.
#GET("/product/123")
fun fetchDataFromNetwork(): Call<Product>
This ignore the base url
and use the url you will be providing this call at run time.
#GET()
fun fetchDataFromNetwork(#Url url : String): Call<Product> //
Thanks to #EpicPandaForce for help. If someone is facing IllegalArgumentException, this is my working code.
public class HostSelectionInterceptor implements Interceptor {
private volatile String host;
public void setHost(String host) {
this.host = HttpUrl.parse(host).host();
}
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String reqUrl = request.url().host();
String host = this.host;
if (host != null) {
HttpUrl newUrl = request.url().newBuilder()
.host(host)
.build();
request = request.newBuilder()
.url(newUrl)
.build();
}
return chain.proceed(request);
}
}
For latest Retrofit library, you can simply use singleton instance and change it with retrofitInstance.newBuilder().baseUrl(newUrl). No need to create another instance.
Dynamic url using Retrofit 2 and Dagger 2
You are able to instantiate new object using un-scoped provide method.
#Provides
LoginAPI provideAPI(Gson gson, OkHttpClient client, BaseUrlHolder baseUrlHolder) {
Retrofit retrofit = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson)
.client(client)
.baseUrl(baseUrlHolder.get())
.build();
return retrofit.create(LoginAPI.class);
}
#AppScope
#Provides
BaseUrlHolder provideBaseUrlHolder() {
return new BaseUrlHolder("https://www.default.com")
}
public class BaseUrlHolder {
public String baseUrl;
public BaseUrlHolder(String baseUrl) {
this.baseUrl = baseUrl;
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
}
Now you can change base url via getting baseUrlHolder from the component
App.appComponent.getBaseUrlHolder().set("https://www.changed.com");
this.loginApi = App.appComponent.getLoginApi();
Please look into my workaround for Dagger dynamic URL.
Step1: Create an Interceptor
import android.util.Patterns;
import com.nfs.ascent.mdaas.repo.network.ApiConfig;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class DomainURLInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
String requestUrl = original.url().toString();
String PROTOCOL = "(?i:http|https|rtsp)://";
String newURL = requestUrl.replaceFirst(PROTOCOL, "")
.replaceFirst(Patterns.DOMAIN_NAME.toString(), "");
newURL = validateBackSlash(newURL) ? ApiConfig.BASE_URL.concat(newURL) : newURL.replaceFirst("/", ApiConfig.BASE_URL);
original = original.newBuilder()
.url(newURL)
.build();
return chain.proceed(original);
}
private boolean validateBackSlash(String str) {
if (!str.substring(str.length() - 1).equals("/")) {
return true;
}
return false;
}
}
Step 2:
add your newly created interceptor in your module
#Provides
#Singlton
DomainURLInterceptor getChangeURLInterceptor() {
return new DomainURLInterceptor();
}
step 3:
add interceptor into list of HttpClient interceptors
#Provides
#Singlton
OkHttpClient provideHttpClient() {
return new OkHttpClient.Builder()
.addInterceptor(getChangeURLInterceptor())
.readTimeout(ApiConfig.API_CONNECTION_TIMEOUT, TimeUnit.SECONDS)
.connectTimeout(ApiConfig.API_CONNECTION_TIMEOUT, TimeUnit.SECONDS)
.build();
}
step 4:
#Provides
#Singlton
Retrofit provideRetrofit() {
return new Retrofit.Builder()
.baseUrl(ApiConfig.BASE_URL) // this is default URl,
.addConverterFactory(provideConverterFactory())
.client(provideHttpClient())
.build();
}
Note: if the user has to change the Base URL from settings, remember to validate the newly created URL with below method:
public final static boolean isValidUrl(CharSequence target) {
if (target == null) {
return false;
} else {
return Patterns.WEB_URL.matcher(target).matches();
}
}
In retrofit 2.0 i want to use only one url .The url is same as base url as that of #GET in interface.I am facing the problem for getting the response.If Any one have better solution for using the whole url in #GET then please suggest the solution.
here is the code
public class RestClient {
private static ApiInterface apiInterface ;
private static String baseUrl = "here is my whole base url";
public static ApiInterface getClient() {
if (apiInterface == null) {
OkHttpClient okClient = new OkHttpClient();
okClient.interceptors().add(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return response;
}
});
Retrofit client = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverter(String.class, new ToStringConverter())
.client(okClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
apiInterface = client.create(ApiInterface.class);
Log.e("RETROFIT RESPONCE IS...", client.toString());
}
return ApiInterface ;
}
public interface ApiInterface {
#Headers("User-Agent: Retrofit2.0Tutorial-App")
#GET("here is my whole base url”)
Call<EventResult> getEvent();
}
}
With retrofit 2 is possible to use the #Url annotation. Let's assume your Retrofit configuration is
Retrofit builder = new Retrofit.Builder()
.baseUrl("http://wwww.example.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
Test r = builder.create(Test.class);
you declare your interface:
public interface Test {
#GET
Call<Example> getTest(#Url String url);
}
and for getTest you don't want to use the baseUrl you declared in the configuration. The #Url will ignore the baseUrl you declared and will use the one you provide as argument
I don't think it's possible since BaseURL is mandatory in Retrofit Builder and even you supply the builder with the full URL the builder will parse it and save only the BaseURL. I guess the reason why they do this is to keep it simple and consistent.
for reference you can see the source code here