【问题标题】:Whats wrong with this retrofit call?这个改造电话有什么问题?
【发布时间】:2017-01-15 09:10:05
【问题描述】:

我正在尝试使用 Android 改造来发送 POST 并构建响应。

我已经成功地发送了 GET,但现在我需要发送带有一些正文元素的 POST。

public static <S> S createAccessService(Class<S> serviceClass, String code, String redirectUri,
                                  String clientId, String clientSecret) {
    OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
    String basicCredentials = clientId+":"+clientSecret;
    byte[] encodeBytes = Base64.encode(basicCredentials.getBytes(), Base64.NO_WRAP);
    httpClient.addInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request original = chain.request();
            RequestBody body = new FormBody.Builder()
                    .add("grant_type", "authorization_code")
                    .add("code", code)
                    .add("redirect_uri", redirectUri).build();
            Request request = original.newBuilder()
                    .addHeader("Authorization", "Basic "+new String(encodeBytes))
                    .method(original.method(), original.body())
                    .put(body)
                    .build();
            return chain.proceed(request);
        }
    });

    OkHttpClient client = httpClient.build();
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(API_BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(client)
            .build();

    return retrofit.create(serviceClass);

我正在尝试构建的 POST 看起来像这样:

POST /api/token HTTP/1.1
Host: accounts.spotify.com
Authorization: Basic ***********************************
Cache-Control: no-cache
Postman-Token: 99177da6-1606-3145-689d-bc4b09b3f212
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A8888%2Fcallback&code*********************************************************************************************************************************************************

显然,为了安全起见,密钥是隐藏的。

这是我用来存储响应的 POJO。

public class Session {

private String scope;

private String expires_in;

private String token_type;

private String refresh_token;

private String access_token;
private String error;

public String getError_description() {
    return error_description;
}

public void setError_description(String error_description) {
    this.error_description = error_description;
}

public String getError() {
    return error;
}

public void setError(String error) {
    this.error = error;
}

private String error_description;

public String getScope ()
{
    return scope;
}

public void setScope (String scope)
{
    this.scope = scope;
}

public String getExpires_in ()
{
    return expires_in;
}

public void setExpires_in (String expires_in)
{
    this.expires_in = expires_in;
}

public String getToken_type ()
{
    return token_type;
}

public void setToken_type (String token_type)
{
    this.token_type = token_type;
}

public String getRefresh_token ()
{
    return refresh_token;
}

public void setRefresh_token (String refresh_token)
{
    this.refresh_token = refresh_token;
}

public String getAccess_token ()
{
    return access_token;
}

public void setAccess_token (String access_token)
{
    this.access_token = access_token;
}




}

我已经改变了很多东西,但无论如何,响应无法实例化一个新的 Session 对象,总是返回 null。

添加:

这是我使用的界面:

   @FormUrlEncoded
   @POST("/api/token")
   Call<Session> getSession();

我做错了什么?

谢谢

【问题讨论】:

    标签: android post retrofit spotify


    【解决方案1】:

    好吧,如果你尝试用retrofit2 发送POST 请求,你应该试试这个:

    首先,创建一个接口,在这个接口中声明POST request的正文内容:

    public interface ISesion {
    
        @FormUrlEncoded
        @POST("/users/login")
        Call<Sesion> inSesion(@Field("username") String usuario, @Field("password") String password);
    }
    

    参数@Field是你在POST request中使用的正文内容

    现在,您可以在 MainActivity 中进行此操作:

    public class MainActivity extends AppCompatActivity {
        private Retrofit retrofit; //your Retrofit Object
        private ISesion iSesion; //your interface
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
        retrofit = new Retrofit.Builder()
                .baseUrl(getString(R.string.url_base)) //your base URL ("http://www.myexample.com")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    
        iSesion = retrofit.create(ISesion.class);
        Call<Sesion> call = iSesion.inSesion(usuario, contrasena); //you get this fields from editText, for example, and you pass it to the method in your interface
            call.enqueue(new Callback<Sesion>() {
                @Override
                public void onResponse(Call<Sesion> call, Response<Sesion> response) {
                    code = response.code();
                    switch (code) {
                        case 200:
                            Intent intent = new Intent(getActivity(), MainActivity.class);
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                            startActivity(intent);
    
                            break;
                        case 401:
                            error = response.body().isError();
                            mensaje = response.body().getMensaje();
                            if (error) {
                                Snackbar.make(view, mensaje, Snackbar.LENGTH_LONG).show();
                            }
                            break;
                    }
                }
    
                @Override
                public void onFailure(Call<Sesion> call, Throwable t) {
                    t.printStackTrace();
                    Snackbar.make(view, getString(R.string.error_general), Snackbar.LENGTH_LONG).show();
                }
            });
        }
    }
    

    Call&lt;Sesion&gt;方法中使用的模型是下一个:

    public class Sesion {
    
        @SerializedName("error")
        private boolean error;
    
        @SerializedName("message")
        private String mensaje;
    
        public boolean isError() {
            return error;
        }
    
        public String getMensaje() {
            return mensaje;
        }
    }  
    

    编辑:

    如果你想在正文中发送你的令牌,你可以试试这个:

    Call<Sesion> call = iSesion.inSesion("Basic " + generatedToken); // here is the authentication token
            call.enqueue(new Callback<Sesion>() {
                @Override
                public void onResponse(Call<Sesion> call, Response<Sesion> response) {
                    code = response.code();
                    switch (code) {
                        case 200:
                            Intent intent = new Intent(getActivity(), MainActivity.class);
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                            startActivity(intent);
    
                            break;
                        case 401:
                            error = response.body().isError();
                            mensaje = response.body().getMensaje();
                            if (error) {
                                Snackbar.make(view, mensaje, Snackbar.LENGTH_LONG).show();
                            }
                            break;
                    }
                }
    
                @Override
                public void onFailure(Call<Sesion> call, Throwable t) {
                    t.printStackTrace();
                    Snackbar.make(view, getString(R.string.error_general), Snackbar.LENGTH_LONG).show();
                }
            });
        }
    

    这是界面:

    public interface ISesion {
    
        @FormUrlEncoded
        @POST("/users/login")
        Call<Sesion> inSesion(@Field("token") String generatedToken);
    }
    

    【讨论】:

    • 我不确定这与我所做的有什么不同
    • 您能调试一下来自POST request 的响应吗?这样我们就可以知道向我们发送请求的响应是什么
    • 我收到了错误的请求 (400)
    • 在这种情况下,正文内容是错误的,为此,您有一个错误的请求,您可以使用Fiddler link 来嗅探您发送正文内容的方式,您可以尝试使用我上面发布的方法,在这种情况下,您将身份验证令牌放在参数@Field 中,您需要将字符串“Basic”与您生成的令牌连接起来
    • 但是由于我能够获得响应代码,因此我可以更轻松地进行调试。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-30
    • 2021-01-31
    • 2012-05-26
    相关资源
    最近更新 更多