2014-04-02 18 views
9

Próbuję użyć Volley, aby wysłać żądanie typu DELETE do mojego serwera i dodać parametry do żądania. Do tej pory nie byłem w stanie tego zrobić.Volley - jak wysłać parametry żądania DELETE?

Tworzenie niestandardowego żądania i przesłanianie metody getParams() nie pomogło mi, ponieważ ta metoda nie jest wywoływana dla żądania typu DELETE.

Jak mogę dodać parametry do żądania USUŃ w siatkówce?

Odpowiedz

12

sam problem tutaj, ale znalazłem rozwiązanie.

Problem polega na wdrożeniu metody createHttpRequest w pliku com.android.volley.toolbox.HttpClientStack.java, która dodaje treść tylko wtedy, gdy metoda żądania to POST, PUT lub 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."); 
    } 
} 

Więc trzeba użyć własnego realizację HttpStack.java lub zastąpić HttpClientStack klasa.

Przede wszystkim należy wymienić swój inicjalizacji RequestQueue z

RequestQueue requestQueue = Volley.newRequestQueue(sContext); 

do

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

i wyraź swoją realizację HttpClientStack gdzie można zmienić przypadek „Method.POST:” w metoda createHttpRequest(). Trzeba również utworzyć obiekt typu "OwnHttpDelete" jako rozszerzenie HttpEntityEnclosingRequestBase, aby użyć metody 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; 
     } 
    } 
} 

Mam nadzieję, że mój kod pomoże komuś. Powinno być również możliwe dodanie parametrów do żądania HEAD.

+0

Uratowałeś mój dzień !!! – codeskraps

+0

Najpierw spróbowałem tego i wszystko poszło dobrze, ale wtedy pojawił się problem z ładowaniem obrazu. Miałem 2 NetworkImageViews, które musiały załadować ten sam obraz. Jeden załadowany, drugi nie. Okazało się, że twoje rozwiązanie jest dla Androida w wersji 9 i niższej. – kroky

2

Po nieco dłuższej lekturze i zagłębianiu się w kod Volleya, doszedłem do wniosku, że nie ma sposobu na dołączenie parametrów do polecenia DELETE w Volley - prawdopodobnie jako wybór projektu, jak się wydaje być ogólnie mile widzianym.

Chciałem dowiedzieć się, jak to zrobić, ponieważ chciałem dołączyć klucz API do każdego typu zapytania, które wysyłam na mój serwer.

Jeśli ktoś znajdzie się z podobnym problemem, to, co do tego doszedłem (i jestem prawie pewien, że to jest sposób na przejście tutaj) jest wysłanie klucza API w części nagłówka żądania. W szczególności w Volley oznacza to przesłonięcie metody getHeaders() i dodanie wymaganych parametrów.

Oto mój kawałek kodu:

@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; 
} 
Powiązane problemy