How to write retrofit function for the following - java

How can I write a retrofit function to receive the following api call. I have only called retrofit functions where we pass parameters directly in params and not in body form-data so I don't know how to do this.
Although it's not right at all, This is what I have tried :
This is my mainActivity-
private void login(String username, String password) {
Call<User> call = student_signin.apiInterface.studentLogin("json",username, password);
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
if (response.body().getError_code() == "401") {
Toast.makeText(student_signin.this, response.body().getError_message(), Toast.LENGTH_SHORT).show();
} else if (!response.body().getU_id().isEmpty()){
Toast.makeText(student_signin.this, "user signed in successfully", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<User> call, Throwable t) {
Toast.makeText(student_signin.this,t.getMessage(),Toast.LENGTH_LONG).show();
}
});
}
This is my APIinterface class-
public interface APIinterface {
#FormUrlEncoded
#POST("login")
Call<User> studentLogin(#Query("format") String format, #Field("username") String username, #Field("password") String password);
}
This is my APIclient class-
public class APIclient {
public static final String BASE_URL = "https://www.example.com/api/xyz/";
public static Retrofit retrofit = null;
public static Retrofit getApiClient()
{
if(retrofit==null)
{
// Gson gson = new GsonBuilder().setLenient().create();
retrofit = new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build();
}
return retrofit;
}
}
And this is my model class-
public class User {
#Expose
#SerializedName("u_id")
private String u_id;
#Expose
#SerializedName("customer_id")
private String customer_id;
#Expose
#SerializedName("error_code")
private String error_code;
public String getU_id() {
return u_id;
}
public String getCustomer_id() {
return customer_id;
}
public String getError_code() {
return error_code;
}
}
Any help would be greatly appreciated and acknowledged.

#POST("/api/xyz/login")
fun getData(#Body params: JsonObject): JsonObject
client.getData(JsonObject().apply {
addProperty("advice_id", adviceId)
addProperty("content", content)
})

you can use this method to send the user name and password as pram in method getData() and revice the json as user list
#GET("/api/xyz/login")
Call<List<User>> getData(#Query("user_name") String userName,#Query("password") String password);

Related

How to solve E/error: End of input at line 1 column 1 path $ in android studio

When I try to call rest API in the android studio I get an error that:
E/error: End of input at line 1 column 1 path $
I use firebase for the database and retrofit2 library.
But when I call the values a go to the firebase database and call the onFailure in call.enqueue() method.
public class APis {
public static final String URL = "http://192.168.178.43:8081/api/";
public static userService setuser() {
return client.getClient(URL).create(userService.class);
}
}
public interface userService {
#Headers("Content-Type: application/json")
#POST("signup")
Call<userlog> adduser(#Body userlog userlog);
}
public class userlog {
#SerializedName("email")
#Expose
private String emial_;
#SerializedName("password")
#Expose
private String password_;
#SerializedName("name")
#Expose
private String name_;
public userlog() {
}
public userlog(String emial_, String password, String name_) {
this.emial_ = emial_;
this.password_ = password;
this.name_ = name_;
}
public String getEmial_() {
return emial_;
}
public void setEmial_(String emial_) {
this.emial_ = emial_;
}
public String getPassword_() {
return password_;
}
public void setPassword_(String password_) {
this.password_ = password_;
}
public String getName_() {
return name_;
}
public void setName_(String name_) {
this.name_ = name_;
}
}
public void setPassword_(String password_) {
this.password_ = password_;
}
}
private void adduser_(userlog userll) {
service = APis.setuser();
Call<userlog> call = service.adduser(userll);
call.enqueue(new Callback<userlog>() {
#Override
public void onResponse(Call<userlog> call, Response<userlog> response) {
if (response.isSuccessful()) {
Toast.makeText(getApplicationContext(), "Success", Toast.LENGTH_SHORT).show();
/* userdetails.setUserid(firebaseAuth.getUid());
userdetails.setEmail_(emailId.getText().toString());
startActivity(new Intent(SignupActivity.this, MainnewActivity.class));*/
}
}
#Override
public void onFailure(Call<userlog> call, Throwable t) {
Log.e("error", t.getMessage());
Toast.makeText(getApplicationContext(), "not Successdd", Toast.LENGTH_SHORT).show();
}
});
}
when I call "adduser_(userll)" method, I get a notification that "not Successdd".
The problem related to retrofit, i think the problem because the response of the call come as null or empty
you can create NullConverterFactory.class :
public class NullConverterFactory extends Converter.Factory {
#Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
final Converter<ResponseBody, ?> delegate = retrofit.nextResponseBodyConverter(this, type, annotations);
return new Converter<ResponseBody, Object>() {
#Override
public Object convert(ResponseBody body) throws IOException {
if (body.contentLength() == 0) return null;
return delegate.convert(body);
}
};
}
}
and add to the create of the retrofit
baseUrl(Config.URL+"/")
.client(okHttpClient)
// -----add here-------
.addConverterFactory(new NullConverterFactory())
//---------------------
.addConverterFactory(GsonConverterFactory.create())
.build()

Retrofit expecting an array not an object

Hi I am new to the Retrofit 2.0 library, I am having problems parsing some json. I have looked at some other solutions on Stackoverflow but not having much luck with my problem. I am trying to call an api from android with retrofit 2.0.But it is throwing error Expected BEGIN_ARRAY but was BEGIN_OBJECT.
Any ideas what im doing wrong?
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 2 column 2 path $
Fragment.java
ListView superListView;
static Retrofit retrofit = null;
#Override
public void onCreate (#Nullable Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
connect2();
}
private void connect2() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
HomeApiService movieApiService = retrofit.create(HomeApiService.class);
Call<List<Movie3>> call = movieApiService.popularMovies2();
call.enqueue(new Callback<List<Movie3>>() {
#Override
public void onResponse(Call<List<Movie3>> call, Response<List<Movie3>> response) {
List<Movie3> myheroList2 = response.body();
String[] oneHeroes = new String[myheroList2.size()];
for (int i2 = 0; i2 < myheroList2.size(); i2++) {
oneHeroes[i2] = myheroList2.get(i2).getTitle();
}
superListView.setAdapter(new ArrayAdapter<String>(getActivity().getApplicationContext(),
android.R.layout.simple_list_item_2, oneHeroes));
}
#Override
public void onFailure(Call<List<Movie3>> call, Throwable throwable) {
Log.e("Error: ", throwable.toString());
}
});
}
HomeApiService.java
public interface HomeApiService {
#GET("movie/test")
Call<List<Movie3>> popularMovies2 ();
}
Movie3.java
public class Movie3 {
#SerializedName("title")
private String title;
public Movie3(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}
Ok...First of all your POJO for accepting the response is not correct. This is a crucial part while accepting a response. Your POJO should look like this :
public class Result{
public boolean adult;
public String backdrop_path;
public List<int> genre_ids;
public int id;
public String original_language;
public String original_title;
public String overview;
public double popularity;
public String poster_path;
public String release_date;
public String title;
public boolean video;
public double vote_average;
public int vote_count;
}
public class Root{
public int page;
public List<Result> results;
public int total_pages;
public int total_results;
}
Where root is the class and result is another class. As you can see the response contains result as a list.
And also the HomeApiService should look like this:
public interface HomeApiService {
#GET("movie/popular?api_key=ffd597419be5a256066dc51c49bc659f")
Call<Root> popularMovies2 ();
}
Hope you got the point. Add necessary getters and setters. Normally it's easy to use a JSON to POJO online converter. Here is one: https://json2csharp.com/json-to-pojo ..... paste the response in JSON and get the POJO converted.

How do I add a JSON body to my post request using Retrofit?

I am trying to send a POST request using Retrofit library.
Here is my MarketApiCalls interface and my networking method doing the work -
public interface MarketApiCalls {
#POST("api/Search/Vendor/Multiple")
Call<String> getVendors(
#Query("take") int take,
#Query("page") int page,
#Body String json
);
}
private void initNetworking() {
String body = "[{ \"filters\": { \"VendorName\": { \"value\": [\"*\"], \"cretiria\": 0, \"type\": 5 } } }]"
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://search.myverte.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
marketApiCalls = retrofit.create(MarketApiCalls.class);
Call<String> vendorsCall = marketApiCalls.getVendors(9, 0, body);
vendorsCall.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if (!response.isSuccessful()) {
Toast.makeText(getContext(), "Not successful", Toast.LENGTH_SHORT).show();
return;
}
Log.d("response body", response.body());
}
#Override
public void onFailure(Call<String> call, Throwable t) {
}
});
}
Here is the JSON I need to attach to the POST request as a body -
[{
"filters": {
"VendorName": {
"value": ["*"],
"cretiria": 0,
"type": 5
}
}
}]
The issue is that I am getting error code 400. It does not specify that the body is missing or corrupt , just gives 400 error saying the following error -
What am I missing? I am suspicious that I am not giving the body as needed.
edit -
I have tried the following solution yet the same error occurs -
public class VendorBodyModel {
private Filters filters;
public VendorBodyModel() {
}
public VendorBodyModel(Filters filters) {
this.filters = filters;
}
public Filters getFilters() {
return filters;
}
public void setFilters(Filters filters) {
this.filters = filters;
}
public class Filters {
private VendorName vendorName;
public Filters() {
}
public Filters(VendorName vendorName) {
this.vendorName = vendorName;
}
}
public class VendorName {
private String[] value;
private int cretiria;
private int type;
public VendorName(String[] value, int cretiria, int type) {
this.value = value;
this.cretiria = cretiria;
this.type = type;
}
public String[] getValue() {
return value;
}
public void setValue(String[] value) {
this.value = value;
}
public int getCretiria() {
return cretiria;
}
public void setCretiria(int cretiria) {
this.cretiria = cretiria;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
}
public interface MarketApiCalls {
#POST("api/Search/Vendor/Multiple")
Call<String> getVendors(
#Query("take") int take,
#Query("page") int page,
#Body VendorBodyModel bodyModel
);
}
private void initNetworking() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://search.myverte.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
marketApiCalls = retrofit.create(MarketApiCalls.class);
String[] array = {"*"};
int cretiria = 5;
int type = 0;
VendorBodyModel.VendorName vendorName = new VendorBodyModel().new VendorName(array, 5, 0);
VendorBodyModel.Filters filters = new VendorBodyModel().new Filters(vendorName);
VendorBodyModel vendorBodyModel = new VendorBodyModel(filters);
Call<String> vendorsCall = marketApiCalls.getVendors(9, 0, vendorBodyModel);
vendorsCall.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if (!response.isSuccessful()) {
Toast.makeText(getContext(), "Not successful", Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(getContext(), "FUCKING SUCCESS!!!", Toast.LENGTH_SHORT).show();
Log.d("response body", response.body());
}
#Override
public void onFailure(Call<String> call, Throwable t) {
}
});
}
What am I missing?
Just simply create post model class like this:
class Body {
Filters filters;
int parameter2;
}
class Filters {
VendorName VendorName;
.......
.......
.......
}
and use it like this:
#POST("api/Search/Vendor/Multiple")
Call<String> getVendors(
#Query("take") int take,
#Query("page") int page,
#Body Body json
);
And also make sure that Body class field namings matches required namings, also dont forget that list or array is marked with [...], simple pojo {...}
Here is full body class in Kotlin:
data class Body(
#SerializedName("filters")
val filters: Filters? = Filters()
)
data class Filters(
#SerializedName("VendorName")
val vendorName: VendorName? = VendorName()
)
data class VendorName(
#SerializedName("value")
val value: List<String?>? = listOf(),
#SerializedName("cretiria")
val cretiria: Int? = 0,
#SerializedName("type")
val type: Int? = 0
)
Instead of string create JsonObject and send it as #Body JsonObject request

Not able to convert JSON to Java class (call WebApi from Android app)

im working on my school project and im new in android programming but i have some programming experiance in c# and .net.
This is my code:
public class ProizvodiAPI {
public class ProizvodiVM implements Serializable
{
public Integer proizvodID;
public String naziv;
public String sifra;
public BigDecimal cijena;
public Byte[] slikaThumb;
public String jedinicaMjere;
public String vrstaProizvoda;
}
public class ProizvodiLista implements Serializable
{
public List<ProizvodiVM> proizvodi;
}
public static void GetAllProizvode(final MyRunnable<ProizvodiLista> onSuccess)
{
RequestQueue queue = Volley.newRequestQueue(MyApp.getContext());
String url = "Proizvodi/GetProizvodiVM";
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, Config.urlApi + url,
new Response.Listener<String>()
{
#Override
public void onResponse(String response)
{
final Gson gson = MyGson.build();
final ProizvodiLista model = gson.fromJson(response, ProizvodiLista.class);
onSuccess.run(model);
}
}, new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
Toast.makeText(MyApp.getContext() , "That didn't work", Toast.LENGTH_LONG).show();
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
}
}
Program crashes here:
final ProizvodiLista model = gson.fromJson(response, ProizvodiLista.class);
Is the problem with deserializing json, if it is, shoud i change the Java class and what to change ?
Here is my C# class in Web Api:
public class Proizvodi
{
public int ProizvodID { get; set; }
public string Naziv { get; set; }
public string Sifra { get; set; }
public decimal Cijena { get; set; }
public byte[] SlikaThumb { get; set; }
public string JedinicaMjere { get; set; }
public string VrstaProizvoda { get; set; }
}
Based on the response you are receiving, it is a JSONArray and not a simple JSONObject. Deserialize it properly.

Updating class field from callback

I'm trying to connect to API using Retrofit. I need to login user and after this set "user" field which contains session key which is required to all other api calls. So I need to have it available before executing any code but I don't know how to check or block code until this field will be set. Any ideas how to do it?
public class ApiClient {
public static final String developerKey = "";
public static final String applicationKey = "";
static final String BASE_URL =
"https://secure.techfortesco.com/tescolabsapi";
public ApiService mApiService;
public User user;
public ApiClient() {
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel( RestAdapter.LogLevel.FULL )
.setEndpoint( BASE_URL )
.build();
if(mApiService == null) {
mApiService = restAdapter.create( ApiService.class );
}
}
public void login() {
mApiService.login( developerKey, applicationKey, new Callback<User>() {
#Override
public void success ( User user, Response response ) {
//code which should update user field
}
#Override
public void failure ( RetrofitError error ) {
}
} );
}
public interface ApiService {
#GET ("/restservice.aspx?command=LOGIN&email=&password=")
public void login (
#Query ("developerkey") String developerKey,
#Query ("applicationkey") String applicationKey,
Callback<User> callback );
#GET ("/restservice.aspx?command=PRODUCTSEARCH")
public void search (
#Query ("searchtext") String searchText,
#Query ("sessionkey") String sessionKey,
Callback<Pojo.SearchResult> callback);
}
}
You can try using callback:
Example:
public interface LoginCallback {
void ready();
}
And in the Activity / Fragment
public MainActivity extends Activity {
public void onCreate() {
super.onCreate();
ApiClient client = new ApiClient();
client.login(new LoginCallback() {
#Override
public void ready() {
//... do your next request in the API.
}
});
}
}
and your login method became:
public void login(final LoginCallback loginCallback) {
mApiService.login( developerKey, applicationKey, new Callback<User>() {
#Override
public void success ( User user, Response response ) {
//code which should update user field
loginCallback.ready();
}
#Override
public void failure ( RetrofitError error ) {
}
} );
}

Categories

Resources