Kharisma
Kharisma

Reputation: 107

Retrofit always response to onFailure

I'm setting up a new android project and using retrofit, my retrofit function work correctly in emulator (NOX) and postman but when I try build my app in mobile device, retrofit always get into onFailure, can anyone give me solution ? My API is published on public hosting,

This is how I call retrofit

 private APIInterface getInterfaceService() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        final APIInterface mInterfaceService = retrofit.create(APIInterface.class);
        return mInterfaceService;
    }

 private void loginInterface(final String username, final String password){
        APIInterface mApiService = this.getInterfaceService();
        Call<Response> mService = mApiService.loginRequest(username,password);
        mService.enqueue(new Callback<Response>() {
            @Override
            public void onResponse(Call<Response> call, retrofit2.Response<Response> response) {
                if(response.body().getValue()==1){
                    Toast.makeText(Login.this,"Welcome",Toast.LENGTH_SHORT).show();
                    Intent intent = new Intent(getApplicationContext(),HomePage.class);
                    startActivity(intent);
                    finish();
                }else{
                    Toast.makeText(Login.this,"Invalid Username or Password",Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call<Response> call, Throwable t) {
                Toast.makeText(Login.this,t.getMessage(),Toast.LENGTH_SHORT).show();
            }
        });
    }

My Response

 public class Response {

    @SerializedName("value")
    @Expose
    private Integer value;
    @SerializedName("result")
    @Expose
    private List<User> result = null;

    public Integer getValue() {
        return value;
    }

    public void setValue(Integer value) {
        this.value = value;
    }

    public List<User> getResult() {
        return result;
    }

    public void setResult(List<User> result) {
        this.result = result;
    }

}

User Model

 public class User {
    @SerializedName("id")
    @Expose
    private String id;
    @SerializedName("username")
    @Expose
    private String username;
    @SerializedName("password")
    @Expose
    private String password;
    @SerializedName("email")
    @Expose
    private String email;
    @SerializedName("image")
    @Expose
    private Object image;
    @SerializedName("point")
    @Expose
    private String point;
    @SerializedName("reputation")
    @Expose
    private String reputation;
    @SerializedName("role")
    @Expose
    private String role;

    public User(String id, String username, String password, String email, Object image, String point, String reputation, String role) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.email = email;
        this.image = image;
        this.point = point;
        this.reputation = reputation;
        this.role = role;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Object getImage() {
        return image;
    }

    public void setImage(Object image) {
        this.image = image;
    }

    public String getPoint() {
        return point;
    }

    public void setPoint(String point) {
        this.point = point;
    }

    public String getReputation() {
        return reputation;
    }

    public void setReputation(String reputation) {
        this.reputation = reputation;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }
}

API Interface

public interface APIInterface {
    @FormUrlEncoded
    @POST("login.php")
    Call<Response> loginRequest(@Field("username") String username,
                            @Field("password") String password);
}

I got this message from t.message 'CLEARTEXT communication to {my api url} not permitted by network security policy'

After I add this into manifest

android:usesCleartextTraffic="true"

I got this new one 'java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $'

My JSON respon is like this

{"value":1,"result":[{"id":"1","username":"username","password":"password","email":"email","image":null,"point":"0","reputation":"0","role":"2"}]}

This is my postman response

enter image description here

Upvotes: 0

Views: 1403

Answers (2)

sushildlh
sushildlh

Reputation: 9056

Things you should follow whenever you are trying to use Retrofit Library in your project.

  1. Convert your response into POJO using this Website. Need example then look out this Answer.
  2. Your BASE URL should end with '/'.

      String BASEURL = "http://www.xxxxxxxx.com/"
    
  3. When you implementing the callback of retrofit. You need to check that your response gives you 200 by checking if(response.isSuccessful()).

     mService.enqueue(new Callback<Response>() {
            @Override
            public void onResponse(Call<Response> call, retrofit2.Response<Response> response) {
            if(response.isSuccessful()){
               if(response.body().getValue()==1){
                    Toast.makeText(Login.this,"Welcome",Toast.LENGTH_SHORT).show();
                    Intent intent = new Intent(getApplicationContext(),HomePage.class);
                    startActivity(intent);
                    finish();
                }else{
                    Toast.makeText(Login.this,"Invalid Username or Password",Toast.LENGTH_SHORT).show();
                }
              }else   Toast.makeText(Login.this,response.errorBody().string(),Toast.LENGTH_SHORT).show(); // this will tell you why your api doesnt work most of time
            }
    
            @Override
            public void onFailure(Call<Response> call, Throwable t) {
                Toast.makeText(Login.this,t.getMessage(),Toast.LENGTH_SHORT).show();
            }
        });
    
  4. As I can see you are using Response class. The response has so many predefined objects and other libraries also have a name of Response. So, You have to check your imports file to cross verify that you are using your Response Object with your package name not others Response object.

  5. As in your POSTMAN, you include 9 headers. You have to find out all 9 headers retrofit examples and add them in your API interface accordingly.

Note:- Follow these things, I think you will solve your problem by yourself.

Feel free to ask any questions after correct all the above instructions.

Upvotes: 0

Mohammad Sommakia
Mohammad Sommakia

Reputation: 1833

use this site to generate a correct response class in java

your response class should be like this :

public class Response implements Serializable
{

@SerializedName("value")
@Expose
private long value;
@SerializedName("result")
@Expose
private List<Result> result = null;
private final static long serialVersionUID = -7121130042760098410L;

public long getValue() {
return value;
}

public void setValue(long value) {
this.value = value;
}

public List<Result> getResult() {
return result;
}

public void setResult(List<Result> result) {
this.result = result;
}

}
-----------------------------------com.example.Result.java-----------------------------------

package com.example;

import java.io.Serializable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Result implements Serializable
{

@SerializedName("id")
@Expose
private String id;
@SerializedName("username")
@Expose
private String username;
@SerializedName("password")
@Expose
private String password;
@SerializedName("email")
@Expose
private String email;
@SerializedName("image")
@Expose
private Object image;
@SerializedName("point")
@Expose
private String point;
@SerializedName("reputation")
@Expose
private String reputation;
@SerializedName("role")
@Expose
private String role;
private final static long serialVersionUID = 7267197789545166983L;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public Object getImage() {
return image;
}

public void setImage(Object image) {
this.image = image;
}

public String getPoint() {
return point;
}

public void setPoint(String point) {
this.point = point;
}

public String getReputation() {
return reputation;
}

public void setReputation(String reputation) {
this.reputation = reputation;
}

public String getRole() {
return role;
}

public void setRole(String role) {
this.role = role;
}

}

Upvotes: 0

Related Questions