Volley - POST / GET-Parameter

81

Ich habe eine Google IO 2013-Sitzung über Volley gesehen und denke darüber nach, auf Volley umzusteigen. Unterstützt Volley das Hinzufügen von POST / GET-Parametern zur Anforderung? Wenn ja, wie kann ich das machen?

Ziem
quelle
2
Ich habe nicht die ganze Keynote gesehen, aber ich bin mir ziemlich sicher, dass das GET machbar sein sollte, indem man einfach die Parameter zur URL hinzufügt (z. B. http://example.com?param1=val1&param2=val2)
JJJollyjim
Es scheint noch keine Dokumentation zu geben, aber Sie können die Quelle hier überprüfen android.googlesource.com/platform/frameworks/volley/+/master
MM.
@ JJ56 - Richtig, aber was ist mit POST-Parametern? Ich habe den Quellcode gesehen, aber nichts im Zusammenhang mit POST-Parametern gefunden.
Ziem
1
Ich schäme mich, das zu sagen. Wenn Sie hier gefragt werden, warum Ihre Anfrage keinen Textkörper auf Ihrem Server hat, stellen Sie sicher, dass Sie die POST / PUT-Methode verwenden. Ich denke, ich bin nur müde. Hoffe, dieser Kommentar hilft jemandem oder hilft mir, mich besser zu fühlen
Alwin Kesler

Antworten:

64

Überschreiben Sie in Ihrer Request-Klasse (die Request erweitert) die Methode getParams (). Sie würden dasselbe für Header tun, überschreiben Sie einfach getHeaders ().

Wenn Sie sich die PostWithBody-Klasse in TestRequest.java in Volley-Tests ansehen, finden Sie ein Beispiel. Es geht so etwas

public class LoginRequest extends Request<String> {

    // ... other methods go here

    private Map<String, String> mParams;

    public LoginRequest(String param1, String param2, Listener<String> listener, ErrorListener errorListener) {
        super(Method.POST, "http://test.url", errorListener);
        mListener = listener;
        mParams = new HashMap<String, String>();
        mParams.put("paramOne", param1);
        mParams.put("paramTwo", param2);

    }

    @Override
    public Map<String, String> getParams() {
        return mParams;
    }
}

Evan Charlton war so freundlich, ein kurzes Beispielprojekt zu erstellen, um uns den Umgang mit Volley zu zeigen. https://github.com/evancharlton/folly/

Afzal N.
quelle
70
Beachten Sie, dass das getParamsnur (standardmäßig) in einer POST- oder PUT-Anforderung aufgerufen wird , nicht jedoch in einer GET-Anforderung. Siehe Ogre_BGR Antwort
Itai Hanski
2
Ich kann nicht glauben, dass ich das bis jetzt nie bemerkt habe
Afzal N
@AfzalivE, eine Idee, wie man eine API-Anfrage mit OAuth signiert, wenn man den obigen Code verwendet?
Bipin Vayalu
2
@BipinVayalu Wenn Sie eine Verbindung zur Google API herstellen, sollten Sie in der Lage sein, com.android.volley.AndroidAuthenticator
Pierre-Antoine
Sie haben vergessen, mParams zu instanziieren.
Moritz
84

Für die GET-Parameter gibt es zwei Alternativen:

Erstens : Wie in einem Kommentar unter der Frage vorgeschlagen, können Sie einfach String verwenden und die Platzhalter für Parameter durch folgende Werte ersetzen:

String uri = String.format("http://somesite.com/some_endpoint.php?param1=%1$s&param2=%2$s",
                           num1,
                           num2);

StringRequest myReq = new StringRequest(Method.GET,
                                        uri,
                                        createMyReqSuccessListener(),
                                        createMyReqErrorListener());
queue.add(myReq);

Dabei sind num1 und num2 String-Variablen, die Ihre Werte enthalten.

Zweitens : Wenn Sie einen neueren externen HttpClient (z. B. 4.2.x) verwenden, können Sie URIBuilder verwenden, um Ihren Uri zu erstellen. Der Vorteil ist, dass wenn Ihre Uri-Zeichenfolge bereits Parameter enthält, es einfacher ist, diese an die zu übergeben URIBuilderund dann ub.setQuery(URLEncodedUtils.format(getGetParams(), "UTF-8"));Ihre zusätzlichen Parameter hinzuzufügen. Auf diese Weise müssen Sie nicht überprüfen, ob "?" wird bereits zum uri hinzugefügt oder um einige zu verpassen und eliminiert so eine Quelle für mögliche Fehler.

Für die POST-Parameter ist es wahrscheinlich manchmal einfacher als die akzeptierte Antwort, dies wie folgt zu tun:

StringRequest myReq = new StringRequest(Method.POST,
                                        "http://somesite.com/some_endpoint.php",
                                        createMyReqSuccessListener(),
                                        createMyReqErrorListener()) {

    protected Map<String, String> getParams() throws com.android.volley.AuthFailureError {
        Map<String, String> params = new HashMap<String, String>();
        params.put("param1", num1);
        params.put("param2", num2);
        return params;
    };
};
queue.add(myReq);

zB um die getParams()Methode einfach zu überschreiben .

Ein Arbeitsbeispiel (zusammen mit vielen anderen grundlegenden Volley-Beispielen) finden Sie im Projekt Andorid Volley Examples .

Ognyan
quelle
Ich bin Ihren Beispielen von Volley gefolgt. Bisher ist es der hilfreichste Volly-Code, aber ich habe ein Problem mit JsonObjectRequest. Ich habe die alte Antwort in createMyReqSuccessListener erhalten, bis ich sie erneut installiere. Befinden sich Volley-Speicherdaten im Cache? Bitte schlagen Sie einen Weg vor, dies zu tun.
SkyWalker
2
Es werden nur Bilder zwischengespeichert. Bitte überprüfen Sie, ob ein Proxy Ihre Anfragen abfängt. Wenn die Anforderungen genau dieselbe URL haben und der Proxy möglicherweise einfach das erste Ergebnis zurückgibt.
Ognyan
2
Für Firefox gibt es ein Plugin namens "HTTP-Ressourcentest", mit dem Sie Anforderungen an den Webserver senden können. Es ist sehr nützlich, um solche Fälle zu testen. Geben Sie einfach Ihre URL (und ggf. die POST-Parameter) ein und sehen Sie, wie der Server auf mehrere aufeinanderfolgende Anforderungen reagiert. Wenn Sie erneut das gleiche Antwortergebnis erhalten, wird es höchstwahrscheinlich zwischengespeichert. In diesem Fall können Sie die zurückgegebenen Header untersuchen, um zu überprüfen, ob Proxy-Header vorhanden sind. Über den "No-Cache" - ja, es sollte funktionieren.
Ognyan
2
Ich schlage vor, dass Sie eine separate Frage öffnen, damit andere beitreten und helfen können. Bitte geben Sie an, welchen Stack Sie mit HURL oder HttpClient verwenden, auch mit der Android-Version, gegen die Sie testen. Bitte setzen Sie hier einen Link zu der neuen Frage, damit die Leute der Diskussion folgen können.
Ognyan
3
@Yousif Wahrscheinlich erhalten Sie viel bessere Antworten, wenn Sie dies als neue Frage stellen, aber kurz gesagt: Mit der POST-Anfrage können Sie Dateien und andere größere Daten senden, die nicht in die GET-Anfrage passen. Außerdem besteht bei Verwendung der GET-Anforderung ein Sicherheitsrisiko, da die URL möglicherweise auf dem Server protokolliert wird, wodurch vertrauliche Daten verfügbar gemacht werden.
Ognyan
23

CustomRequest ist eine Möglichkeit, das JSONObjectRequest des Volleys zu lösen. Es können keine Parameter wie das veröffentlicht werden StringRequest

Hier ist die Hilfsklasse, mit der Parameter hinzugefügt werden können:

    import java.io.UnsupportedEncodingException;
    import java.util.Map;    
    import org.json.JSONException;
    import org.json.JSONObject;    
    import com.android.volley.NetworkResponse;
    import com.android.volley.ParseError;
    import com.android.volley.Request;
    import com.android.volley.Response;
    import com.android.volley.Response.ErrorListener;
    import com.android.volley.Response.Listener;
    import com.android.volley.toolbox.HttpHeaderParser;

    public class CustomRequest extends Request<JSONObject> {

    private Listener<JSONObject> listener;
    private Map<String, String> params;

    public CustomRequest(String url, Map<String, String> params,
            Listener<JSONObject> reponseListener, ErrorListener errorListener) {
        super(Method.GET, url, errorListener);
        this.listener = reponseListener;
        this.params = params;
    }

    public CustomRequest(int method, String url, Map<String, String> params,
            Listener<JSONObject> reponseListener, ErrorListener errorListener) {
        super(method, url, errorListener);
        this.listener = reponseListener;
        this.params = params;
    }

    protected Map<String, String> getParams()
            throws com.android.volley.AuthFailureError {
        return params;
    };

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            return Response.success(new JSONObject(jsonString),
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }

    @Override
    protected void deliverResponse(JSONObject response) {
        // TODO Auto-generated method stub
        listener.onResponse(response);
    }

}

danke an Greenchiu

LOG_TAG
quelle
@ WarrenFaith Danke für den Hinweis, ich habe die Antwort aktualisiert!
LOG_TAG
3
Vielen Dank, ich habe stundenlang gesucht, bevor ich diese Lösung erhalten habe. Es ist so seltsam, dass das Überschreiben der JSONObjectReuqest- getParams()Funktion nicht funktioniert.
Walid Ammar
@MohammadWalid FYI lesen Sie diese stackoverflow.com/questions/16902716/… und versuchen Sie, Nachrüstung zu verwenden! Sowohl Volleyball als auch Nachrüstung können mit okhttp verwendet werden!
LOG_TAG
Ich habe diese Lösung ausprobiert, aber bei mir nicht funktioniert. getParams () wird nicht aufgerufen.
Mahdi
10

Diese Hilfsklasse verwaltet Parameter für GET- und POST- Anforderungen:

import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;    

import org.json.JSONException;
import org.json.JSONObject;

import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;

public class CustomRequest extends Request<JSONObject> {
    private int mMethod;
    private String mUrl;
    private Map<String, String> mParams;
    private Listener<JSONObject> mListener;

    public CustomRequest(int method, String url, Map<String, String> params,
            Listener<JSONObject> reponseListener, ErrorListener errorListener) {
        super(method, url, errorListener);
        this.mMethod = method;
        this.mUrl = url;
        this.mParams = params;
        this.mListener = reponseListener;
    }

@Override
public String getUrl() {
    if(mMethod == Request.Method.GET) {
        if(mParams != null) {
            StringBuilder stringBuilder = new StringBuilder(mUrl);
            Iterator<Map.Entry<String, String>> iterator = mParams.entrySet().iterator();
            int i = 1;
            while (iterator.hasNext()) {
                Map.Entry<String, String> entry = iterator.next();
                if (i == 1) {
                    stringBuilder.append("?" + entry.getKey() + "=" + entry.getValue());
                } else {
                    stringBuilder.append("&" + entry.getKey() + "=" + entry.getValue());
                }
                iterator.remove(); // avoids a ConcurrentModificationException
                i++;
            }
            mUrl = stringBuilder.toString();
        }
    }
    return mUrl;
}

    @Override
    protected Map<String, String> getParams()
            throws com.android.volley.AuthFailureError {
        return mParams;
    };

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            return Response.success(new JSONObject(jsonString),
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }

    @Override
    protected void deliverResponse(JSONObject response) {
        // TODO Auto-generated method stub
        mListener.onResponse(response);
    }
}
Andrea Motto
quelle
Dies löst das Hinzufügen von Parametern zur GET-Methode. Vielen Dank!
Karkar
2
In unserem Fall hat der Iterator-Ansatz das ursprüngliche Map-Parameter-Objekt zerstört, das wir an die Funktion übergeben haben. Scheint, als würde Volley GetUrlmehrmals intern anrufen . Am Ende hatten wir einen klassischen foreach-Ansatz, der in einer separaten Antwort veröffentlicht wurde. Hoffe das hilft wer hier landet. :)
Paolo Casciello
Wie man diese
Hilfsklasse aufruft,
@kgandroid, erstellen Sie eine Map <String, String> mit Ihren Schlüsseln und Werten. Beispiel: Map <String, String> params = new HashMap <String, String> (); params.put ("param1", "value1"); params.put ("param2", "value2"); params.put ("param3", "value3");
Andrea Motto
6

Umgang mit GET- Parametern Ich habe die Lösung von Andrea Motto wiederholt. Das Problem war, dass Volley anriefGetUrl mehrmals anrief und seine Lösung mit einem Iterator das ursprüngliche Kartenobjekt zerstörte. Die nachfolgenden internen Volley-Aufrufe hatten ein leeres params-Objekt.

Ich habe auch die Kodierung der Parameter hinzugefügt.

Dies ist eine Inline-Verwendung (keine Unterklasse).

public void GET(String url, Map<String, String> params, Response.Listener<String> response_listener, Response.ErrorListener error_listener, String API_KEY, String stringRequestTag) {
    final Map<String, String> mParams = params;
    final String mAPI_KEY = API_KEY;
    final String mUrl = url;

    StringRequest stringRequest = new StringRequest(
            Request.Method.GET,
            mUrl,
            response_listener,
            error_listener
    ) {
        @Override
        protected Map<String, String> getParams() {
            return mParams;
        }

        @Override
        public String getUrl() {
            StringBuilder stringBuilder = new StringBuilder(mUrl);
            int i = 1;
            for (Map.Entry<String,String> entry: mParams.entrySet()) {
                String key;
                String value;
                try {
                    key = URLEncoder.encode(entry.getKey(), "UTF-8");
                    value = URLEncoder.encode(entry.getValue(), "UTF-8");
                    if(i == 1) {
                        stringBuilder.append("?" + key + "=" + value);
                    } else {
                        stringBuilder.append("&" + key + "=" + value);
                    }
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                i++;

            }
            String url = stringBuilder.toString();

            return url;
        }

        @Override
        public Map<String, String> getHeaders() {
            Map<String, String> headers = new HashMap<>();
            if (!(mAPI_KEY.equals(""))) {
                headers.put("X-API-KEY", mAPI_KEY);
            }
            return headers;
        }
    };

    if (stringRequestTag != null) {
        stringRequest.setTag(stringRequestTag);
    }

    mRequestQueue.add(stringRequest);
}

Diese Funktion verwendet Header, um einen APIKEY zu übergeben, und setzt einen TAG auf die Anforderung, die nützlich ist, um sie vor ihrem Abschluss abzubrechen.

Hoffe das hilft.

Paolo Casciello
quelle
3

Dies kann Ihnen helfen ...

private void loggedInToMainPage(final String emailName, final String passwordName) {

    String tag_string_req = "req_login";
    StringRequest stringRequest = new StringRequest(Request.Method.POST, "http://localhost/index", new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            Log.d(TAG, "Login Response: " + response.toString());
            try {
                JSONObject jsonObject = new JSONObject(response);
                Boolean error = jsonObject.getBoolean("error");
                if (!error) {

                    String uid = jsonObject.getString("uid");
                    JSONObject user = jsonObject.getJSONObject("user");
                    String email = user.getString("email");
                    String password = user.getString("password");


                    session.setLogin(true);
                    Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                    startActivity(intent);
                    finish();
                    Toast.makeText(getApplicationContext(), "its ok", Toast.LENGTH_SHORT).show();
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError volleyError) {
            System.out.println("volley Error .................");
        }
    }) {
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            Map<String, String> params = new HashMap<String, String>();
            params.put("tag", "login");
            params.put("email", emailName);
            params.put("password", passwordName);
            return params;
        }
    };


    MyApplication.getInstance().addToRequestQueue(stringRequest,tag_string_req);
}
Mahbod
quelle
3

Für zukünftige Leser

Ich liebe es mit Volley zu arbeiten . Um Entwicklungszeit zu sparen, habe ich versucht, eine kleine handliche Bibliothek Gloxey Netwok Manager zu schreiben, um Volley mit meinem Projekt einzurichten . Es enthält JSON-Parser und verschiedene andere Methoden zur Überprüfung der Netzwerkverfügbarkeit.

Verwendung, ConnectionManager.classbei der verschiedene Methoden für Volley String- und Volley JSON- Anforderungen verfügbar sind. Sie können GET, PUT, POST, DELETE mit oder ohne Header anfordern . Die vollständige Dokumentation finden Sie hier .

Fügen Sie diese Zeile einfach in Ihre Gradle-Datei ein.

  dependencies { 

       compile 'io.gloxey.gnm:network-manager:1.0.1'
   }

Volley StringRequest

Methode GET (ohne Header)

    ConnectionManager.volleyStringRequest(context, isDialog, progressDialogView, requestURL, volleyResponseInterface);

Wie benutzt man?

     Configuration                Description

     Context                      Context 
     isDialog                     If true dialog will appear, otherwise not.
     progressView                 For custom progress view supply your progress view id and make isDialog true. otherwise pass null. 
     requestURL                   Pass your API URL.  
     volleyResponseInterface      Callback for response.  

Beispiel

    ConnectionManager.volleyStringRequest(this, false, null, "url", new VolleyResponse() {
    @Override
    public void onResponse(String _response) {

        /**
         * Handle Response
         */
    }

    @Override
     public void onErrorResponse(VolleyError error) {

        /**
         * handle Volley Error
         */
    }

    @Override
    public void isNetwork(boolean connected) {

        /**
         * True if internet is connected otherwise false
         */
    }
});

Volley StringRequest

Methode POST / PUT / DELETE (ohne Header)

    ConnectionManager.volleyStringRequest(context, isDialog, progressDialogView, requestURL, requestMethod, params, volleyResponseInterface);

Beispiel

Use Method : Request.Method.POST
             Request.Method.PUT
             Request.Method.DELETE

Your params : 

HashMap<String, String> params = new HashMap<>();
params.put("param 1", "value");
params.put("param 2", "value");

ConnectionManager.volleyStringRequest(this, true, null, "url", Request.Method.POST, params, new VolleyResponse() {
    @Override
    public void onResponse(String _response) {

        /**
         * Handle Response
         */
    }

    @Override
    public void onErrorResponse(VolleyError error) {

        /**
         * handle Volley Error
         */
    }

    @Override
    public void isNetwork(boolean connected) {

        /**
         * True if internet is connected otherwise false
         */
    }
});

Bonus

Gloxey JSON Parser

Fühlen Sie sich frei, Gloxey JSON Parser zu verwenden, um Ihre API-Antwort zu analysieren.

  YourModel yourModel = GloxeyJsonParser.getInstance().parse(stringResponse, YourModel.class);

Beispiel

ConnectionManager.volleyStringRequest(this, false, null, "url", new VolleyResponse() {
    @Override
    public void onResponse(String _response) {

        /**
         * Handle Response
         */

         try {

          YourModel yourModel = GloxeyJsonParser.getInstance().parse(_response, YourModel.class);

            } catch (Exception e) {
                e.printStackTrace();
            }

    }

    @Override
     public void onErrorResponse(VolleyError error) {

        /**
         * handle Volley Error
         */
         if (error instanceof TimeoutError || error instanceof NoConnectionError) {

                showSnackBar(parentLayout, getString(R.string.internet_not_found), getString(R.string.retry), new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {

                     //handle retry button

                    }
                });

            } else if (error instanceof AuthFailureError) {
            } else if (error instanceof ServerError) {
            } else if (error instanceof NetworkError) {
            } else if (error instanceof ParseError) {
            }

    }

    @Override
    public void isNetwork(boolean connected) {

        /**
         * True if internet is connected otherwise false
         */
          if (!connected) {
                showSnackBar(parentLayout, getString(R.string.internet_not_found), getString(R.string.retry), new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        //Handle retry button
                    }
                });
    }
});


     public void showSnackBar(View view, String message) {
            Snackbar.make(view, message, Snackbar.LENGTH_LONG).show();
     }

     public void showSnackBar(View view, String message, String actionText, View.OnClickListener onClickListener) {
            Snackbar.make(view, message, Snackbar.LENGTH_LONG).setAction(actionText, onClickListener).show();
     }
Adnan Bin Mustafa
quelle
Aber unterstützt es Method.Get
David Kariuki
Ja, bitte schauen Sie nach Details. github.com/adnanbinmustafa/Gloxey-Network-Manager
Adnan Bin Mustafa
0

Um POSTParameter bereitzustellen , senden Sie Ihren Parameter wie JSONObject in an den JsonObjectRequestKonstruktor. Der dritte Parameter akzeptiert a JSONObject, das im Anforderungshauptteil verwendet wird.

JSONObject paramJson = new JSONObject();

paramJson.put("key1", "value1");
paramJson.put("key2", "value2");


JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST,url,paramJson,
    new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {

        }
    },
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {

        }
    });
requestQueue.add(jsonObjectRequest);
Abu Yousuf
quelle