J'essaie en vain de consommer une API sur Android en utilisant la bibliothèque Retrofit, mais tout en utilisant POSTMAN, je peux voir les résultats attendus.
POSTMAN SETTING
L'URI de l'API (base + contrôleur)
Méthode HTTP définie sur POST
Cliqué sur les données de départ ou x-www-form-urlencoded
Ensuite, je passe les deux paramètres sur les champs clé/valeur.
RÉGLAGE Android RETROFIT
@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);
Aucune de ces options ne fonctionne. Mais je reçois {} comme résultat.
MISE À JOUR
Les mêmes paramètres utilisant la classe standard HttpClient
(et HttpPost
) fonctionnent bien.
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);
Pourquoi je ne peux pas faire cette demande et obtenir la réponse correcte dans Retrofit?
PDATE 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);
Après avoir joué, je pense avoir trouvé la source du problème. J'ai mis à jour mon code de modification pour recevoir List<LandingPageReport>
. Mais maintenant cette erreur se produit
retrofit.RetrofitError: com.google.gson.JsonSyntaxException: Java.lang.IllegalStateException: BEGIN_ARRAY attendu mais BEGIN_OBJECT à la ligne 1 colonne 2 chemin $
La raison en est que je consomme 2 api (webapi et wcf). Toutes mes autres réponses json
sont des tableaux d'objets. [{}, {}] mais dans cet appel j'ai reçu ceci
{
"GetDetailWithMonthWithCodeResult": [
{
"code": "test",
"field1": "test",
}
]
}
Mais je n'arrive toujours pas à analyser la réponse.
J'ai trouvé la solution. La question était un problème dans la structure de mes classes. Donc je les ai mis à jour comme les exemples suivants.
public class LandingPageReport {
private ArrayList<LandingPageReportItem> GetDetailWithMonthWithCodeResult;
// + Getter Setter methods
}
public class LandingPageReportItem {
private String code;
private String field1;
// + Getter Setter methods
}
Et puis j'utilise cette configuration de rattrapage
@POST("/GetDetailWithMonthWithCode")
void getLandingPageReport(@Field("code") String code,
@Field("monthact") String monthact,
Callback<LandingPageReport> cb);
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"
}
Réponse de connexion
{
"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;
}
}
interface APIInterface
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:paddingLeft="@dimen/edit_input_padding"
Android:paddingRight="@dimen/edit_input_padding"
Android:paddingTop="@dimen/edit_input_padding"
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>
Ceci est une solution simple où nous n'avons pas besoin d'utiliser 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);
}
méthode d'envoi de données
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();
}
}
);
}
Maintenant, nous pouvons obtenir la demande de publication en utilisant php ou n'importe quel autre script côté serveur.
Vous devriez créer une interface pour ça, comme ça marche bien
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);
}
ou vous pouvez visiter à http://teachmeandroidhub.blogspot.com/2018/08/post-data-using-retrofit-in-Android.html
et vous pouvez visiter https://github.com/rajkumu12/GetandPostUsingRatrofit
La bonne façon à mon avis est de l'envoyer dans le POST Body
_ cela signifie que vous devrez créer un nouveau POJO, mais certains aimeront peut-être le plus cette implémentation.
public interface APIInterface {
@POST("/GetDetailWithMonthWithCode")
List<LandingPageReport> getLandingPageReport(@Body Report report);
}
Faites ensuite votre POJO avec un constructeur, des getters et des 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...
}
Et appelez ça comme ça.
Call<List<Report>> request = apiInterface
.createRetrofitAPIInterface()
.getLandingPageReport(new Report(code, monthact));