通过改造发送帖子消息

时间:2017-04-12 21:25:49

标签: android retrofit2

这是我第一次改装,但我正在尝试向我的服务器发送一组Gps数据点

来自我的设备

这是我的POJO课程

script_function

这是我的Request类,它包含列表

public class GpsData {

    private long mId;
    @SerializedName("mduid")
    @Expose
    private String mMduid;
    @SerializedName("latitude")
    @Expose
    private double mLat;
    @SerializedName("longitude")
    @Expose
    private double mLng;
    @SerializedName("speed")
    @Expose
    private float mSpeed;
    @SerializedName("time")
    @Expose
    private long mTime;
    private boolean mSent;
    @SerializedName("status")
    @Expose
    private String mStatus;

这是我的界面

public class GpsRequest {
    @SerializedName("gpsData")
    @Expose
    public List<GpsData> data;
}

这是我提出请求的方式

public interface GpsApiInterface {

    @Headers( "Content-Type: application/json" )
    @POST("/api/v2/GPS")
    Call<ResponseBody> sendGpsData(@Body GpsRequest gpsData);
}

这是我用来测试的服务器代码

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://"+ DEBUG_API)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        GpsApiInterface apiInterface = retrofit.create(GpsApiInterface.class);

        ArrayList<GpsData> list = new ArrayList<>();
        list.add(data);
        list.add(data);
        GpsRequest request = new GpsRequest();
        request.data = list;

            Call<ResponseBody> call = apiInterface.sendGpsData(request);
            call.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    if(response.code() == HttpURLConnection.HTTP_OK){
                        GpsDB db = new GpsDB(LocationService.this);
                        db.delete(GpsDB.ID+"=?",new String[]{String.valueOf(id)});
                        db.close();
                    }
                }

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {

                }
            });

这是服务器上的GPS数据类

public class GPSController : ApiController
    {
        public GPSController() { }

        public HttpResponseMessage Post([FromBody]GPSData[] gpsData)
        {
            if (gpsData != null)
            {
                for (int i = 0; i < gpsData.Length; i++)
                {

                }
                return Request.CreateResponse(HttpStatusCode.OK);
            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }


        }
    }

当我发出请求时,服务器被命中但没有数据(gpsData为null)。如果我从public class GPSData { public string mduid; public double latitude; public double longitude; public int speed; public string time; public string status; } 拨打同一个电话,它会被调用,数据就在那里,所以我错过了什么?

更新

添加了对okhttp的记录,这是日志

postman

比较D/OkHttp: --> POST http://192.168.202.170:9001/api/v2/GPS http/1.1 D/OkHttp: Content-Type: application/json; charset=UTF-8 D/OkHttp: Content-Length: 247 D/OkHttp: Accept: application/json D/OkHttp: Host: 192.168.202.170:9001 D/OkHttp: Connection: Keep-Alive D/OkHttp: Accept-Encoding: gzip D/OkHttp: User-Agent: okhttp/3.6.0 D/OkHttp: {"gpsData":[{"mId":0,"latitude":43.0360532,"longitude":-78.8010079,"mSent":false,"speed":0.0,"status":"OK","time":1492088158526},{"mId":0,"latitude":43.0360532,"longitude":-78.8010079,"mSent":false,"speed":0.0,"status":"OK","time":1492088158526}]} D/OkHttp: --> END POST (247-byte body)

的Json
Postman

从应用程序发送的数据

[
    {
        "latitude": 43.0360532,
        "longitude": -78.8010079,
        "speed": 0,
        "time": 1492027407344
    },
    {
        "latitude": 43.0360532,
        "longitude": -78.8010079,
        "speed": 0,
        "time": 1492027407344
    }
]

似乎服务器上的{ "gpsData": [ { "mId": 0, "latitude": 43.0360532, "longitude": -78.8010079, "mSent": false, "speed": 0, "status": "OK", "time": 1492088158526 }, { "mId": 0, "latitude": 43.0360532, "longitude": -78.8010079, "mSent": false, "speed": 0, "status": "OK", "time": 1492088158526 } ] } 是一个数组,但应用程序正在发送带有数组的对象可能是问题?如果是这样,我如何发送不在对象中的数组?

3 个答案:

答案 0 :(得分:1)

您需要GPSRequest类的构造函数:

public class GpsRequest {
    @SerializedName("gpsData")
    @Expose
    public List<GpsData> data;
    public GpsRequest(List<GpsData> data) {
         this.data = data;
    }

然后在你的请求中:

GpsRequest request = new GpsRequest(list);

答案 1 :(得分:0)

Digression到POJO模型。如果使用@Expose创建Gson实例,则POJO中的GsonConverterFactory.create()注释无效(因为后台的Gson实例是使用new Gson()创建的),因此来自{{GpsData的所有属性无论注释如何,都将序列化类。

如果您希望注释生效,则必须将Gson实例创建为new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()并将其传递给GsonConverterFactory.create()。也许它影响服务器不要正确地序列化数据,但不确定..

其次,使用OkHttp日志记录非常有用,这样您就可以在android studio console中看到HTTP请求详细信息。

以下是OkHttpClient为所有端点设置Content-Type的示例,您可以从@Headers中删除GpsApiInterface

private OkHttpClient getClient() {
    return new OkHttpClient.Builder()
            .addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE))
            .addInterceptor(chain -> {
                Request request = chain.request()
                        .newBuilder()
                        .addHeader("Content-Type", "application/json;charset=utf-8")
                        .addHeader("Accept", "application/json")
                        .build();

                return chain.proceed(request);
            }).build();
}

然后修改Retrofit实例化,如下所示:

new Retrofit.Builder()
            .baseUrl("http://"+ DEBUG_API)
            .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()))
            .client(getClient())
            .build();

在调试模式下运行时,您将在控制台中看到HTTP请求和响应,并且更容易调试。 我知道这不是完整的答案,但它是解决方案的一步。 等待反馈。

<强>更新

另一件需要注意的事情。如果您正在使用Retrofit2,则baseUrl(在您的情况下为DEBUG_API值)必须以/结尾,在这种情况下,请在/中启动@POST("/api/v2/GPS")可能导致问题,因为生成的端点url可能看起来像http://DEBUG_API//api/v2/GPS。 尝试将方法POST修改为@POST("api/v2/GPS")

答案 2 :(得分:0)

问题是我发送了一个带有数组的对象,服务器只期待一个数组,所以我将请求更改为

@POST("/api/v2/GPS")
Call<ResponseBody> sendGpsData(@Body List<GpsData> gpsData);

现在它正常工作