[android] Send Post Request with params using Retrofit

I'm trying unsuccessfully to consume an API on Android using Retrofit library but while using POSTMAN I can see the expected results.

POSTMAN SETTING

  • The api url (base+controller)

  • HTTP Method set to POST

  • Clicked the from-data or x-www-form-urlencoded

  • Then i pass the two params on the key/value fields.

ANDROID RETROFIT SETTING

@POST("/GetDetailWithMonthWithCode")
void getLandingPageReport(@Query("code") String code,
                          @Query("monthact") String monthact,
                          Callback<LandingPageReport> cb);

@FormUrlEncoded
@POST("/GetDetailWithMonthWithCode")
void getLandingPageReport(@Field("code") String code,
                          @Field("monthact") String monthact,
                          Callback<LandingPageReport> cb);

None of this options works. But am getting {} as result.

UPDATE

Same settings by using the standard HttpClient(and HttpPost) class works fine.

HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);

List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
urlParameters.add(new BasicNameValuePair("code", "testcode"));
urlParameters.add(new BasicNameValuePair("monthact", "feb-2015"));

post.setEntity(new UrlEncodedFormEntity(urlParameters));

HttpResponse response = client.execute(post);

Why I can't do this request and get the correct response in Retrofit?

UPDATE 2

@POST("/GetDetailWithMonthWithCode")
void getLandingPageReport(@Query("code") String code,
                          @Query("monthact") String monthact,
                          Callback<List<LandingPageReport>> cb);

@FormUrlEncoded
@POST("/GetDetailWithMonthWithCode")
void getLandingPageReport(@Field("code") String code,
                          @Field("monthact") String monthact,
                          Callback<List<LandingPageReport>>> cb);

After playing around I think I've found the source of the problem. I've updated my retrofit code to receive List<LandingPageReport>. But now this error occur

retrofit.RetrofitError: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

The reason is that i consume 2 api's (webapi and wcf). All my other json response are arrays of objects. [{},{}] but in this call I've received this

{
  "GetDetailWithMonthWithCodeResult": [
     {
        "code": "test",
        "field1": "test",
     }
   ]
}

But still I can't manage to parse the response.

This question is related to android post retrofit

The answer is


You should create an interface for that like it is working well

public interface Service {
    @FormUrlEncoded
    @POST("v1/EmergencyRequirement.php/?op=addPatient")
    Call<Result> addPerson(@Field("BloodGroup") String bloodgroup,
           @Field("Address") String Address,
           @Field("City") String city, @Field("ContactNumber") String  contactnumber, 
           @Field("PatientName") String name, 
           @Field("Time") String Time, @Field("DonatedBy") String donar);
}

or you can visit to http://teachmeandroidhub.blogspot.com/2018/08/post-data-using-retrofit-in-android.html

and youcan vist to https://github.com/rajkumu12/GetandPostUsingRatrofit


build.gradle

      compile 'com.google.code.gson:gson:2.6.2'

      compile 'com.squareup.retrofit2:retrofit:2.1.0'// compulsory

      compile 'com.squareup.retrofit2:converter-gson:2.1.0' //for retrofit conversion

Login APi Put Two Parameters

    {
        "UserId": "1234",
        "Password":"1234"
    }

Login Response

    {
        "UserId": "1234",
        "FirstName": "Keshav",
        "LastName": "Gera",
        "ProfilePicture": "312.113.221.1/GEOMVCAPI/Files/1.500534651736E12p.jpg"
    }

APIClient.java

    import retrofit2.Retrofit;
    import retrofit2.converter.gson.GsonConverterFactory;

    class APIClient {

        public static final String BASE_URL = "Your Base 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;
        }
    }

APIInterface interface

    interface APIInterface {

        @POST("LoginController/Login")
        Call<LoginResponse> createUser(@Body LoginResponse login);
    }

Login Pojo

    package pojos;

    import com.google.gson.annotations.SerializedName;

    public class LoginResponse {


        @SerializedName("UserId")
        public String UserId;
        @SerializedName("FirstName")
        public String FirstName;
        @SerializedName("LastName")
        public String LastName;
        @SerializedName("ProfilePicture")
        public String ProfilePicture;
        @SerializedName("Password")
        public String Password;
        @SerializedName("ResponseCode")
        public String ResponseCode;
        @SerializedName("ResponseMessage")
        public String ResponseMessage;

        public LoginResponse(String UserId, String Password) {
            this.UserId = UserId;
            this.Password = Password;
        }

        public String getUserId() {
            return UserId;
        }

        public String getFirstName() {
            return FirstName;
        }

        public String getLastName() {
            return LastName;
        }

        public String getProfilePicture() {
            return ProfilePicture;
        }

        public String getResponseCode() {
            return ResponseCode;
        }

        public String getResponseMessage() {
            return ResponseMessage;
        }
    }

MainActivity

    package com.keshav.retrofitloginexampleworkingkeshav;

    import android.app.Dialog;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;

    import pojos.LoginResponse;
    import retrofit2.Call;
    import retrofit2.Callback;
    import retrofit2.Response;
    import utilites.CommonMethod;

    public class MainActivity extends AppCompatActivity {

        TextView responseText;
        APIInterface apiInterface;

        Button loginSub;
        EditText et_Email;
        EditText et_Pass;
        private Dialog mDialog;
        String userId;
        String password;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            apiInterface = APIClient.getClient().create(APIInterface.class);

            loginSub = (Button) findViewById(R.id.loginSub);
            et_Email = (EditText) findViewById(R.id.edtEmail);
            et_Pass = (EditText) findViewById(R.id.edtPass);

            loginSub.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (checkValidation()) {
                        if (CommonMethod.isNetworkAvailable(MainActivity.this))
                            loginRetrofit2Api(userId, password);
                        else
                            CommonMethod.showAlert("Internet Connectivity Failure", MainActivity.this);
                    }
                }
            });
        }

        private void loginRetrofit2Api(String userId, String password) {
            final LoginResponse login = new LoginResponse(userId, password);
            Call<LoginResponse> call1 = apiInterface.createUser(login);
            call1.enqueue(new Callback<LoginResponse>() {
                @Override
                public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
                    LoginResponse loginResponse = response.body();

                    Log.e("keshav", "loginResponse 1 --> " + loginResponse);
                    if (loginResponse != null) {
                        Log.e("keshav", "getUserId          -->  " + loginResponse.getUserId());
                        Log.e("keshav", "getFirstName       -->  " + loginResponse.getFirstName());
                        Log.e("keshav", "getLastName        -->  " + loginResponse.getLastName());
                        Log.e("keshav", "getProfilePicture  -->  " + loginResponse.getProfilePicture());

                        String responseCode = loginResponse.getResponseCode();
                        Log.e("keshav", "getResponseCode  -->  " + loginResponse.getResponseCode());
                        Log.e("keshav", "getResponseMessage  -->  " + loginResponse.getResponseMessage());
                        if (responseCode != null && responseCode.equals("404")) {
                            Toast.makeText(MainActivity.this, "Invalid Login Details \n Please try again", Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(MainActivity.this, "Welcome " + loginResponse.getFirstName(), Toast.LENGTH_SHORT).show();
                        }
                    }
                }

                @Override
                public void onFailure(Call<LoginResponse> call, Throwable t) {
                    Toast.makeText(getApplicationContext(), "onFailure called ", Toast.LENGTH_SHORT).show();
                    call.cancel();
                }
            });
        }

        public boolean checkValidation() {
            userId = et_Email.getText().toString();
            password = et_Pass.getText().toString();

            Log.e("Keshav", "userId is -> " + userId);
            Log.e("Keshav", "password is -> " + password);

            if (et_Email.getText().toString().trim().equals("")) {
                CommonMethod.showAlert("UserId Cannot be left blank", MainActivity.this);
                return false;
            } else if (et_Pass.getText().toString().trim().equals("")) {
                CommonMethod.showAlert("password Cannot be left blank", MainActivity.this);
                return false;
            }
            return true;
        }
    }

CommonMethod.java

    public class CommonMethod {


        public static final String DISPLAY_MESSAGE_ACTION =
                "com.codecube.broking.gcm";

        public static final String EXTRA_MESSAGE = "message";

        public  static boolean isNetworkAvailable(Context ctx) {
            ConnectivityManager connectivityManager
                    = (ConnectivityManager)ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
            return activeNetworkInfo != null && activeNetworkInfo.isConnected();
        }

        public static void showAlert(String message, Activity context) {

            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setMessage(message).setCancelable(false)
                    .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {

                        }
                    });
            try {
                builder.show();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

activity_main.xml

    <LinearLayout android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:orientation="vertical"
        xmlns:android="http://schemas.android.com/apk/res/android">

            <ImageView
                android:id="@+id/imgLogin"
                android:layout_width="200dp"
                android:layout_height="150dp"
                android:layout_gravity="center"
                android:layout_marginTop="20dp"
                android:padding="5dp"
                android:background="@mipmap/ic_launcher_round"
                />

            <TextView
                android:id="@+id/txtLogo"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/imgLogin"
                android:layout_centerHorizontal="true"
                android:text="Holostik Track and Trace"
                android:textSize="20dp"
                android:visibility="gone" />

            <android.support.design.widget.TextInputLayout
                android:id="@+id/textInputLayout1"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/box_layout_margin_left"
                android:layout_marginRight="@dimen/box_layout_margin_right"
                android:layout_marginTop="8dp"
                android:padding="@dimen/text_input_padding">

                <EditText
                    android:id="@+id/edtEmail"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="5dp"
                    android:ems="10"
                    android:fontFamily="sans-serif"
                    android:gravity="top"
                    android:hint="Login ID"
                    android:maxLines="10"
                    android:paddingLeft="@dimen/edit_input_padding"
                    android:paddingRight="@dimen/edit_input_padding"
                    android:paddingTop="@dimen/edit_input_padding"
                    android:singleLine="true"></EditText>

            </android.support.design.widget.TextInputLayout>

            <android.support.design.widget.TextInputLayout
                android:id="@+id/textInputLayout2"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/textInputLayout1"
                android:layout_marginLeft="@dimen/box_layout_margin_left"
                android:layout_marginRight="@dimen/box_layout_margin_right"
                android:padding="@dimen/text_input_padding">

                <EditText
                    android:id="@+id/edtPass"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:focusable="true"
                    android:fontFamily="sans-serif"
                    android:hint="Password"
                    android:inputType="textPassword"

                    android:singleLine="true" />

            </android.support.design.widget.TextInputLayout>

            <RelativeLayout
                android:id="@+id/rel12"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/textInputLayout2"
                android:layout_marginTop="10dp"
                android:layout_marginLeft="10dp"
                >

                <Button
                    android:id="@+id/loginSub"
                    android:layout_width="wrap_content"
                    android:layout_height="45dp"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:background="@drawable/border_button"
                    android:paddingLeft="30dp"
                    android:paddingRight="30dp"
                    android:layout_marginRight="10dp"
                    android:text="Login"
                    android:textColor="#ffffff" />    
            </RelativeLayout>

    </LinearLayout>

Post data to backend using retrofit

 implementation 'com.squareup.retrofit2:retrofit:2.8.1'
 implementation 'com.squareup.retrofit2:converter-gson:2.8.1'
 implementation 'com.google.code.gson:gson:2.8.6'
 implementation 'com.squareup.okhttp3:logging-interceptor:4.5.0'

public interface UserService {
  @POST("users/")
  Call<UserResponse> userRegistration(@Body UserRegistration 
    userRegistration);
}



public class ApiClient {

    private static Retrofit getRetrofit(){
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        OkHttpClient okHttpClient = new OkHttpClient
                .Builder()
                .addInterceptor(httpLoggingInterceptor)
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://api.larntech.net/")
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient)
                .build();



        return retrofit;

    }


    public static UserService getService(){
        UserService userService = getRetrofit().create(UserService.class);
        return userService;
    }

}

The good way in my opinion is to send it in the POST Body this means you'll have a create a new POJO but some might like this implementation the most.

public interface APIInterface {
    @POST("/GetDetailWithMonthWithCode")
    List<LandingPageReport> getLandingPageReport(@Body Report report);
}

Then make your POJO with a constructor, getters and setters.

public static class Report {
    private String code;
    private String monthact;

    public Report(String code, String monthact) {
        this.code = code;
        this.monthact = monthact;  
    }

    // Getters and Setters...
}

And just call it the normal way.

Call<List<Report>> request = apiInterface
    .createRetrofitAPIInterface()
    .getLandingPageReport(new Report(code, monthact));

This is a simple solution where we do not need to use JSON

public interface RegisterAPI {
@FormUrlEncoded
@POST("/RetrofitExample/insert.php")
public void insertUser(
        @Field("name") String name,
        @Field("username") String username,
        @Field("password") String password,
        @Field("email") String email,
        Callback<Response> callback);
}

method to send data

private void insertUser(){
    //Here we will handle the http request to insert user to mysql db
    //Creating a RestAdapter
    RestAdapter adapter = new RestAdapter.Builder()
            .setEndpoint(ROOT_URL) //Setting the Root URL
            .build(); //Finally building the adapter

    //Creating object for our interface
    RegisterAPI api = adapter.create(RegisterAPI.class);

    //Defining the method insertuser of our interface
    api.insertUser(

            //Passing the values by getting it from editTexts
            editTextName.getText().toString(),
            editTextUsername.getText().toString(),
            editTextPassword.getText().toString(),
            editTextEmail.getText().toString(),

            //Creating an anonymous callback
            new Callback<Response>() {
                @Override
                public void success(Response result, Response response) {
                    //On success we will read the server's output using bufferedreader
                    //Creating a bufferedreader object
                    BufferedReader reader = null;

                    //An string to store output from the server
                    String output = "";

                    try {
                        //Initializing buffered reader
                        reader = new BufferedReader(new InputStreamReader(result.getBody().in()));

                        //Reading the output in the string
                        output = reader.readLine();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    //Displaying the output as a toast
                    Toast.makeText(MainActivity.this, output, Toast.LENGTH_LONG).show();
                }

                @Override
                public void failure(RetrofitError error) {
                    //If any error occured displaying the error as toast
                    Toast.makeText(MainActivity.this, error.toString(),Toast.LENGTH_LONG).show();
                }
            }
    );
}

Now we can get the post request using php aur any other server side scripting.

Source Android Retrofit Tutorial


Examples related to android

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How to implement a simple scenario the OO way My eclipse won't open, i download the bundle pack it keeps saying error log getting " (1) no such column: _id10 " error java doesn't run if structure inside of onclick listener Cannot retrieve string(s) from preferences (settings) strange error in my Animation Drawable how to put image in a bundle and pass it to another activity FragmentActivity to Fragment A failure occurred while executing com.android.build.gradle.internal.tasks

Examples related to post

How to post query parameters with Axios? How can I add raw data body to an axios request? HTTP POST with Json on Body - Flutter/Dart How do I POST XML data to a webservice with Postman? How to set header and options in axios? Redirecting to a page after submitting form in HTML How to post raw body data with curl? How do I make a https post in Node Js without any third party module? How to convert an object to JSON correctly in Angular 2 with TypeScript Postman: How to make multiple requests at the same time

Examples related to retrofit

Call another rest api from my server in Spring-Boot Retrofit 2: Get JSON from Response body Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $ Retrofit 2 - URL Query Parameter POST Multipart Form Data using Retrofit 2.0 including image How to get response as String using retrofit without using GSON or any other library in android Adding header to all request with Retrofit 2 Retrofit 2 - Dynamic URL Retrofit 2.0 how to get deserialised error response.body Logging with Retrofit 2