im new in retrofit and im using retrofit2 version 2.4.0 . there is my Api client code :
public class ApiClient {
public static final String BASE_URL = "https://api.coinmarketcap.com/v1/";
public static Retrofit retrofit = null;
public static Retrofit getApiClient (){
if (retrofit == null){
retrofit = new Retrofit().Builder.baseUrl(BASE_URL).
addConverterFactory(GsonConverterFactory.create()).build();
}
return retrofit;
}
}
this is my error : is not public in 'retrofit2.Retrofit' , cannot be accessed from outside
its showing me error on this part of the code : new Retrofit().Builder
You need to instantiate Retrofit like this
public class ApiClient {
public static final String BASE_URL = "https://api.coinmarketcap.com/v1/";
public static Retrofit retrofit = null;
public static Retrofit getApiClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
I had the same problem.
Use Retrofit.Builder() instead of Retrofit().Builder().
Related
I have a structure whose base url address is constantly variable. When my user changes his location in the application, I change the base url to show the closest server to him. but the retrofit client does not regenerate even though I restart the activities and change all the static variables. The only way to do this is to close the application completely and restart it.
I don't have a fixed base url. There could be 4 different locations today, 12 different locations tomorrow. so i need to find a permanent solution.
I have examined a lot in debug mode, but; When the base url changes, it never goes inside the getClient and cannot reassign the base url.
public static Retrofit retrofit = null;
// I want this address to change.
public static String baseUrl = "";
#Provides
public static Retrofit getClient() {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
#Override
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return new Date(json.getAsJsonPrimitive().getAsLong());
}
});
Gson gson = builder.create();
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.addHeader("AUTHORIZATION", "" + JWT_TOKEN)
.build();
return chain.proceed(request);
}
}).build();
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build();
return retrofit;
}
return retrofit;
}
You can use a dynamic URL in your application during runtime. Retrofit2 introduced the #Url annotation that allows us to pass a complete URL for an endpoint:
#GET
public Call<ResponseBody> profilePicture(#Url String url);
EDITED
You should create a new Retrofit instance when you want to use a new base URL.
public class ServiceGenerator {
public static String apiBaseUrl = "http://futurestud.io/api";
private static Retrofit retrofit;
private static Retrofit.Builder builder =
new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(apiBaseUrl);
private static OkHttpClient.Builder httpClient =
new OkHttpClient.Builder();
// No need to instantiate this class.
private ServiceGenerator() {
}
public static void changeApiBaseUrl(String newApiBaseUrl) {
apiBaseUrl = newApiBaseUrl;
builder = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(apiBaseUrl);
}
public static <S> S createService(Class<S> serviceClass, AccessToken token) {
String authToken = token.getTokenType().concat(token.getAccessToken());
return createService(serviceClass, authToken);
}
// more methods
// ...
}
https://futurestud.io/tutorials/retrofit-2-how-to-change-api-base-url-at-runtime-2
I used SharedPreferences to handle this problem:
#Singleton
#Provides
suspend fun getBaseUrl(preferencesManager: PreferencesManager): String {
return preferencesManager.getPrefBaseUrl()
}
#Singleton
#Provides
fun provideGsonBuilder(): Gson {
return GsonBuilder()
.setLenient()
.create()
}
#Provides
#Singleton
fun provideOkHttpClient( ) =
OkHttpClient
.Builder()
.connectTimeout(3, TimeUnit.MINUTES)
.readTimeout(3, TimeUnit.MINUTES)
.writeTimeout(3, TimeUnit.MINUTES)
.build()
#Singleton
#Provides
fun provideRetrofit(gson: Gson, okHttpClient: OkHttpClient, preferencesManager: PreferencesManager): Retrofit.Builder {
return Retrofit.Builder()
.baseUrl( preferencesManager.getPrefBaseUrl())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.client(okHttpClient)
}
#Singleton
#Provides
fun provideBlogService(retrofit: Retrofit.Builder): MyApi {
return retrofit
.build()
.create(MyApi::class.java)
}
i want fetch data from server, i have API URL like example : https://example.com/PlanController/getData/2/7k Plan, int his api url 2 is dynamic value and 7k plan is also dynamic Value. i want fetch data from retrofit method. give me some examples.
public interface APIService {
#GET("PlanController/getData")
Call<CoachListResponse> getAllData();
}
Retrofit clint
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
Gson gson = new GsonBuilder().setLenient().create();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
return retrofit;
}
}
Define service after creating the retrofit
public interface APIService {
#GET("getData/{id}/{kid}")
Call<CoachListResponse> getAllData(#Path("id") Long id, #Path("kid") String kid);
}
public class RetrofitClient {
private static APIService service;
public static Retrofit getClient(String baseUrl) {
Gson gson = new GsonBuilder().setLenient().create();
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson)).build();
}
service = retrofit.create(APIService.class);
return retrofit;
}
public static void getAllData(Callback<CoachListResponse> callback) {
Call<CoachListResponse> regionsCall = service.getAllData();
regionsCall.enqueue(callback);
}
}
, consume
RetrofitClient.getClient("https://example.com/PlanController/").getAllData(new Callback<CoachListResponse>() {
#Override
public void onResponse(Call<CoachListResponse> call, Response<CoachListResponse> response) {
CoachListResponse responseDto = response.body();
// logic
}
#Override
public void onFailure(Call<CoachListResponse> call, Throwable t) {
// logic
}
}, );
I wanted to replace only a part of the URL, and with this solution, I don't have to pass the whole URL, just the dynamic part and Your Retrofit client as it is no need to change:
public interface APIService {
#GET("PlanController/getData/{value}/{plan}")
Call<CoachListResponse> getAllData(#Path(value = "value", encoded = true) String value, #Path(value = "plan", encoded = true) String plan);
}
I am a beginner to the android. I am using Retrofit to call the API. But I would like to write the retrofit call method only once and use the same function in different API calls in my application. I try to create It's a generic method in nonactivity class and use it in my activity class.
public static generic_Retrofit_Class apiClient;
private Retrofit retrofit = null;
public static generic_Retrofit_Class getInstance() {
if (apiClient == null) {
apiClient = new generic_Retrofit_Class();
}
return apiClient;
}
public Retrofit getclient()
{
return getclient(null);
}
private Retrofit getclient(Object o) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.level(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder();
okHttpClient.readTimeout(60, TimeUnit.SECONDS);
okHttpClient.writeTimeout(60, TimeUnit.SECONDS);
okHttpClient.connectTimeout(60, TimeUnit.SECONDS);
okHttpClient.addInterceptor(interceptor);
okHttpClient.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(Constant.Baseurl)
.client(okHttpClient.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
After this code when I call this method in my Activity class it shows an error. Here is the implementation of the method in the Activity class.
private void Getstock() {
final String mid = medicineid.getText().toString().trim();
final String batch = batchno.getText().toString().trim();
if (medicineid.getText().length() != 0 && batchno.getText().length() != 0) {
App_Interfaces app_interfaces = (App_Interfaces) new generic_Retrofit_Class().getclient().create(App_Interfaces.class);
Map<String, String> mapdata = new HashMap<>();
mapdata.put("mid", mid);
mapdata.put("batch", batch);
final Call<Response> getstock_call = app_interfaces.getstock(mapdata);
getstock_call.enqueue(new Callback<Response>() {
#Override
public void onResponse(Call<Response> call, Response<Response> response) {
if (response.isSuccessful() && response.body() != null && response != null) {
String jsonresponse = response.body().toString();
parseStockData(jsonresponse);
System.out.print(jsonresponse);
return;
}
}
#Override
public void onFailure(Call<Response> call, Throwable t) {
}
});
}
Here is the error
java.lang.IllegalArgumentException: 'retrofit2.Response' is not a valid response body type. Did you mean ResponseBody?
for method App_Interfaces.getstock
here is my Interface Code
public interface get_stock
{
#GET("/getstock")
Call<Response> getstock(#QueryMap Map<String, String> options);
}
Welcome to SO
Change the getClient method code as
public class YOUR_CLASS{
private static YOUR_API_INTERFACE retrofit = null;
public static YOUR_API_INTERFACE getClient() { // no need to pass the object params
if(retrofit == null){
//you client code same as you written in question
retrofit = new Retrofit.Builder()
.baseUrl(Constant.Baseurl)
.client(okHttpClient.build()) //okHtttpClient from your client code
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit.create(YOUR_API_INTERFACE.class);
}
}
Now, you can easily access the retrofit api interface by YOUR_CLASS.getClient(). This will return your Retrofit Interface
Your Retrofit Interface with declare method should be like this
public interface YOUR_API_INTERFACE {
#GET("your api name")
Call<YOUR_POJO> yourApi();
}
In your activity/fragment class you can access the yourApi method as
YOUR_CLASS.getClient().yourApi();
I'm developing an application that uses Retrofit2 to upload some photos to a server, this is my code:
public static class NetworkClient {
private static final String BASE_URL = "http://myServer/";
private static Retrofit retrofit;
public static Retrofit getRetrofitClient(Context context) {
if (retrofit == null) {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(JacksonConverterFactory.create())
.build();
}
return retrofit;
}
}
public interface UploadAPIs {
#Multipart
#POST("tools/index.php/testUpload/do_upload")
Call<SimpleAdapter> uploadAttachment(#Part MultipartBody.Part filePart);
}
but when I try I get the following error:
com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class android.widget.SimpleAdapter]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: java.io.InputStreamReader#a0717cf; line: 1, column: 2]
I have JSON file like this http://androiddocs.ru/api/friends.json
{
"data":"dbfriends",
"friends": [{"id":"1","name":"Andrew","city":"Moscow","contacts":{"mobile":"+7 0000000","email":"andrew#androiddocs.ru","skype":"andrew"}}, {"id":"2","name":"Ivan","city":"Kiev","contacts":{"mobile":"+38 0000000","email":"ivan#androiddocs.ru","skype":"ivan"}}]
}
my retrofit interface
public interface Friends_API {
String BASE_URL = " http://androiddocs.ru/api/";
#GET("friends.json") Call<Friends> getFriends();
class Factory {
private static Friends_API service;
public static Friends_API getInstance(){
if (service == null) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build();
service = retrofit.create(Friends_API.class);
return service;
} else {
return service;
}
}
}
}
POJO file generated by http://www.jsonschema2pojo.org/
and my code to get data value and:
Friends_API.Factory.getInstance().getFriends().enqueue(new Callback<Friends>() {
#Override
public void onResponse(Call<Friends> call, Response<Friends> response) {
String getData = response.body().getData();
}
#Override
public void onFailure(Call<Friends> call, Throwable t) {
}
}
i can't understood how i can get value: id, name, city...
thanks for help!
You can get the data from retrieved response using:
Friends friends = response.body();
And then you can retrieve the List<Friend> using friends.getFriends() object. Now you can iterate through this list of friends and can get id,name, city or contact details.