Is it possible to use multiple baseurl in retrofit? - android

I want to use two server url using retrofit, but only one is working when I am using two base url. Please tell me how to use two base url in android.
public class APIUtils {
public static String Url1 = "http://10.0.13.46:19460";
public static String Url12 = "http://freshcamera.herokuapp.com";
public static SOService getSOService(String url) {
return RetrofitClient.getClient(url1).create(SOService.class);
}
}
SOService class
public interface SOService {
//URL 2
#FormUrlEncoded
#POST("/api/user/LoginUser")
Call<Login> Login(#Field("username") String username, #Field("password")String password, #Field("grant_type")String passwords);
}
SOService_AI class
public interface SOService_AI {
//URL 1
#FormUrlEncoded
#POST("/finalresult1")
Call<List<AIImageProcessing>> AiImageCheck(#Field("img_data") String imgdata, #Field("name")String imgName);
}

I guess what you need is changing URL at runtime to a completely different one.
For example, the following code will override the URL passed as baseUrl to retrofit object.
#GET
public Call<ResponseBody> profilePicture(#Url String url);
Note: You can't add url param to #GET and #POST. The URL must be passed to #Url.
// ERROR ( #Url cannot be used with #GET URL)
#GET("users") // or POST
public Call<Foo> getUsers(#Url String url);
// CORRECT
#GET
public Call<Foo> getUsers(#Url String fullUrl);
Checkout this tutorial for further information.

if you are working two url then you create two retrofit object. because single retrofit object work on single url.
if you want to access two your make two retofit object like below code..
public class ApiClient {
private final static String BASE_URL = "https://simplifiedcoding.net/demos/";
private final static String BASE_URL2 = "http://freshcamera.herokuapp.com";
public static ApiClient apiClient;
private Retrofit retrofit = null;
private Retrofit retrofit2=null;
public static ApiClient getInstance() {
if (apiClient == null) {
apiClient = new ApiClient();
}
return apiClient;
}
//private static Retrofit storeRetrofit = null;
public Retrofit getClient() {
return getClient(null);
}
public Retrofit getClient2() {
return getClient2(null);
}
private Retrofit getClient(final Context context) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.readTimeout(60, TimeUnit.SECONDS);
client.writeTimeout(60, TimeUnit.SECONDS);
client.connectTimeout(60, TimeUnit.SECONDS);
client.addInterceptor(interceptor);
client.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
return chain.proceed(request);
}
});
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
private Retrofit getClient2(final Context context) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.readTimeout(60, TimeUnit.SECONDS);
client.writeTimeout(60, TimeUnit.SECONDS);
client.connectTimeout(60, TimeUnit.SECONDS);
client.addInterceptor(interceptor);
client.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
return chain.proceed(request);
}
});
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL2)
.client(client.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
}
then after access like below code ..
ApiClient.getInstance().getClient();
ApiClient.getInstance().getClient2();

with Kotlin its even easier
companion object {
// init Retrofit base server instance
val redditClient by lazy { ApiService.invoke(REDDIT_BASE_URL) }
val stackClient by lazy { ApiService.invoke(STACK_BASE_URL) }
private val loggingInterceptor = HttpLoggingInterceptor().apply {
this.level = HttpLoggingInterceptor.Level.BODY
}
operator fun invoke(baseUrl: String): ApiService {
val client = OkHttpClient.Builder().apply {
/**addNetworkInterceptor(StethoInterceptor()) */
addNetworkInterceptor(loggingInterceptor)
connectTimeout(10, TimeUnit.MINUTES)
readTimeout(10, TimeUnit.MINUTES)
writeTimeout(10, TimeUnit.MINUTES)
}.build()
return Retrofit.Builder()
.client(client)
.baseUrl(baseUrl)
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
}
}
just pass the baseUrl in the invoke method

This is really easy now
Simply use Post or Get without a constant url instead accept it in a parameter and annotate that parameter with #Url
#GET
suspend fun handshakeUser(#Url url : String): Response<JsonObject>
#POST
suspend fun makePostRequest(
#Header("Authorization") token: String = getToken(),
#Url url: String,
#Body inputModel: JsonObject
): Response<JsonObject>

Related

How to solve failed connection to service?

I want to get to the service in specific URL .... I use retrofit to get it but it give me an error connection to the URL...while the URL is active in chrome.
in the code I write ??? instead to correct one ^__^ (this code is class APIClient)
and to be sure that I work in correct way I was built an api in mocky site with the same json file .... and it is work
so can any one help me please
public static final String BASE_URL = "http://111.222.1.12:0000/???/???/????/";
//database
public static final String BASE_URL2 = "http://www.mocky.io/v2/";
public static Boolean URL=true;
private static Retrofit retrofit = null;
public static Retrofit getClient(){
if (retrofit==null) {
if(URL)
{
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
else
{
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL2)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
}
return retrofit;
}
Hello you can try using my ApiClient, I'm using rxJava so you need to redesign the APIClient to your need
public class ApiClient {
private static Retrofit retrofit = null;
private static int REQUEST_TIMEOUT = 120;
private static OkHttpClient okHttpClient;
public static Retrofit getClient(Context context) {
if (okHttpClient == null)
initOkHttp(context);
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(API_PATH)
.client(okHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
private static void initOkHttp(Context context) {
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.cipherSuites(
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
.build();
OkHttpClient.Builder httpClient = new OkHttpClient().newBuilder()
.connectTimeout(REQUEST_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(REQUEST_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(REQUEST_TIMEOUT, TimeUnit.SECONDS);
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
httpClient.addInterceptor(interceptor);
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.addHeader("Accept", "application/json")
.addHeader("Request-Type", "Android")
.addHeader("Content-Type", "application/json");
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
okHttpClient = httpClient.build();
}
public static void resetApiClient() {
retrofit = null;
okHttpClient = null;
}
}
Hope this reference can help you solve your problems

Retrofit Logging Error

I am authenticating against an API EndPoint using the Password Grant Flow for OAuth2. The library I am using is Retrofit.
I get the following error:
D/OkHttp: {"error":"invalid_clientId","error_description":"ClientId should be sent."}
I would like to see exactly what API Call I am sending so I can check it for errors.. I have searched the web and found that you need to add a LoggingInterceptor, which I am doing. Still not getting the full API Call..
In my log I get a track of the headers I am sending, as well as the URL, but not the body parameters.. Is there a way to also get the body parameters in the logging?
I would like to see each parameter with its sent value..
The code with provisional credentials can be found at:
https://github.com/NVwingh84/ATTAPITest
Code that I am using is:
public class MainActivity extends AppCompatActivity {
private String grant_type = "password";
private String username = "xxxxx";
private String password = "xxxxx";
private String clientId = "xxxxx";
private String client_secret = "xxxxx";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AccessTokenRequest mytokenrequest = new AccessTokenRequest(grant_type,username,password,clientId,client_secret);
sendNetworkRequest(mytokenrequest);
}
public void sendNetworkRequest(AccessTokenRequest accessTokenRequest){
//create okhttpclientbuilder and set up logging for full logging level "Body"
OkHttpClient.Builder okhttpclientbuilder = new OkHttpClient.Builder();
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//App will only log if you are in development mode
if (BuildConfig.DEBUG){
okhttpclientbuilder.addInterceptor(loggingInterceptor);
}
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("https://api.allthingstalk.io")
.addConverterFactory(GsonConverterFactory.create())
.client(okhttpclientbuilder.build());
Retrofit retrofit = builder.build();
AccessTokenClient client = retrofit.create(AccessTokenClient.class);
Call<AccessTokenRequest> call = client.getAccessToken();
call.enqueue(new Callback() {
#Override
public void onResponse(Call call, Response response) {
Toast.makeText(MainActivity.this, "EndPoint Response", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call call, Throwable t) {
Toast.makeText(MainActivity.this, "Something went wrong", Toast.LENGTH_SHORT).show();
}
});
};
}
Try this code.
add below dependency into app level gradle file..
implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1'
and make separate class for retrofit object define and it is easy to access like below code..
public class ApiClient {
private final static String BASE_URL = "https://dog.ceo/api/breed/";
public static ApiClient apiClient;
private Retrofit retrofit = null;
public static ApiClient getInstance() {
if (apiClient == null) {
apiClient = new ApiClient();
}
return apiClient;
}
//private static Retrofit storeRetrofit = null;
public Retrofit getClient() {
return getClient(null);
}
private Retrofit getClient(final Context context) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.readTimeout(60, TimeUnit.SECONDS);
client.writeTimeout(60, TimeUnit.SECONDS);
client.connectTimeout(60, TimeUnit.SECONDS);
client.addInterceptor(interceptor);
client.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
return chain.proceed(request);
}
});
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
}

How to implement authentication with access and refresh token using retrofit in android?

I am trying to implement the token based authentication with access and refresh token. The access token expires after some limited time. Then using the refresh token it needs to be updated again. I am following this reference and this answer as well. As I am new to android I got no idea about how to implement these concepts.
This is my interface to get access token using the refresh token.
//get access Token with Refresh Token
#POST("/api/token")
Call<ResponseBody> getAccessToken(#Body JSONObject jsonObject);
This is my Retrofit Client:
public class ApiClient {
public static final String BASE_URL = "https://lit-cove-70675.herokuapp.com";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
I have no idea where and how to implement those Service Generators and Authenticator. I have to pass "Authentication"=>ACCESSTOKEN in header with every API URL.
public class ApiClient {
public static final String BASE_URL = "https://lit-cove-70675.herokuapp.com";
public <Service> Service buildApi(Class<Service> service, String accessToken) {
return new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(getOkkHttpClient(accessToken))
.build()
.create(service);
}
private OkHttpClient getOkkHttpClient(String accessToken) {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(#NonNull Interceptor.Chain chain) throws IOException {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder();
// ============= Your access token will go here ============
if(accessToken != null) {
requestBuilder.header("Access token key", accessToken);
}
return chain.proceed(requestBuilder.build());
}
});
return httpClient.build();
}
}
Please use below code to create your service:
public <S> S createService(Class<S> serviceClass, AuthToken authToken) {
final String token = "Bearer" + " " + authToken.getAceessToken();
Log.d("ServiceGenerator", "Token::::::: " + token);
httpClient.addInterceptor(chain -> {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header(KEY_AUTH_HEADER, token).header("Content-Type", "application/json");
Request request = requestBuilder.build();
return chain.proceed(request);
});
Retrofit retrofit = builder.client(httpClient.build()).build();
return retrofit.create(serviceClass);
}
Add following line to call method:
ApiService service = serviceGenerator.createService(ApiService.class, token);
Call<ResponseBody> call = service.getMovielist(id);
serviceGenerator is the class where i have defined create service method.You can declare whenever you want.

Using Interceptors to customize header in Retrofit calls

I am trying to use an Interceptor to add a header when using Retrofit. I think I have created my Interceptor in the right way but I don't know what should I do to call it and connect it with my GET Retrofit method.
This is my Interceptor:
public class HeaderInterceptor
implements Interceptor {
#Override
public Response intercept(Chain chain)
throws IOException {
Request request = chain.request();
request = request.newBuilder()
.addHeader(Constants.VersionHeader.NAME, Constants.VersionHeader.VALUE)
.addHeader("Authorization", "Bearer " + token)
.addHeader("Origin","MY URL")
.build();
Response response = chain.proceed(request);
return response;
}
}
And this is my interface:
public interface CategoryService {
#GET("/v3/projects/{projectId}/categories/")
Call<ArrayList<Category2>> getProjectCategories(#Path("projectId") String projectId);
}
I also have this client which I don't know if I should use it anymore considering that I am using an Interceptor:
public class CategoryClient {
public static final String BASE_URL = "MY URL";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
So I have this GET method getProjectCategories, where I pass the projectID and it returns the contents. What I want to know is how can I call the method using the Interceptor and be able to get the results from the request.
I was able to fix my problem by creating a method called SendNetworkRequest sending the projectId as a parameter, and inside this class I created my OkHttpClient, my Interceptor and my retrofit builder to handle everything that i needed.
private void SendNetworkRequest(String projectID) {
OkHttpClient.Builder okhttpBuilder = new OkHttpClient.Builder();
okhttpBuilder.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder newRequest = request.newBuilder().header("Authorization", "Bearer " + token);
return chain.proceed(newRequest.build());
}
});
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("MY URL")
.client(okhttpBuilder.build())
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
CategoryService category = retrofit.create(CategoryService.class);
Call<ArrayList<Category2>> call = category.getProjectCategories(projectID, token);
call.enqueue(new Callback<ArrayList<Category2>>() {
#Override
public void onResponse(Call<ArrayList<Category2>> call, Response<ArrayList<Category2>> response) {
listCategories = response.body();
listCategories.remove(response.body().size() - 1);
if (response.body().size() > 0){
add_category_layout.setVisibility(View.VISIBLE);
layout_bar.setVisibility(View.VISIBLE);
message_body.setVisibility(View.INVISIBLE);
message_title.setVisibility(View.INVISIBLE);
edit_image.setVisibility(View.INVISIBLE);
adapter2 = new CategoryAdapter2(getApplicationContext(), listCategories);
recyclerView.setAdapter(adapter2);
recyclerView.setVisibility(View.VISIBLE);
}
}
#Override
public void onFailure(Call<ArrayList<Category2>> call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
}

BaseUrl doesn't changed dynamically Dagger 2 & retrofit

I'm trying to change the baseUrl of an android app dynamically but the url doesn't changed.
I'm taking the reference of David's answer from here,the OkHttp Approach Dagger + Retrofit dynamic URL and Set dynamic base url using Retrofit 2.0 and Dagger 2, but still no luck.
Initially the app point to the urls "https://imd.com/yeddydemo/wpApp/",which is our app base url.
After doing some googling i have written the following code to change the app base url points to https://imd.com/rahudemo/wpApp/ but it doesn't works correctly:
Can anyone please point out where i'm doing wrong.Thanks in Advance:)
Method to change the base url:
public void changeUrlConfiguration(String name){
NetComponent netComponent = DaggerNetComponent.builder()
.apiModule(new ApiModule("https://imd.com/rahudemo/wpApp/"))
.appModule(new AppModule((ImdPoApp)homeActivity.getApplication()))
.storageModule(new StorageModule((ImdPoApp)homeActivity.getApplication()))
.build();
ApiStories service = netComponent.retrofit().create(ApiStories.class);
HostSelectionInterceptor interceptor = netComponent.interceptor();
interceptor.setHost("https://imd.com/rahudemo/wpApp/","8WAtp8nUEOrzSu67t9tGITEo");
}
Interceptor class
public final class HostSelectionInterceptor implements Interceptor {
private volatile String host;
private String authKey;
public void setHost(String host,String authKey) {
this.host = host;
this.authKey=authKey;
new ApiModule(host);
}
#Override public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String host = this.host;
if (host != null) {
HttpUrl newUrl = HttpUrl.parse(host);
request = request.newBuilder()
.url(newUrl)
.build();
}
return chain.proceed(request);
}
}
ApiModule
#Module
public class ApiModule {
String mBaseUrl;
HostSelectionInterceptor sInterceptor;
public ApiModule(String mBaseUrl) {
this.mBaseUrl = mBaseUrl;
}
#Provides
#Singleton
Cache provideHttpCache(Application application) {/*..*/}
#Provides
#Singleton
Gson provideGson() {/*..*/}
#Provides
#Singleton
OkHttpClient provideOkhttpClient(Cache cache, HostSelectionInterceptor hostSelectionInterceptor) {
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.addInterceptor(chain -> {
Request request = chain.request();
Request.Builder builder = request.newBuilder().addHeader("Authkey", "8WAtp8nUEOrzSu67t9tGITEo");
return chain.proceed(builder.build());
});
client.addInterceptor(hostSelectionInterceptor);
client.cache(cache);
return client.build();
}
#Provides
#Singleton
HostSelectionInterceptor provideInterceptor() {
if (sInterceptor == null) {
sInterceptor = new HostSelectionInterceptor();
}
return sInterceptor;
}
#Provides
#Singleton
Retrofit provideRetrofit(OkHttpClient okHttpClient) {
return new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(mBaseUrl)
.client(okHttpClient)
.build();
}
}
In your method pass the base url want to change to newbaseurl
public void changeUrlConfiguration(String name, String newbaseurl){
NetComponent netComponent = DaggerNetComponent.builder()
.apiModule(new ApiModule(newbaseurl))
.appModule(new
AppModule((ImdPoApp)homeActivity.getApplication()))
.storageModule(new StorageModule((ImdPoApp)homeActivity.getApplication()))
.build();
ApiStories service = netComponent.retrofit().create(A
piStories.class);
HostSelectionInterceptor interceptor = netComponent.interceptor();
interceptor.setHost(newbaseurl,"8WAtp8nUEOrzSu67t9tGITEo");
}
By Changing my interceptor & ChangeUrlConfiguration method as below i can able to change the BaseUrl
Interceptor method
#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()
.removePathSegment(0).removePathSegment(0).removePathSegment(0).addPathSegments(host).addPathSegment("wpApp").addEncodedPathSegment("api.php")
.build();
request = request.newBuilder()
.url(newUrl).addHeader("Authkey", "8WAtp8nU")
.build();
} else {
request = request.newBuilder().addHeader("Authkey", "8WAtp8nU")
.build();
}
try {
return chain.proceed(request);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
changeUrlConfiguration
public void changeUrlConfiguration(String constituencyName){
String newbaseurl="https://imdstar.com/rahuldemo/wpApp/";
hostSelectionInterceptor.setHost(newbaseurl,"8WAtp8nUEOrzSu67t9tGITEzIdgr6huIpXqo");
}

Categories

Resources