web-dev-qa-db-ja.com

Retrofitを使用して、パラメーターを使用して投稿要求を送信する

Retrofitライブラリを使用してAndroidでAPIを使用しようとして失敗しましたが、POSTMANを使用している間、予期した結果を確認できます。

ポストマン設定

  • API URL(ベース+コントローラー)

  • POSTに設定されたHTTPメソッド

  • From-dataまたはx-www-form-urlencodedをクリックしました

  • 次に、キー/値フィールドに2つのパラメーターを渡します。

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);

このオプションはいずれも機能しません。しかし、結果として{}を取得しています。

UPDATE

標準のHttpClient(およびHttpPost)クラスを使用した同じ設定は正常に機能します。

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);

なぜこの要求を実行できず、Retrofitで正しい応答を取得できないのですか?

更新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);

遊んだ後、私は問題の原因を見つけたと思います。 List<LandingPageReport>を受け取るように改造コードを更新しました。しかし、今このエラーが発生します

retrofit.RetrofitError:com.google.gson.JsonSyntaxException:Java.lang.IllegalStateException:BEGIN_ARRAYが必要ですが、1行2列のパスがBEGIN_OBJECTでした$

その理由は、2つのAPI(webapiとwcf)を消費するためです。私の他のjson応答はすべてオブジェクトの配列です。 [{}、{}]が、この電話でこれを受け取った

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

しかし、それでも応答を解析することができません。

27
Adam

私は解決策を見つけました。この問題は、私のクラス構造の問題でした。そこで、次のサンプルのように更新しました。

public class LandingPageReport {

    private ArrayList<LandingPageReportItem> GetDetailWithMonthWithCodeResult;

    // + Getter Setter methods
}

public class LandingPageReportItem {

    private String code;

    private String field1;

    // + Getter Setter methods
}

そして、このレトロフィット構成を使用します

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

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"
    }

ログイン応答

    {
        "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 APIInterface {

        @POST("LoginController/Login")
        Call<LoginResponse> createUser(@Body LoginResponse 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>
29
Keshav Gera

これは、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);
}

データを送信する方法

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();
                }
            }
    );
}

これで、他のサーバー側スクリプトを使用して、phpを使用して投稿要求を取得できます。

ソース Android Retrofit Tutorial

23
Belal Khan

それがうまく機能しているように、そのためのインターフェイスを作成する必要があります

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);
}

または、 http://teachmeandroidhub.blogspot.com/2018/08/post-data-using-retrofit-in-Android.html にアクセスできます

そして、あなたは https://github.com/rajkumu12/GetandPostUsingRatrofit

3
rajeev ranjan

私の意見では、POST Bodyで送信するのが良い方法です。これは、新しいPOJOを作成することを意味しますが、この実装を最も気に入っている人もいるでしょう。

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

次に、コンストラクター、ゲッター、セッターを使用してPOJOを作成します。

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...
}

通常の方法で呼び出します。

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