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.
Approach. You will have to create a Request interceptor ( BasicAuthInterceptor ) which extends Interceptor class of OkHttp library. Then, override intercept function and add your credentials into the request. Generate basic credentials with Credentials class of package OkHttp by using its basic function.
This means your @GET or @DELETE should not have @Body parameter. You can use query type url or path type url or Query Map to fulfill your need. Else you can use other method annotation.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With