2014-04-02 10 views
9

Sto tentando di utilizzare Volley per inviare una richiesta di tipo DELETE al mio server e aggiungere parametri alla richiesta. Finora non sono stato in grado di farlo.Volley - come inviare i parametri di richiesta DELETE?

La creazione di una richiesta personalizzata e l'override del metodo getParams() non mi è stata di aiuto poiché questo metodo non viene chiamato per la richiesta del tipo DELETE.

Come posso aggiungere parametri a una richiesta DELETE in Volley?

risposta

12

Stesso problema qui, ma ho trovato la soluzione.

Il problema è l'implementazione del metodo createHttpRequest in com.android.volley.toolbox.HttpClientStack.java che aggiungerà il corpo solo se il metodo di richiesta è POST, PUT o PATCH.

/** 
* Creates the appropriate subclass of HttpUriRequest for passed in request. 
*/ 
@SuppressWarnings("deprecation") 
/* protected */ static HttpUriRequest createHttpRequest(Request<?> request, 
     Map<String, String> additionalHeaders) throws AuthFailureError { 
    switch (request.getMethod()) { 
     case Method.DEPRECATED_GET_OR_POST: { 
      // This is the deprecated way that needs to be handled for backwards compatibility. 
      // If the request's post body is null, then the assumption is that the request is 
      // GET. Otherwise, it is assumed that the request is a POST. 
      byte[] postBody = request.getPostBody(); 
      if (postBody != null) { 
       HttpPost postRequest = new HttpPost(request.getUrl()); 
       postRequest.addHeader(HEADER_CONTENT_TYPE, request.getPostBodyContentType()); 
       HttpEntity entity; 
       entity = new ByteArrayEntity(postBody); 
       postRequest.setEntity(entity); 
       return postRequest; 
      } else { 
       return new HttpGet(request.getUrl()); 
      } 
     } 
     case Method.GET: 
      return new HttpGet(request.getUrl()); 
     case Method.DELETE: 
      return new HttpDelete(request.getUrl()); 
     case Method.POST: { 
      HttpPost postRequest = new HttpPost(request.getUrl()); 
      postRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); 
      setEntityIfNonEmptyBody(postRequest, request); 
      return postRequest; 
     } 
     case Method.PUT: { 
      HttpPut putRequest = new HttpPut(request.getUrl()); 
      putRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); 
      setEntityIfNonEmptyBody(putRequest, request); 
      return putRequest; 
     } 
     case Method.HEAD: 
      return new HttpHead(request.getUrl()); 
     case Method.OPTIONS: 
      return new HttpOptions(request.getUrl()); 
     case Method.TRACE: 
      return new HttpTrace(request.getUrl()); 
     case Method.PATCH: { 
      HttpPatch patchRequest = new HttpPatch(request.getUrl()); 
      patchRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); 
      setEntityIfNonEmptyBody(patchRequest, request); 
      return patchRequest; 
     } 
     default: 
      throw new IllegalStateException("Unknown request method."); 
    } 
} 

quindi bisogna usare la propria implementazione di HttpStack.java o si ignora HttpClientStack classe.

Prima di tutto la vostra necessità di sostituire le inizializzazione del RequestQueue da

RequestQueue requestQueue = Volley.newRequestQueue(sContext); 

a

String userAgent = "volley/0"; 
    try { 
     String packageName = getContext().getPackageName(); 
     PackageInfo info = getContext().getPackageManager().getPackageInfo(packageName, 0); 
     userAgent = packageName + "/" + info.versionCode; 
    } catch (PackageManager.NameNotFoundException e) {} 
    HttpStack httpStack = new OwnHttpClientStack(AndroidHttpClient.newInstance(userAgent)); 
    RequestQueue requesQueue = Volley.newRequestQueue(sContext, httpStack); 

e scrivere una propria implementazione di HttpClientStack dove si cambia il caso di "Method.POST:" in il metodo createHttpRequest(). Devi anche creare un oggetto come "OwnHttpDelete" come estensione di HttpEntityEnclosingRequestBase per utilizzare il metodo setEntityIfNonEmptyBody().

public class OwnHttpClientStack extends com.android.volley.toolbox.HttpClientStack { 
    private final static String HEADER_CONTENT_TYPE = "Content-Type"; 

    public OwnHttpClientStack(HttpClient client) { 
     super(client); 
    } 

    @Override 
    public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders) 
      throws IOException, AuthFailureError { 
     HttpUriRequest httpRequest = createHttpRequest(request, additionalHeaders); 
     addHeaders(httpRequest, additionalHeaders); 
     addHeaders(httpRequest, request.getHeaders()); 
     onPrepareRequest(httpRequest); 
     HttpParams httpParams = httpRequest.getParams(); 
     int timeoutMs = request.getTimeoutMs(); 
     // TODO: Reevaluate this connection timeout based on more wide-scale 
     // data collection and possibly different for wifi vs. 3G. 
     HttpConnectionParams.setConnectionTimeout(httpParams, 5000); 
     HttpConnectionParams.setSoTimeout(httpParams, timeoutMs); 
     return mClient.execute(httpRequest); 
    } 

    private static void addHeaders(HttpUriRequest httpRequest, Map<String, String> headers) { 
     for (String key : headers.keySet()) { 
      httpRequest.setHeader(key, headers.get(key)); 
     } 
    } 

    static HttpUriRequest createHttpRequest(Request<?> request, Map<String, String> additionalHeaders) throws AuthFailureError { 
     switch (request.getMethod()) { 
      case Request.Method.DEPRECATED_GET_OR_POST: { 
       byte[] postBody = request.getPostBody(); 
       if (postBody != null) { 
        HttpPost postRequest = new HttpPost(request.getUrl()); 
        postRequest.addHeader(HEADER_CONTENT_TYPE, request.getPostBodyContentType()); 
        HttpEntity entity; 
        entity = new ByteArrayEntity(postBody); 
        postRequest.setEntity(entity); 
        return postRequest; 
       } else { 
        return new HttpGet(request.getUrl()); 
       } 
      } 
      case Request.Method.GET: 
       return new HttpGet(request.getUrl()); 
      case Request.Method.DELETE: 
       OwnHttpDelete deleteRequest = new OwnHttpDelete(request.getUrl()); 
       deleteRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); 
       setEntityIfNonEmptyBody(deleteRequest, request); 
       return deleteRequest; 
      case Request.Method.POST: { 
       HttpPost postRequest = new HttpPost(request.getUrl()); 
       postRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); 
       setEntityIfNonEmptyBody(postRequest, request); 
       return postRequest; 
      } 
      case Request.Method.PUT: { 
       HttpPut putRequest = new HttpPut(request.getUrl()); 
       putRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); 
       setEntityIfNonEmptyBody(putRequest, request); 
       return putRequest; 
      } 
      case Request.Method.HEAD: 
       return new HttpHead(request.getUrl()); 
      case Request.Method.OPTIONS: 
       return new HttpOptions(request.getUrl()); 
      case Request.Method.TRACE: 
       return new HttpTrace(request.getUrl()); 
      case Request.Method.PATCH: { 
       HttpPatch patchRequest = new HttpPatch(request.getUrl()); 
       patchRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); 
       setEntityIfNonEmptyBody(patchRequest, request); 
       return patchRequest; 
      } 
      default: 
       throw new IllegalStateException("Unknown request method."); 
     } 
    } 

    private static void setEntityIfNonEmptyBody(HttpEntityEnclosingRequestBase httpRequest, 
               Request<?> request) throws AuthFailureError { 
     byte[] body = request.getBody(); 
     if (body != null) { 
      HttpEntity entity = new ByteArrayEntity(body); 
      httpRequest.setEntity(entity); 
     } 
    } 

    private static class OwnHttpDelete extends HttpPost { 
     public static final String METHOD_NAME = "DELETE"; 

     public OwnHttpDelete() { 
      super(); 
     } 

     public OwnHttpDelete(URI uri) { 
      super(uri); 
     } 

     public OwnHttpDelete(String uri) { 
      super(uri); 
     } 

     public String getMethod() { 
      return METHOD_NAME; 
     } 
    } 
} 

Spero che il mio codice possa aiutare qualcuno. Dovrebbe anche essere possibile aggiungere parametri a una richiesta HEAD.

+0

Hai salvato la mia giornata !!! – codeskraps

+0

All'inizio ho provato questo, e tutto è andato bene, ma poi c'è stato un problema, con il caricamento delle immagini. Avevo 2 NetworkImageViews che dovevano caricare la stessa immagine. Uno caricato, il secondo no. Ho scoperto che la tua soluzione è per Android versione 9 e precedenti. – kroky

2

Dopo un po 'di lettura e un po' di ricerca del codice di Volley, sono giunto alla conclusione che non esiste un modo per associare i parametri a una richiesta DELETE in Volley - molto probabilmente come una scelta di progettazione come sembra essere disapprovato in generale.

Volevo capire come farlo perché volevo collegare una chiave API ad ogni tipo di richiesta che sto inviando al mio server.

Se qualcuno si trova con un problema simile, quindi quello che ho finito (e sono abbastanza sicuro ora che è il modo di andare qui) è inviare la chiave API nella parte intestazioni della richiesta. In particolare in Volley ciò significa sovrascrivere il metodo getHeaders() e aggiungere i parametri necessari.

Ecco il mio pezzo di codice:

@Override 
public Map<String, String> getHeaders() throws AuthFailureError { 
    Map<String, String> headers = super.getHeaders(); 

    if (headers == null 
      || headers.equals(Collections.emptyMap())) { 
     headers = new HashMap<String, String>(); 
    } 

    headers.put("API_KEY", apiKey); 

    return headers; 
}