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",
}
]
}
しかし、それでも応答を解析することができません。
私は解決策を見つけました。この問題は、私のクラス構造の問題でした。そこで、次のサンプルのように更新しました。
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);
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>
これは、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を使用して投稿要求を取得できます。
それがうまく機能しているように、そのためのインターフェイスを作成する必要があります
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
私の意見では、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));