Null Response fron "http" API using retrofit - android

I'm using retrofit to connect APIs. It is working fine when fetching data from https API but getting response "Null" and error body response "okhttp3.ResponseBody$1#174390c" when fetching data from http API.
Here is the Retrofit client class:
public static Retrofit getSClient(String baseUrl) {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
}
return retrofit;
}
Here is the Apiservice Class:
#GET("Mobile/OperatorFetch?")
Call<String>getOperatorDetails(#Query("apimember_id")String apiMemberId,
#Query("api_password")String apiPassword,
#Query("Mobileno")String mobileNumber);
Here is the ApiUtils Class:
public static ApiService getSApiService(){
return RetrofitClient.getSClient(PLAN_URL).create(ApiService.class);
}
Here is my network request method from Repository class:
private void fetchOperator(String apiId, String apiPassword, String mobile) {
ApiService apiService = ApiUtills.getSApiService();
apiService.getOperatorDetails(apiId, apiPassword, mobile)
.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if (response.isSuccessful() && response.body() != null){
Log.e(TAG,"Operator fetch successful: " + response.body().toString());
}else {
Log.e(TAG,"Operator fetch failed: " + response.errorBody().toString());
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG,"Fetch operator failed" + t.getMessage());
}
});
}
Getting response from Post Man

Related

I keep connection failed error in my "onFailure" method

I'm using retrofit object to call my API but I keep getting
"java.net.ConnectException: Failed to connect to
api.backtory.com/185.105.185.244:443"
in my onFailure method
I have set the title using #Headers
I have added INTERNET permission to my manifests
I have added the gson-converter library and retrofit as well
public class RegisterUserController {
public void start(User user){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ChatRoomAPI.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
ChatRoomAPI chatRoomAPI = retrofit.create(ChatRoomAPI.class);
Call<User> call = chatRoomAPI.registerUser(user);
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
Log.d("TAG" , "onResponse" + response.code());
}
#Override
public void onFailure(Call<User> call, Throwable t) {
Log.d("TAG" , "onFailure" + t.getCause()); //
}
});
}
}

How to POST with RxJava 2 + Retrofit 2?

This question may sound like a no-brainer but I'm having a hardtime.
I can do the post with retrofit 2 this way:
class RetrofitClient {
private static Retrofit retrofit = null;
static Retrofit getClient(String baseUrl) {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
Api service interface:
#POST("postsInit")
#FormUrlEncoded
Call<InitPost> postInit(
#Field("appVersion") String versionName,
#Field("appId") String applicationId,
);
And finally:
apiService.postInit(versionName, applicationId).enqueue(new Callback<InitPost>() {
#Override
public void onResponse(#NonNull Call<InitPost> call, #NonNull Response<InitPost> response) {
if (response.isSuccessful()) {
Timber.d("post submitted to API");
getInitResponse();
}
}
#Override
public void onFailure(#NonNull Call<InitPost> call, #NonNull Throwable t) {
if (call.isCanceled()) {
Timber.e("Request was aborted");
} else {
Timber.e("Unable to submit post to API.");
}
}
});
How can I convert this to RxJava 2 ? I've already implemented the converter factory but there is no info on the internet for using rxJava 2 and retrofit 2 together.
Converting your call in RxJava code:-
apiService.postInit(versionName, applicationId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.unsubscribeOn(Schedulers.io())
.subscribe(new Subscriber<InitPost>() {
#Override
public void onSubscribe(Subscription s) {
}
#Override
public void onNext(InitPost initPost) {
}
#Override
public void onError(Throwable t) {
}
#Override
public void onComplete() {
}
});
}
Post service interface:
#POST("postsInit")
#FormUrlEncoded
Observable<InitPost> postInit(
#Field("appVersion") String versionName,
#Field("appId") String applicationId,
);

Reusing Retrofit method

I have a method that makes a call to my server using Retrofit:
public class MainActivity extends AppCompatActivity {
// ... activity methods here, removed for simplicity ...
// Used to subscribe to a user given their userId
public void subscribeToUser(int userId) {
final ApiInterface apiService = ApiClient.createService(ApiInterface.class);
Call<BasicResponse> call = apiService.subscribe(userId);
call.enqueue(new Callback<BasicResponse>() {
#Override
public void onResponse(Call<BasicResponse> call, Response<BasicResponse> response) {
if (response.isSuccessful()) {
Toast.makeText(MainActivity.this, "Success", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this, "Failed", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<BasicResponse> call, Throwable t) {
Log.e(TAG, t.toString());
}
});
}
}
I now need to use this same method (subscribeToUser()) in another activity, but it doesn't make sense to copy and paste the method into the other activity. Then I would just have the same code twice.
So can I put the method into one place and have it let the activities know whether or not the call succeeded or failed? How should I organize this?
Here is my ApiClient.java class:
public class ApiClient {
public static final String API_BASE_URL = "http://www.website.com/api/";
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient.build()).build();
return retrofit.create(serviceClass);
}
public static <S> S createService(Class<S> serviceClass, final String authToken) {
if (authToken != null) {
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", "Bearer " + authToken)
.method(original.method(), original.body());
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
}
OkHttpClient client = httpClient.build();
Retrofit retrofit = builder.client(client).build();
return retrofit.create(serviceClass);
}
}
And here is my ApiInterface.java class:
public interface ApiInterface {
#FormUrlEncoded
#POST("subscribe")
Call<BasicResponse> subscribe(#Field("userId") Integer userId);
}
Thanks.
In my opinion, createService(ApiInterface.class) shouldn't be invoked multiple times. It's not necessary and slows down your application. You can try to create UserService with singleton pattern as below:
public class UserService {
private UserService userService;
final ApiInterface apiService;
//Contructor private to prevent init object from outside directly.
private UserService() {
apiService = ApiClient.createService(ApiInterface.class);
}
//use this method when you need to use UserService
public static UserService getInstance() {
if(userService == null) {
userService = new UserService();
}
}
// Used to subscribe to a user given their userId
public void subscribeToUser(int userId, ServiceCallBack serviceCallBack) {
final ApiInterface apiService = ApiClient.createService(ApiInterface.class);
Call<BasicResponse> call = apiService.subscribe(userId);
call.enqueue(new Callback<BasicResponse>() {
#Override
public void onResponse(Call<BasicResponse> call, Response<BasicResponse> response) {
if (response.isSuccessful()) {
Toast.makeText(MainActivity.this, "Success", Toast.LENGTH_LONG).show();
serviceCallBack.successful(response);
} else {
Toast.makeText(MainActivity.this, "Failed", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<BasicResponse> call, Throwable t) {
Log.e(TAG, t.toString());
serviceCallBack.fail(t);
}
});
}
//this is callback interface, help you know whether success from outside.
interface ServiceCallBack {
void successful(Response response);
void fail(Throwable t);
}
}
How to use:
UserService.getInstance(1, new ServiceCallBack(){
#Override
public void successful(Response response) {
//process successful
}
#Override
public void fail(Throwable t) {
//process fail
}
});
Now you can put all methods relate to User api to UserService class to reuse.

POST with Retrofit

I am creating a simple log-in/register app, consuming predefined JSON-structured data. So far I have created the GET endpoint (using retrofit)
public interface RetrofitGet {
#GET("----")
Call<User> getUserDetails();
}
EDIT: the POST endPoint:
#POST("----")
Call<User> postUserDetails();
Then I have a method, taking the entered JSON-like data and set the data as text of 2 of the fields:
private void getUser() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitGet service = retrofit.create(RetrofitGet.class);
Call<User> call = service.getUserDetails();
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Response<User> response, Retrofit retrofit) {
try {
input_email.setText(response.body().getEmail());
input_pass.setText(response.body().getPassword());
} catch (Exception e) {
Log.d("onResponse", "There is an error");
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable t) {
Log.d("onFailure", t.toString());
}
});
What I am trying to do now is to define the POST endpoint, in order to be able the data to be generated from the app (to be taken from the register form), posted on the server, and then handled in the login.
EDIT:
The method, consuming the POST endpoint so far:
private void postUser() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitPost service = retrofit.create(RetrofitPost.class);
Call<User> call = service.postUserDetails();
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Response<User> response, Retrofit retrofit) {
try {
emailRegister.getText().toString();
passRegister.getText().toString();
} catch (Exception e) {
Log.d("onResponse", "There is an error");
e.printStackTrace();
}
}
So, I have the data, entered by the user on Register, but I don't see it stored in the server and cannot handle it in the Login part.
Any help would be appreciated,
Thanks!
#POST("----")
Call<CommonBean> comment(#Body PostComment comment);
and the PostComment:
public class PostComment {
private int pcOrdersId;
private int pcStar;
private String pcComment;
public PostComment(int pcOrdersId, int pcStar, String pcComment) {
this.pcOrdersId = pcOrdersId;
this.pcStar = pcStar;
this.pcComment = pcComment;
}
}
others on different with 'GET'

Retrofit Can't return Data

i'm probebly doing something wrong,
i'm trying to figure out how to use retrofit, so for now i'm calling back just a general ResponseBody, and not yet parsing anything, (just a simple http get)
but retrofit can't get the data, what am i doing wrong ? >
my Retrofit API >
public interface retrofitApi {
String baseUrl = "http://localhost:3003/";
#GET("api/radBox/getDegrees")
Call<ResponseBody> getCallData();
class Factory {
private static retrofitApi service;
public static retrofitApi getInstance() {
if (service == null) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
service = retrofit.create(retrofitApi.class);
return service;
} else {
return service;
}
}
}
}
and in my main Activity i put >
retrofitApi.Factory.getInstance().getCallData().enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.d("myLogs", "log: " + response);
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d("myLogs", "failed to Retrive Data");
}
});
I think your problem is caused by using "localhost". Looks like you are using your phone to connect to phone's 3003 port. Exchange the localhost to your Server IP to give a try.
I copy all your code in my retrofit project, I exchange the URL, everything is working well on my side, meaning your retrofit code has no problem.
Try use instead ResponseBody your model (for me it WeatherModel) which must will return from server.
Like this
String baseUrl = "http://api.openweathermap.org/";
#GET("data/2.5/weather")
Call<WeatherModel> getCallData(#Query("q") String q, #Query("lang") String lang,
#Query("appid") String appid);
and put in MainActivity like this
retrofitApi.Factory.getInstance()
.getCallData("Taganrog,ru", "ru", "bde41abf61e82b6209a544a5ea2ddb76")
.enqueue(new Callback<WeatherModel>() {
#Override
public void onResponse(Call<WeatherModel> call, Response<WeatherModel> response) {
Log.d("myLogs", "log: " + response);
}
#Override
public void onFailure(Call<WeatherModel> call, Throwable t) {
Log.d("myLogs", "log: " + "failed to Retrive Data");
}
});
It's works fine for me

Categories

Resources